https://m.hanbit.co.kr/store/books/book_view.html?p_code=B3450156021
์ด ๊ธ์ ์ฑ
'๋๋ฅผ ์๊ทนํ๋ ์๊ณ ๋ฆฌ์ฆ' ์์ ๋ฐฐ์ด ๋ด์ฉ์ ์ ๊ทน ์ฐธ๊ณ ํ๊ณ ์์ต๋๋ค.
๋ํ, ๋ชจ๋ ์๋ฃ๊ตฌ์กฐ ๋ฐ ์๊ณ ๋ฆฌ์ฆ์ Swift๋ก ๊ตฌํํ๊ณ ์์์ ๋จผ์ ์๋ฆฝ๋๋ค.
* ์ด์ ํฌ์คํ ๊ณผ ์ด์ด์ง๋๋ค!
[DataStructure] ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ Swift๋ก ๊ตฌํํ๊ธฐ
https://m.hanbit.co.kr/store/books/book_view.html?p_code=B3450156021 ์ด ๊ธ์ ์ฑ '๋๋ฅผ ์๊ทนํ๋ ์๊ณ ๋ฆฌ์ฆ' ์์ ๋ฐฐ์ด ๋ด์ฉ์ ์ ๊ทน ์ฐธ๊ณ ํ๊ณ ์์ต๋๋ค. ๋ํ, ๋ชจ๋ ์๋ฃ๊ตฌ์กฐ ๋ฐ ์๊ณ ๋ฆฌ์ฆ์ Swift๋ก ๊ตฌํํ๊ณ ์์์
bpeeper.tistory.com
0. ์๋ก
Single Linked List๋ ํน์ ๋
ธ๋์ ์ด์ ๋
ธ๋๋ค์ ๋ํ ์ ๊ทผ์ด ๋ถํธํ์์ต๋๋ค.
์ด๋ก ์ธํด ๋
ธ๋์ ์ฝ์
์ด๋ ์ญ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋๊ฒ๋ ์กฐ๊ธ ๋ต๋ตํ ๋ฉด์ด ์์์ง์.
์๋ฅผ๋ค์ด n๋ฒ์งธ ๋
ธ๋๋ฅผ ์ญ์ ํ๊ณ ์ถ๋ค๋ฉด, n-1๋ฒ์งธ ๋
ธ๋์ ์ ๊ทผํ์ฌ nextNode๋ก n๋ฒ์งธ ๋
ธ๋๋ฅผ ์ญ์ ํ๋ ๋ฑ ๋ง์ด์ฃ !
์ด๋ฐ ๋จ์ ์ ์ด๋ป๊ฒ ํด์ํ ์ ์์๊น์? ์ด์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํจ์ผ๋ก์จ ํด๊ฒฐํ ์ ์์๊ฒ ๊ฐ์ง ์๋์?
1. ๊ตฌ์กฐ์ ์
์ด์ค ๋งํฌ๋ ๋ฆฌ์คํธ(Doubly Linked List)์ ๊ฐ ๋
ธ๋๋ค์ ์ด์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํ๋กํผํฐ Prev๋ฅผ ํตํด ์ด์ ๋
ธ๋์ ์ ๊ทผํ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๋
ธ๋๋ค์ ๋๋ค์ ์ฃผ๋ ์ฃผ๋ ์ฐ๊ฒฐํ์ฌ Linked List๋ฅผ ํ์ฑํ๋ ๊ฒ์ผ๋ก, ๋๋ธ๋ฆฌ ๋งํฌ๋ ๋ฆฌ์คํธ๊ฐ ์์ฑ๋ฉ๋๋ค.
์ด์ ์ด ๊ตฌ์กฐ์ ์ฝ์
- ์ญ์ - ํ์์ Swift๋ก ๊ตฌํํ๋๋ก ํ์ฃ .
2. ๊ตฌํ
์ด์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง ์๋ก์ด ํด๋์ค๋ฅผ ์ ์๋ก ์์ํด๋ณด๊ฒ ์ต๋๋ค.
class DoublyNode<T>{
var prevNode: DoublyNode<T>?
var nextNode: DoublyNode<T>?
var data: T?
init(prevNode: DoublyNode<T>? = nil, nextNode: DoublyNode<T>? = nil, data: T? = nil) {
self.prevNode = prevNode
self.nextNode = nextNode
self.data = data
}
prevNode ํ๋กํผํฐ๋ ์ด์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฐ ํ๋กํผํฐ๋ฅผ ์ด๊ธฐํํ๋ ์์ฑ์๋ ๋ง๋ค์ด ๋์์ต๋๋ค.
3. ์ฝ์
///๋ฆฌ์คํธ์ ์ฒ์์ ๋
ธ๋ ์ถ๊ฐ
@discardableResult
func insertAtFirst(_ newNode: DoublyNode<T>)->DoublyNode<T>{
if self.head == nil{
self.head = newNode
return newNode
}
self.head?.prevNode = newNode
newNode.nextNode = self.head
self.head = newNode
return newNode
}
///๋ฆฌ์คํธ๋ด ํน์ ์์น์ ๋
ธ๋ ์ถ๊ฐ
@discardableResult
func InsertNodeAt(_ newNode:DoublyNode<T>, _ idx: Int) -> DoublyNode<T>?{
if self.head == nil { return nil}
var currentNode = self.head
for _ in 0..<idx{
if currentNode == nil {return nil}
currentNode = currentNode?.nextNode
}
if currentNode?.prevNode == nil{
self.head = newNode
}
currentNode?.prevNode = newNode
newNode.nextNode = currentNode
newNode.prevNode = nil
return newNode
}
///๋ฆฌ์คํธ์ ๊ฐ์ฅ ๋ง์ง๋ง์ ๋
ธ๋๋ฅผ ์ถ๊ฐ
@discardableResult
func appendNode(_ newNode: DoublyNode<T>)->DoublyNode<T>{
if self.head == nil {
self.head = newNode
return newNode
}
var tail = self.head
while(tail?.nextNode != nil){
tail = tail?.nextNode
}
newNode.nextNode = tail?.nextNode
newNode.prevNode = tail
tail?.nextNode = newNode
return newNode
}
์ถ๊ฐํ ์์น๊น์ง ๋ฐ๋ณต๋ฌธ์ ํตํด ๋๋ฌํ ๋ค, ํด๋น ์์น์ ๋ ธ๋๋ฅผ ์ ๋ ธ๋์ nextNode์, ์ด์ ๋ ธ๋๋ฅผ prevNode์ ์ ์ฅํฉ๋๋ค.
3. ์ญ์
///๋ฆฌ์คํธ์ ๊ฐ์ฅ ๋ง์ง๋ง์ ๋
ธ๋๋ฅผ ์ญ์
@discardableResult
func removeLast()->DoublyNode<T>?{
if self.head == nil {
return nil
}
var tail = self.head
while(tail?.nextNode != nil){
tail = tail?.nextNode
}
tail?.prevNode?.nextNode = nil
tail?.prevNode = nil
return tail
}
///๋ฆฌ์คํธ์ ์ฒ์ ๋
ธ๋๋ฅผ ์ญ์
@discardableResult
func removeFirst()->DoublyNode<T>?{
if self.head == nil{
return nil
}
var removeNode = self.head
self.head = self.head?.nextNode
self.head?.prevNode = nil
return removeNode
}
///๋ฆฌ์คํธ์ ํน์ ์์น ๋
ธ๋๋ฅผ ์ญ์
@discardableResult
func removeAt(_ idx: Int)->DoublyNode<T>?{
if self.head == nil {return nil}
var removeNode = self.head
for _ in 0..<idx{
if removeNode?.nextNode == nil {return nil}
removeNode = removeNode?.nextNode
}
if removeNode?.prevNode == nil { self.head = removeNode?.nextNode}
removeNode?.prevNode?.nextNode = removeNode?.nextNode
removeNode?.nextNode?.prevNode = removeNode?.prevNode
removeNode?.prevNode = nil
removeNode?.nextNode = nil
return removeNode
}
ํน์ ๋ ธ๋๊น์ง ์ด๋ํ ํ ๋ ธ๋์ ํ๋กํผํฐ๋ฅผ ๋น์์ฃผ๊ณ , ์ด์ ๋ ธ๋์ ๋ค์ ๋ ธ๋์ ์ ์ฅ์ ๋์ด์ฃผ๋ฉด ARC๋งจ์ด ์ฒ๋ฆฌํด์ค๋๋ค!
4. ํ์
///๋ฆฌ์คํธ๋ด ํน์ ์์น์ ๋
ธ๋ ๋ฐํ
@discardableResult
func getNodeAt(_ idx: Int) -> DoublyNode<T>?{
if self.head == nil { return nil}
var currentNode = self.head
for _ in 0..<idx{
if currentNode == nil {return nil}
currentNode = currentNode?.nextNode
}
return currentNode
}
5. ๊ฒฐ๋ก
์ ์ ์ฝ๋๊ฐ ์ฌ์ ํ ๋ชจ๋ ์์
์์ n๋ฒ์ ๋ฐ๋ณต์ ์ํํ๊ณ ์๋๊ฒ์ ๋์น์ฑ์
จ๋์?
์ฑ๊ธ์ด๋ ๋๋ธ์ด๋, ๋งํฌ๋ ๋ฆฌ์คํธ๋ O(n)์ ํ๊ณ์์ ๋ฒ์ด๋์ง ๋ชปํ๋๊ตฐ์,,
์ฝ๋ฉ ๊ณ ์๋ถ๋ค์ด ์์ฑํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋ฆฌ์คํธ๋ ์ด๋ป๊ฒ ๊ตฌํ๋์ด์๋์ง ์ดํด๋ณด๋๊ฒ๋ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค!
ํด๋น ๋ด์ฉ์..! ๋ค์ ํฌ์คํ
์์ ๋ค๋ฃฐ ๋งํฌ๋ ๋ฆฌ์คํธ ์๋ฆฌ์ฆ์ ๋ง์ง๋ง, ํํ ๋งํฌ๋ ๋ฆฌ์คํธ์์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
6. ๋ถ๋ก
์ด๋ฒ ๋ถ๋ก์์๋,,!
์ฑ
์ 'Vitamin Quiz, ๋๋ธ ๋งํฌ๋ ๋ฆฌ์คํธ์ ๋ฐ์ดํฐ๋ฅผ ์ญ์์ผ๋ก ์ถ๋ ฅํ๋ ํจ์๋ฅผ ์์ฑํด ๋ณด์ธ์'๋ฅผ ๊ตฌํํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ ๋ ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํด์ ๊ตฌํํด๋ณด๋ ค๊ณ ํด์! ์ด๊ฒ์ด ์ ๋ต์ ์๋๋ฉฐ, ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์ ์ ์๊ฒ ์ต๋๋ค.
๋ฐ์ดํฐ์ ์ถ๋ ฅ์ ๋
ธ๋์ ์ ๊ทผํ์ฌ data ํ๋กํผํฐ์ ์ ๊ทผํจ์ผ๋ก์จ ํด๊ฒฐํ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ค์ ์ด์ ๋
ธ๋๋ก ๋๋์๊ฐ๊ณ , ์๊ธฐ ํ๋์ ์ฒซ ๋
ธ๋๊น์ง ๋ฐ๋ณต ์ํํ๋ฉด ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ์ถ๋ ฅํ ์ ์๊ฒ ๊ตฐ์!
ํ์ฌ DoublyLinkedList ํด๋์ค๋ ๋ง์ง๋ง ๋
ธ๋์ ๋ํ ์ ๋ณด๋ฅผ ์ง์ ์ ์ผ๋ก ๊ฐ์ง๊ณ ์์ง ์๋ค๋ ์ ๋ ์ฐธ๊ณ ํด์ผ ํ ์ฌํญ์
๋๋ค.
์ด๋ฅผ ํ ๋๋ก, ํจ์์ ๋ก์ง์ ์์๋๋ก ๋์ดํ๋ฉด,
- ๋ฆฌ์คํธ์ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ๋ฐ๋ณต๋ฌธ์ผ๋ก ์ ๊ทผํ๋ค.
- ํ์ฌ ๋ ธ๋์ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ๋ค.
- ํ์ฌ ๋ ธ๋์ ์ด์ ๋ ธ๋๋ฅผ ํ์ฌ ๋ ธ๋๋ก ๋ณ๊ฒฝํ๋ค.
- ์ด์ ๋
ธ๋๊ฐ nil์ด ์๋๋ผ๋ฉด, ๊ณผ์ 2๋ก ๋์๊ฐ๋ค.
(ํ์ ํฌ์คํ ํ ์คํ์ ์ฌ์ฉํ๋ค๋ฉด 1์ ๊ณผ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์๊ณ , ์ด๋ฅผ ์ถ๋ ฅํ๋ฉด ๊ฐ๋จํ ํด๊ฒฐํ ์ ์๋ค๋ ์คํฌ์ผ๋ฌ๋ฅผ ์ ์ ใ ใ ..)
์ ๊ณผ์ ์ ์ฝ๋๋ก ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
///๋ฆฌ์คํธ ๋ด์ ๋
ธ๋๋ฅผ ์ญ์์ผ๋ก ๊ฐ ๋
ธ๋์ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅ
func printReverse(){
if self.head == nil{
print("\(type(of: self)) is empty")
}
var currentNode = self.head
while currentNode?.nextNode != nil{
currentNode = currentNode?.nextNode
}
while currentNode != nil{
print("\(currentNode?.data)",terminator: " ")
if currentNode?.prevNode != nil{
print("->", terminator: " ")
}
currentNode = currentNode?.prevNode
}
}
์์ค์ฝ๋ ์ ๋ฌธ
//
// DoublyLinkedList.swift
// Swift-Practice
//
// Created by Yune gim on 2024/03/21.
//
///๋๋ธ ๋งํฌ๋ ๋ฆฌ์คํธ, ํน์ ๋
ธ๋๋ ์ด์ ๋
ธ๋์ ์ดํ ๋
ธ๋์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
class DoublyLinkedList<T:Equatable>{
var head: DoublyNode<T>?
///๋ฆฌ์คํธ์ ์ฒ์์ ๋
ธ๋ ์ถ๊ฐ
@discardableResult
func insertAtFirst(_ newNode: DoublyNode<T>)->DoublyNode<T>{
if self.head == nil{
self.head = newNode
return newNode
}
self.head?.prevNode = newNode
newNode.nextNode = self.head
self.head = newNode
return newNode
}
///๋ฆฌ์คํธ๋ด ํน์ ์์น์ ๋
ธ๋ ์ถ๊ฐ
@discardableResult
func InsertNodeAt(_ newNode:DoublyNode<T>, _ idx: Int) -> DoublyNode<T>?{
if self.head == nil { return nil}
var currentNode = self.head
for _ in 0..<idx{
if currentNode == nil {return nil}
currentNode = currentNode?.nextNode
}
if currentNode?.prevNode == nil{
self.head = newNode
}
currentNode?.prevNode = newNode
newNode.nextNode = currentNode
newNode.prevNode = nil
return newNode
}
///๋ฆฌ์คํธ์ ๊ฐ์ฅ ๋ง์ง๋ง์ ๋
ธ๋๋ฅผ ์ถ๊ฐ
@discardableResult
func appendNode(_ newNode: DoublyNode<T>)->DoublyNode<T>{
if self.head == nil {
self.head = newNode
return newNode
}
var tail = self.head
while(tail?.nextNode != nil){
tail = tail?.nextNode
}
newNode.nextNode = tail?.nextNode
newNode.prevNode = tail
tail?.nextNode = newNode
return newNode
}
///๋ฆฌ์คํธ์ ๊ฐ์ฅ ๋ง์ง๋ง์ ๋
ธ๋๋ฅผ ์ญ์
@discardableResult
func removeLast()->DoublyNode<T>?{
if self.head == nil {
return nil
}
var tail = self.head
while(tail?.nextNode != nil){
tail = tail?.nextNode
}
tail?.prevNode?.nextNode = nil
tail?.prevNode = nil
return tail
}
///๋ฆฌ์คํธ์ ์ฒ์ ๋
ธ๋๋ฅผ ์ญ์
@discardableResult
func removeFirst()->DoublyNode<T>?{
if self.head == nil{
return nil
}
var removeNode = self.head
self.head = self.head?.nextNode
self.head?.prevNode = nil
return removeNode
}
///๋ฆฌ์คํธ์ ํน์ ์์น ๋
ธ๋๋ฅผ ์ญ์
@discardableResult
func removeAt(_ idx: Int)->DoublyNode<T>?{
if self.head == nil {return nil}
var removeNode = self.head
for _ in 0..<idx{
if removeNode?.nextNode == nil {return nil}
removeNode = removeNode?.nextNode
}
if removeNode?.prevNode == nil { self.head = removeNode?.nextNode}
removeNode?.prevNode?.nextNode = removeNode?.nextNode
removeNode?.nextNode?.prevNode = removeNode?.prevNode
removeNode?.prevNode = nil
removeNode?.nextNode = nil
return removeNode
}
///๋ฆฌ์คํธ๋ด ํน์ ์์น์ ๋
ธ๋ ๋ฐํ
@discardableResult
func getNodeAt(_ idx: Int) -> DoublyNode<T>?{
if self.head == nil { return nil}
var currentNode = self.head
for _ in 0..<idx{
if currentNode == nil {return nil}
currentNode = currentNode?.nextNode
}
return currentNode
}
///๋ฆฌ์คํธ ๋ด์ ๋
ธ๋ ์๋ฅผ ๋ฐํ
func getNodeCount()->Int{
if self.head == nil {return 0}
var count = 0
var currentNode = self.head
while(currentNode != nil){
print("\(currentNode!.data!)",terminator: "")
count += 1
currentNode = currentNode?.nextNode
if currentNode != nil { print(" -> ",terminator: "")}
}
print()
return count
}
///๋ฆฌ์คํธ ๋ด์ ๋
ธ๋๋ฅผ ์ญ์์ผ๋ก ๊ฐ ๋
ธ๋์ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅ
func printReverse(){
if self.head == nil{
print("\(type(of: self)) is empty")
}
var currentNode = self.head
while currentNode?.nextNode != nil{
currentNode = currentNode?.nextNode
}
while currentNode != nil{
print("\(currentNode?.data)",terminator: " ")
if currentNode?.prevNode != nil{
print("->", terminator: " ")
}
currentNode = currentNode?.prevNode
}
}
}
'learnings > Algorithm&DS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DataStructure] ํ 1๋ถ (1) | 2024.05.01 |
---|---|
[DataStructure] ์คํ (1) | 2024.05.01 |
[Algorithm] ์ฐจ๋๊ธฐ์ง ์๊ณ ๋ฆฌ์ฆ, ์คํ์ ์ฌ์ฉํ์ฌ ์ค์ ํ๊ธฐ๋ฒ์ ํ์ ํ๊ธฐ๋ฒ์ผ๋ก ๋ณํ (0) | 2024.04.05 |
[DataStructure] ํํ ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ Swift๋ก ๊ตฌํํ๊ธฐ (0) | 2024.03.26 |
[DataStructure] ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ Swift๋ก ๊ตฌํํ๊ธฐ (0) | 2024.03.20 |