๊ธ์ ์ฑ
'๋๋ฅผ ์๊ทนํ๋ ์๊ณ ๋ฆฌ์ฆ' ์์ ๋ฐฐ์ด ๋ด์ฉ์ ์ ๊ทน ์ฐธ๊ณ ํ๊ณ ์์ต๋๋ค.
๋ํ, ๋ชจ๋ ์๋ฃ๊ตฌ์กฐ ๋ฐ ์๊ณ ๋ฆฌ์ฆ์ Swift๋ก ๊ตฌํํ๊ณ ์์์ ๋จผ์ ์๋ฆฝ๋๋ค.
๋๋ฅผ ์๊ทนํ๋ ์๊ณ ๋ฆฌ์ฆ
ํ๋ก๊ทธ๋๋จธ์๊ฒ ์๋ฃ๊ตฌ์กฐ, ์๊ณ ๋ฆฌ์ฆ์ ์ฐ๊ณผ ๊ฐ๋ค. ๋์ด์ผ ํ๋ค๋ ๊ฒ์ ์๊ธฐ์ ์ค๋ฅด๊ณ ๋ ์ค๋ฅด์ง๋ง, ์ ์์ ๋ฐ๊ธฐ๋ ์ฝ์ง ์๋ค. ๋ฐฐ์ฐ๊ธฐ๊ฐ ์ด๋ ต๊ณ ์ฌ๋ฏธ๋ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ๋ง์ ํ๋ก๊ทธ๋๋จธ๊ฐ
m.hanbit.co.kr
* ์ด์ ํฌ์คํ ๊ณผ ์ด์ด์ง๋๋ค!
[DataStructure] ์ด์ค ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ Swift๋ก ๊ตฌํํ๊ธฐ
https://m.hanbit.co.kr/store/books/book_view.html?p_code=B3450156021 ์ด ๊ธ์ ์ฑ '๋๋ฅผ ์๊ทนํ๋ ์๊ณ ๋ฆฌ์ฆ' ์์ ๋ฐฐ์ด ๋ด์ฉ์ ์ ๊ทน ์ฐธ๊ณ ํ๊ณ ์์ต๋๋ค. ๋ํ, ๋ชจ๋ ์๋ฃ๊ตฌ์กฐ ๋ฐ ์๊ณ ๋ฆฌ์ฆ์ Swift๋ก ๊ตฌํํ๊ณ ์์์
bpeeper.tistory.com
0. ์๋ก
๋ฆฌ์คํธ ์ฒ์์ ๋
ธ๋๋ฅผ ์ฝ์
ํ๊ฑฐ๋ ์ญ์ ํ๋ ๊ฒ ์ฒ๋ผ, ๋ฆฌ์คํธ ๋์ ์๋ ๋
ธ๋๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ํ ๋ O(1)์ ์์์๊ฐ์ผ๋ก ์ฒ๋ฆฌ๋ ์ ์๋ค๋ฉด ๋ง์ ๋น์ฉ์ ์ค์ผ ์ ์์๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ ์ ์ ์์ผ์ ๊ฐ์?
์ด์ ํฌ์คํ
์ Vitamin ๋ฌธ์ ์์ ๋ค๋ค๋ '๋ฆฌ์คํธ ์ญ์ ์ถ๋ ฅ' ๊ฐ์ ๊ฒฝ์ฐ์๋, ๋ง์ง๋ง ๋
ธ๋๊น์ง ์ ๊ทผํด์ผ ํ๋ ๋น์ฉ์ด ๋ฐ์ํฉ๋๋ค!
(์คํ์ ์ฌ์ฉํ์ง ์๋๋ค๋ ์ ์ ํ์ ๋ง์ ๋๋ฆฌ๊ณ ์์ต๋๋ค,,)
์ด์ ๋๊ฐ ๋๋ํ์์ต๋๋ค.
๋ฆฌ์คํธ์ head ํ๋กํผํฐ ์ฒ๋ผ, ๋ง์ง๋ง ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ tail ํ๋กํผํฐ์ ๋ํด ์๊ฐํด๋ณผ ๋๊ฐ!
ํน์ ์ฐ๋ก๋ณด๋ก์ค๋ฅผ ์๊ณ ๊ณ์๋์? ์์ ์ ๊ผฌ๋ฆฌ๋ฅผ ์ผํค๊ณ ์๋ ๋ชจ์์ด ๋ง์น ์ค๋ ์์๋ณผ ํํ ๋งํฌ๋ ๋ฆฌ์คํธ ๊ฐ๊ตฐ์!
1. ๊ตฌ์กฐ์ ์
์ฒซ ๋
ธ๋๊ฐ ๋ง์ง๋ง ๋
ธ๋๊ฐ ์ฒซ ๋
ธ๋์ ์ฐ๊ฒฐ๋ผ์๊ณ , ๊ทธ ๋ฐ๋๋ ๋ง์ฐฌ๊ฐ์ง์ธ ํํ๋ฅผ ๋๊ณ ์์ต๋๋ค.
์ฒซ ๋
ธ๋๋ฅผ head, ๋ง์ง๋ง ๋
ธ๋๋ฅผ tail์ด๋ผ๊ณ ํ๊ณ ๋๋จธ์ง๋ ์ด์ค ๋งํฌ๋๋ฆฌ์คํธ์์ ๊ทธ๋๋ก ๊ฐ์ ธ์๋ ๋ฌด๋ฐฉํ๊ฒ ๊ตฐ์!
2. ๊ตฌํ
class CircularLinkedList<T>{
fileprivate var head: DoublyNode<T>?
fileprivate weak var tail: DoublyNode<T>?
deinit {
var currentNode = self.head
while(currentNode != nil){
currentNode?.nextNode = nil
currentNode = currentNode?.prevNode
}
}
}
deinit ๋ฉ์๋ ๋ด๋ถ์ ์ฝ๋๋ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ๋ฃ์ ์ฝ๋์
๋๋ค.
3. ์ฝ์
///๋ฆฌ์คํธ์ ์ฒ์์ ๋
ธ๋ ์ถ๊ฐ
func inertAtFirst(_ newNode: DoublyNode<T>){
if self.head == nil{
self.head = newNode
self.tail = newNode
return
}
self.head?.prevNode = newNode
self.tail?.nextNode = self.head?.prevNode
newNode.prevNode = self.tail
newNode.nextNode = self.head
self.head = newNode
}
//๋ฆฌ์คํธ์ ํน์ ์์น์ ๋
ธ๋ ์ฝ์
@discardableResult
func insertAt(_ idx: Int, _ newNode: DoublyNode<T>)->DoublyNode<T>?{
if self.head == nil {return nil}
var currentNode = self.head
for _ in 0..<idx{
if currentNode == nil {return nil}
currentNode = currentNode?.nextNode
}
currentNode?.prevNode?.nextNode = newNode
currentNode?.prevNode = currentNode?.prevNode?.nextNode
newNode.prevNode = currentNode?.prevNode
newNode.nextNode = currentNode
return newNode
}
///๋ฆฌ์คํธ์ ๋ง์ง๋ง์ ๋
ธ๋ ์ถ๊ฐ
func insertAtLast(_ newNode: DoublyNode<T>){
if self.head == nil {
self.head = newNode
self.tail = newNode
// head?.prevNode = newNode
// tail?.nextNode = newNode
return
}
newNode.prevNode = self.tail //prevNode๋ weak๋ผ rf ์ฆ๊ฐ ์ํ๋ค
newNode.nextNode = self.tail?.nextNode //rf 1 ์ฆ๊ฐ, newNode.nextNode = self.head์ head์ ๋ํ rf๊ฐ ์ฆ๊ฐํจ
self.tail!.nextNode = newNode //์ ๋
ธ๋์ rf 1 ์ฆ๊ฐ
self.tail = newNode //tail์ weak๋ผ rf ์ฆ๊ฐ ์ํ๋ค
}
๋ณ๋ค๋ฅผ๊ฒ ์๋ ์ฝ๋ ์
๋๋ค๋ง,,
์ด์ tail ํ๋กํผํฐ๋ฅผ ํตํด ๋ฆฌ์คํธ์ ๋ง์ง๋ง ๋
ธ๋์ ์ง์ ์ ๊ทผํ ์ ์์ด ๋ง์ง๋ง์ ๋
ธ๋๋ฅผ ์ถ๊ฐํ๋ ๋น์ฉ์ด O(n)์์ O(1)๋ก ์ ์ฝ๋์์ ์์ ์์ต๋๋ค!
4. ์ญ์
///๋ฆฌ์คํธ์ ์ฒ์ ๋
ธ๋๋ฅผ ์ญ์
@discardableResult
func removeFirst()->DoublyNode<T>?{
if self.head == nil{
return nil
}
var removeNode = self.head
self.head = self.head?.nextNode
self.head?.prevNode = self.tail
self.tail?.nextNode = self.head
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
}
removeNode?.nextNode?.prevNode = removeNode?.prevNode
removeNode?.prevNode?.nextNode = removeNode?.nextNode
return removeNode
}
์ฝ์ ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ง์ง๋ง ๋ ธ๋ ์ญ์ ๋ํ O(1)์ ๋น์ฉ์ผ๋ก ์ํํ ์ ์์ต๋๋ค.
5. ํ์
///๋ฆฌ์คํธ๋ด ํน์ ์์น์ ๋
ธ๋ ๋ฐํ
@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
}
๋์ด์ ๋๋ฆด ์ ์๋ ๋ง์ด ์์ต๋๋ค. ์ฒ์, ๋ ๋ ธ๋๋ฅผ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ์ง์ ์ ์ํด๋ณด์๊ธธ ๋ฐ๋๋๋ค!
6. ๋งํฌ๋ ๋ฆฌ์คํธ์ Swift์ ๋ฐฐ์ด ๋น๊ต
์, ๋งํฌ๋ ๋ฆฌ์คํธ์ ํต์์ ์ผ๋ก ์๋ ค์ง ๊ฐ๋จํ ๋น๊ตํด๋ณด์์ต๋๋ค.
๋งํฌ๋ ๋ฆฌ์คํธ | ๋ฐฐ์ด | |
๋ฉ๋ชจ๋ฆฌ์ ์ฐ์์ ์ผ๋ก ์ ์ฅ๋์ด ์๋๊ฐ? | X | O |
๋ค์ ์๋ฃ๋ฅผ ๊ฐ๋ฆฌํค๊ธฐ ์ํ ์ถ๊ฐ์ ์ธ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํ๊ฐ? | O | X |
ํน์ ์์น์ ์๋ฃ๋ฅผ ์ป๊ธฐ ์ํ ๋น์ฉ์ ์ผ๋ง์ธ๊ฐ? | ํ๊ท ์ ์ผ๋ก O(n), ๊ฒฝ์ฐ์ ๋ฐ๋ผ O(1) | O(1) |
์์๋ฅผ ์ถ๊ฐ/์ญ์ ํจ์ ๋ฐ๋ผ ๋ฐ์ํ๋ ๋น ๊ณต๊ฐ์ ๊ด๋ฆฌ๊ฐ ์ฉ์ดํ๊ฐ? | O | X |
๋น๊ตํ ๊ฑฐ๋ฆฌ๋ ๋ ๋ง๊ฒ ์ต๋๋ค๋ง, ๊ฐ ์๋ฃ๊ตฌ์กฐ์ ๋ฐ๋ผ ์ฅ๋จ์ ์ด ์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ๋ง์
๋๋ค, ํน์ ์ฌ๋ฌ๋ถ์ C, C++์ Swift์์ ๋ฐฐ์ด์ ์ฌ์ฉํด ๋ณธ ๊ฒฝํ์ด ์์ผ์ ๊ฐ์? ์ ๋ ์๋ต๋๋ค!
์ผ๋ฐ์ ์ผ๋ก ๋ฐฐ์ด์ ๊ทธ ํฌ๊ธฐ๋ฅผ ์์ค์ฝ๋ ๋ ๋ฒจ์์ ์ง์ ํ๊ฑฐ๋, C๊ณ์ด์ ๊ฒฝ์ฐ์ malloc ๋ฑ์ผ๋ก ํ์ํ ํฌ๊ธฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํด ์ฌ์ฉํฉ๋๋ค.
๊ทธ๋ฌ๋ Swift์์๋ ๋ฐฐ์ด์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ฉ๋ชจ๋ฆฌ ํ ๋น ๋ฑ์ ์์
์ ํ ๊ธฐ์ต์ ์๊ตฐ์. ์ด๋ป๊ฒ ๋ ์ผ์ผ๊น์?
//type var_name[demension], c++์ Array ์์ฑ
int arr[10];
//var var_name: [Element] = [], Swift์ Array ์์ฑ
var arr: [Int] = []
์์, ๋ค๋ฅธ๊ณณ ๊ธฐ์๊ฑฐ๋ฆด ํ์ ์์ด ๊ณต์๋ฌธ์๋ฅผ ์ดํผ๋ฉฐ ํ์ธํด๋ณผ๊น์?
(Swift์ ๊ณต์๋ฌธ์์ Apple์ ๊ณต์๋ฌธ์ ๋๊ณณ์์ ํ์ธํ ์ ์๋๋ฐ, Apple์ชฝ ๋ฌธ์์ ์ค๋ช
์ด ๋ ์ ํฉํ๋ค๊ณ ํ๋จํ์์ต๋๋ค.)
Every array reserves a specific amount of memory to hold its contents. When you add elements to an array and that array begins to exceed its reserved capacity, the array allocates a larger region of memory and copies its elements into the new storage. This exponential growth strategy means that appending an element happens in constant time, averaging the performance of many append operations. Append operations that trigger reallocation have a performance cost, but they occur less and less often as the array grows larger.
Swift์์ ๋ชจ๋ ๋ฐฐ์ด์ ์ปจํ ์ธ ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด ํน์ ํ ํฌ๊ธฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ์ง๋ฉฐ, ์ ์์๋ฅผ append ํ ๋ ๊ธฐ์กด ํฌ๊ธฐ๋ฅผ ๋์ด์๋ฉด ๊ทธ ํฌ๊ธฐ์ ๋๋ฐฐ์ ์ ๊ณต๊ฐ์ ํ๋ณดํ ํ ์ด๊ณณ์ผ๋ก ๊ธฐ์กด ๋ฐฐ์ด์ ๋ณต์ฌํฉ๋๋ค. ์ด๋ฌํ ๊ธฐํ๊ธ์์ ์ฆ๊ฐ ์ ๋ต์, ํ๊ท ์ ์ผ๋ก ์์์ ์ถ๊ฐ ์์์๊ฐ ์์ ์ผ์ด๋๋๊ฒ์ ๋ปํ๋ฉฐ, ๋ฉ๋ชจ๋ฆฌ ์ฌํ ๋น์ ๋ํ ์ํ๋น์ฉ์ ๋ฐ์ํ๋ ๋ฐฐ์ด์ด ์ปค๊ฐ์ ๋ฐ๋ผ ์ค์ด๋ญ๋๋ค.
์์ปจ๋, ๋ฐฐ์ด์ด ๊ฝ ์ฐจ๋ฉด ์ค์ค๋ก๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ฌํ ๋น์ ์ํํ๋ฉฐ ํฌ๊ธฐ๋ฅผ ๊ณ์ ๋๋ ค๋๊ฐ๋ ๋ฉ์ปค๋์ฆ์ ์ทจํ๊ณ ์๊ตฐ์.
๊ทธ๋ ๋ค๋ฉด ์ฝ์
, ์ญ์ ๋ฑ์ด ํต์์ ๋ฐฐ์ด๋ณด๋ค ์ฉ์ดํ ์ ์๊ฒ ๋ค์?
๋ง์ต๋๋ค! ๊ณต์ ๋ฌธ์๋ฅผ ๋ณด๊ณ ์ค์
จ๋ค๋ฉด ์ด๋ฏธ ์์๊ฒ ์ง๋ง, Swift์ ๋ฐฐ์ด์ ๋ง์น ๋งํฌ๋ ๋ฆฌ์คํธ์ฒ๋ผ ์ฝ์
, ์ญ์ ๋ฑ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ณ ์์ต๋๋ค!
var array:[Int] = []
let first = array.first!
let last = array.last!
array.append(1)
array.removeLast()
array.insert(1, at: 1)
array.remove(at: 1)
array.removeAll()
๋ ์์ธํ Swift ๋ฐฐ์ด์ ๋ด์ฉ์ ๋ณ๋์ ํฌ์คํ
์ ์์ฑํ์ฌ ๋ฐฐ์ด์ ๋ํด ์์๋ณด๋๊ฒ์ผ๋ก ์ด์ฏค ๋ง๋ฌด๋ฆฌ ์ง๊ฒ ์ต๋๋ค.
ํ ... Swift์์๋ ๊ตณ์ด ๋งํฌ๋๋ฆฌ์คํธ๋ฅผ ๊ตฌํํ ํ์๊ฐ ์์ด ๋ณด์ด๋๊ตฐ์... T_T
์๊ฐ๋ฝ ์ํ ๋ ์ง๊ธ๊น์ง์ ๊ณต๋ถ๋ ์๋ฏธ๊ฐ ์๋ ๊ฑธ๊น์?
7. ๋ง๋ฌด๋ฆฌ
๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ์์ ๊ตฌํํ๊ณ , ์ฝ์
์ด๋ ์ญ์ ๋ฑ์ ์ฐ์ฐ์ ์ง์ ๊ณ ์ํด๋ณด๋ฉด์ ๋งํฌ๋ ๋ฆฌ์คํธ๊ฐ ์ด๋ค ๋ฐฉ์์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ถ๊ฐ/์ญ์ ๊ฐ ๋ฐฐ์ด๋ณด๋ค ์ฉ์ดํ๋๋ก ๊ณ ์๋์๊ณ ๋์ํ๋์ง, ํ์/์ฝ์
/์ญ์ ๋ฑ์ ์ฐ์ฐ์ด ์ ํต์์ ์ผ๋ก O(n)์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋ฉฐ ํน์ ๊ฒฝ์ฐ์์ O(1)์ ์์์๊ฐ์ ๊ฐ์ง๋์ง ์ ์ ์์์ต๋๋ค.
Xcode๋ฅผ ์ฌ์ฉํ๋ค ๋ณด๋ฉด ์ค๋ฅธ์ชฝ Quick Help์ฐฝ์ ์์ฃผ ๋ณด์คํ
๋ฐ์! ์ด๊ณณ์ ๊ทธ๋์ ๊ณต๋ถํ๋ ๋ด์ฉ์ด ๋์์ด ๋ ๋๊ฐ ์์ต๋๋ค.
Swift์ ๋ฐฐ์ด์์ insert๋ remove ํจ์์ ๋ฌธ์๋ฅผ ๋ง์ง๋ง๊น์ง ์ฝ์ด ๋ณด๋ฉด, Complexity๋ก ํด๋น ํจ์์ ๋น์ฉ์ ์๋ดํ๊ณ ์์ต๋๋ค.
๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ๊ณต๋ถํ๋ฉฐ ์์ฃผ ๋ณด์๋ O(n)์ Swift ๋ฐฐ์ด์ Complexity์์๋ ๋ณผ ์ ์๊ตฐ์!
์ด์ O(n)์ ๋น์ฉ์ด ๋๋ ์ด์ ๋ฅผ ์กฐ๊ธ ์๊ฒ ๊ฐ์ต๋๋ค! ๋น๋ก ๋ด๋ถ์ ์ธ ๊ตฌํ์ด ์ด๋ป๊ฒ ์ด๋ฃจ์ด์ ธ ์๋์ง ์ ์ ์์ง๋ง ๋ง์ด์ฃ
์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๋ค์์ ๋ ๋ง๋์!
'learnings > Algorithm&DS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DataStructure] ํ 1๋ถ (1) | 2024.05.01 |
---|---|
[DataStructure] ์คํ (1) | 2024.05.01 |
[Algorithm] ์ฐจ๋๊ธฐ์ง ์๊ณ ๋ฆฌ์ฆ, ์คํ์ ์ฌ์ฉํ์ฌ ์ค์ ํ๊ธฐ๋ฒ์ ํ์ ํ๊ธฐ๋ฒ์ผ๋ก ๋ณํ (0) | 2024.04.05 |
[DataStructure] ์ด์ค ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ Swift๋ก ๊ตฌํํ๊ธฐ (0) | 2024.03.25 |
[DataStructure] ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ Swift๋ก ๊ตฌํํ๊ธฐ (0) | 2024.03.20 |