Bibi's DevLog ๐ค๐
[Swift ์๋ฃ๊ตฌ์กฐ] 4. Stack ์คํ (๋ฐฐ์ด/์ฐ๊ฒฐ๋ฆฌ์คํธ๋ก ๊ตฌํํ๊ธฐ) ๋ณธ๋ฌธ
[Swift ์๋ฃ๊ตฌ์กฐ] 4. Stack ์คํ (๋ฐฐ์ด/์ฐ๊ฒฐ๋ฆฌ์คํธ๋ก ๊ตฌํํ๊ธฐ)
๋น๋น bibi 2022. 12. 21. 21:01Data Structure in Swift (Stack)โ-โPart 3
Swift Algorithm Club: Swift Stack Data Structure
์ด ๊ธ์ ์์ ๋ ๋ฌธ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํด์ ๋ฐ ์ ๋ฆฌํ ๊ธ์ ๋๋ค.
์คํ Stack
์คํ์ ์์๋ฅผ ์ ํ(linear)์ผ๋ก ์ ๋ฆฌํ๊ฒ ํด ์ฃผ๋ ์๋ฃ๊ตฌ์กฐ์ ๋๋ค.
์คํ์ ๊ธฐ๋ณธ์ ์ผ๋ก LIFO(Last In First Out) ๋งค์ปค๋์ฆ์ ํตํด ์์๋ฅผ ์ฝ์ ํ๊ณ ์ญ์ ํฉ๋๋ค.
์ด๋ ๊ฐ์ฅ ๋์ค์ ๋ํด์ง ์์๊ฐ ๊ฐ์ฅ ๋จผ์ ์ญ์ ๋จ์ ์๋ฏธํฉ๋๋ค.
์คํ์ ์ฐ์ฐ
์คํ์ ๊ต์ฅํ ํ์ ๋ ๋ฒ์์ ์ฐ์ฐ์ ์ ๊ณตํ๋ค.
push()
:O(1)
. ์คํ์ ์๋ก์ด ์์๋ฅผ ์ฝ์ ํ๋ ์ฐ์ฐpop()
:O(1)
. ์คํ์ ๋งจ ์์ ์์๋ฅผ ์ญ์ ํ๋ ์ฐ์ฐpeek()
: ์คํ์ ๋งจ ์์ ์์๊ฐ ๋ฌด์์ธ์ง ์กฐํํ๋ ์ฐ์ฐ- ์คํ์ ์์๋ฅผ ์กฐํํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง ์๋๋ค. ์์ธ์ ์ผ๋ก
peek()
์ ํตํด ๋งจ ์์ ์์๊ฐ ๋ฌด์์ธ์ง ํ์ธํ๋ ๊ฒ๋ง ๊ฐ๋ฅํ๋ค.
- ์คํ์ ์์๋ฅผ ์กฐํํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง ์๋๋ค. ์์ธ์ ์ผ๋ก
Swift์์์ ์คํ
์คํ์ ๊ฑฐ์ ๋ชจ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์ ์ฌ์ฉ๋๋ค. iOS์์๋ ๋ค์๊ณผ ๊ฐ์ ๊ณณ์ ์คํ ์๋ฃ๊ตฌ์กฐ๊ฐ ์ฌ์ฉ๋๋ค.
- UINavigationController๊ฐ ๋ทฐ ์ปจํธ๋กค๋ฌ๋ค์ pushํ๊ณ popํ ๋
- ์ง์ญ ๋ณ์์ ๋ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ ๋
โ๏ธ Swift๋ ์คํ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ์ง ์์ผ๋ฏ๋ก, ์ง์ ๊ตฌํํด์ผ ํ๋ค.
Swift๋ก ์คํ ๊ตฌํํ๊ธฐ - (1) ๋ฐฐ์ด ์ฌ์ฉ
์ฃผ์์ด ์๋ ์ ์ฒด ์ฝ๋๋ ์ฌ๊ธฐ์ ์์ต๋๋ค. (๋ฐฐ์ด, ์ฐ๊ฒฐ๋ฆฌ์คํธ ๊ตฌํ๋ฐฉ์ ๋ชจ๋ ํฌํจ)
struct Stack<Element> {
fileprivate var array: [Element] = []
// isEmpty : ์คํ์ด ๋น์ด์๋์ง ํ์ธ
var isEmpty: Bool {
return array.isEmpty
}
// count : ์คํ์ด ๋ช ๊ฐ์ ์์๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ํ์ธ
var count: Int {
return array.count
}
// push : ์คํ ๋งจ ์์ ์ ์์๋ฅผ ์ถ๊ฐํจ
mutating func push(_ element: Element) {
array.append(element)
}
// pop : ์คํ ๋งจ ์์ ์์๋ฅผ ์ ๊ฑฐํจ
// ์คํ์ด ๋น์ด ์์ ๋ nil ๋ฐํ
mutating func pop() -> Element? {
return array.popLast()
}
// peek : ์คํ ๋งจ ์์ ์์๊ฐ ๋ฌด์์ธ์ง ์กฐํํจ
// ์ญ์ ์คํ์ด ๋น์ด ์์ ๋ nil ๋ฐํ
func peek() -> Element? {
return array.last
}
}
extension Stack: CustomStringConvertible {
var description: String {
let topDivider = "---Stack---\n"
let bottomDivider = "\n-----------\n"
let stackElements = array.map { "\($0)" }.reversed().joined(separator: "\n")
return topDivider + stackElements + bottomDivider
}
}
isEmpty
: ์คํ์ด ๋น์ด์๋์ง ํ์ธcount
: ์คํ์ด ๋ช ๊ฐ์ ์์๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ํ์ธpush()
: ์คํ ๋งจ ์์ ์ ์์๋ฅผ ์ถ๊ฐํจ- ์ด ์คํ์ ๋ด๋ถ์ ์ผ๋ก ๋ฐฐ์ด์ ์ฌ์ฉํ๋ฏ๋ก,
pop()
์ ํตํด ๋ฐฐ์ด์ ๋งจ ๋์ ์์๋ฅผ ์ถ๊ฐํ๋ค. ๊ทธ ์ด์ ๋ ๋ฐฐ์ด์ ๊ฒฝ์ฐ ์์๋ฅผ ๋งจ ์์ด๋ ์ค๊ฐ์ ์ฝ์ ํ ๋(O(n)
) ์ ๋นํด ๋งจ ๋์ ์ฝ์ ํ๋ ๊ฒ(O(1)
) ์ด ๋ ๋น ๋ฅด๊ธฐ ๋๋ฌธ์ด๋ค. - Swift๊ฐ ์ ๊ณตํ๋ ๋ฉ์๋์ธ
append()
๋ฅผ ์ฌ์ฉํ๋ค. -O(1)
- ์ด ์คํ์ ๋ด๋ถ์ ์ผ๋ก ๋ฐฐ์ด์ ์ฌ์ฉํ๋ฏ๋ก,
pop()
: ์คํ ๋งจ ์์ ์์๋ฅผ ์ ๊ฑฐํจ- ์ด ์คํ์ ๋งจ ๋์์๋ถํฐ ์์๋ฅผ ์ถ๊ฐํ๋ฏ๋ก, ์ญ์ ํ ๋๋ ๋งจ ๋์ ์์๋ฅผ ์ญ์ ํด์ผ ํ๋ค.
- Swift๊ฐ ์ ๊ณตํ๋ ๋ฉ์๋์ธ
popLast()
๋ฅผ ์ฌ์ฉํ๋ค. -O(1)
- ๋ฆฌํด๊ฐ์ด ์ต์
๋์ด๋ค : ์คํ์ด ๋น์ด ์๋ ์ํ์์
pop()
์ ํ๋ฉดnil
์ ๋ฐํํ๋ค.
peek()
: ์คํ ๋งจ ์์ ์์๊ฐ ๋ฌด์์ธ์ง ์กฐํํจ- ์ญ์ ๋งจ ๋์ ์์๊ฐ ๋ฌด์์ธ์ง ์กฐํํด ๋ฐํํ๋ฉด ๋๋ค.
- Swift๊ฐ ์ ๊ณตํ๋ ํ๋กํผํฐ์ธ
.last
๋ฅผ ์ฌ์ฉํ๋ค. -O(1)
- ๋ฆฌํด๊ฐ์ด ์ต์
๋์ด๋ค : ์คํ์ด ๋น์ด ์๋ ์ํ์์
peek()
์ ํ๋ฉดnil
์ ๋ฐํํ๋ค.
extension Stack: CustomStringConvertible {...}
- ์คํ์ ์ถ๋ ฅ(print) ํ์ ๋ ๋ณด๊ธฐ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์ถ๊ฐ๋ก ๊ตฌํํ ์ ์๋ค.
reversed()
: ์คํ์ ์์๋ค์ด ๋ฐฐ์ด์ ๋ค์์๋ถํฐ ์ ์ฅ๋์ด ์์ผ๋ฏ๋ก, ์ถ๋ ฅํ ๋๋ ์ต๊ทผ ์์(๋งจ ๋ค์ ์์)๊ฐ ๋งจ ์์ ์ถ๋ ฅ๋๊ฒ ํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค..joined(separator: "\n")
: ์์ ์ฌ์ด์ ์ค๋ฐ๊ฟ๋ฌธ์(\n
) ๋ฅผ ๋ฃ์ด ๋ณด๊ธฐ ํธํ๊ฒ ํ๋ค.
<Element>
: ์ ๋ค๋ฆญ ์ฌ์ฉ- ํน์ ํ์ ์ ์์ ๋ฟ ์๋๋ผ ๋ชจ๋ ํ์ ์ ์ฌ์ฉํ ์ ์๊ฒ ํ๊ธฐ ์ํด.
Swift๋ก ์คํ ๊ตฌํํ๊ธฐ - (2) ์ฐ๊ฒฐ๋ฆฌ์คํธ ์ฌ์ฉ
์ฐ๊ฒฐ๋ฆฌ์คํธ์ ๊ฐ์ด Node์ ๊ฐ๋ ์ ์ฌ์ฉํด ์คํ์ ๊ตฌํํด ๋ณธ๋ค.
// Node class to hold the data
class Node<T> {
let value: T
var next: Node?
init(value: T) {
self.value = value
}
}
// Stack class to hold the all items
class Stack<T> {
var top: Node<T>?
func push(_ value: T) {
let currentTop = top
top = Node(value: value)
top?.next = currentTop
}
@discardableResult
func pop() -> T? {
let currentTop = top
top = top?.next
return currentTop?.value
}
func peek() -> T? {
return top?.value
}
}
extension Node: CustomStringConvertible {
var description: String {
guard let next = next else { return "\(value)" }
return "\(value)\n" + String(describing: next) // ์ฌ๊ธฐ์ ์ฐ์์ ์ผ๋ก ๋
ธ๋๋ฅผ String์ผ๋ก ๋ณํ
}
}
extension Stack: CustomStringConvertible {
var description: String {
guard let top = top else { return "---- Stack is EMPTY ----" }
return "---- Stack ----\n" + String(describing: top) + "\n---------------"
}
}
var stackString = Stack<String>()
print(stackString.pop())
top
: ์คํ์ ์ต์์ ๋ ธ๋๋ฅผ ์๋ฏธํ๋ค.push()
: ์คํ ๋งจ ์์ ์ ์์๋ฅผ ์ถ๊ฐํจ- ๊ธฐ์กด
top
์์ ์ ๋ ธ๋๋ฅผ ๋ง๋ค์ด ์๋๋ค.
- ๊ธฐ์กด
pop()
: ์คํ ๋งจ ์์ ์์๋ฅผ ์ ๊ฑฐํจ- ์ต์์ ๋
ธ๋์ next(
nil
)๋ฅผ ์ต์์ ๋ ธ๋๋ก ๋ง๋ ๋ค์, ๊ธฐ์กด ์ต์์ ๋ ธ๋์ ๊ฐ์ ๋ฐํํ๋ค. - ๋ฆฌํด๊ฐ์ด ์ต์
๋์ด๋ค : ์คํ์ด ๋น์ด ์๋ ์ํ์์
pop()
์ ํ๋ฉดnil
์ ๋ฐํํ๋ค.
- ์ต์์ ๋
ธ๋์ next(
peek()
: ์คํ ๋งจ ์์ ์์๊ฐ ๋ฌด์์ธ์ง ์กฐํํจ- ํ์ฌ ์ต์์ ๋
ธ๋ (=
top
) ์ ๊ฐ์ ๋ฐํํ๋ค - ๋ฆฌํด๊ฐ์ด ์ต์
๋์ด๋ค : ์คํ์ด ๋น์ด ์๋ ์ํ์์
peek()
์ ํ๋ฉดnil
์ ๋ฐํํ๋ค.
- ํ์ฌ ์ต์์ ๋
ธ๋ (=
extension Node: CustomStringConvertible {...}
- ๋ ธ๋๋ฅผ ์ถ๋ ฅ(print) ํ์ ๋ ๋ณด๊ธฐ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์ถ๊ฐ๋ก ๊ตฌํํ ์ ์๋ค.
next
๊ฐ ์์ผ๋ฉดvalue
์next
๋ฅผ, ์์ผ๋ฉดvalue
๋ฅผ ๋ฐํnext
๋ํNode
์ด๋ฏ๋กnext
๊ฐ ์๋ค๋ฉด ๋ค์Node
๋ ์ฐ์์ ์ผ๋ก ์ถ๋ ฅํ๊ฒ ๋๋ค.
extension Stack: CustomStringConvertible {...}
- ์คํ์ ์ถ๋ ฅ(print) ํ์ ๋ ๋ณด๊ธฐ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์ถ๊ฐ๋ก ๊ตฌํํ ์ ์๋ค.
top
์ ๊ฐ์ด ์์ผ๋ฉดtop
์ ๊ฐ์, ์์ผ๋ฉด ๋น์ด์๋ค๋ ๋ฌธ๊ตฌ๋ฅผ ๋ฐํํ๋ค.top
์ ๊ฐ์ด ์์ผ๋ฉดString(describing: top)
๋ฅผ ์ถ๋ ฅํ๋๋ฐ, ์ด๋top
์ดNode
์ด๋ฏ๋กNode
์CustomStringConvertible
์ ๋ฐ๋ผ ์ถ๋ ฅ๋๋ค.
<Element>
: ์ ๋ค๋ฆญ ์ฌ์ฉ- ํน์ ํ์ ์ ์์ ๋ฟ ์๋๋ผ ๋ชจ๋ ํ์ ์ ์ฌ์ฉํ ์ ์๊ฒ ํ๊ธฐ ์ํด.
Swift๋ก ์คํ ๊ตฌํํ๊ธฐ - (1)๋ฐฐ์ด๊ณผ (2)์ฐ๊ฒฐ๋ฆฌ์คํธ ๋น๊ต
import Foundation
let startTime = CFAbsoluteTimeGetCurrent()
var stackString = Stack<String>()
stackString.push("First")
stackString.pop()
stackString.push("Second")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("Third")
stackString.push("First")
stackString.pop()
stackString.push("Second")
stackString.push("Third")
let processTime = CFAbsoluteTimeGetCurrent() - startTime
print(processTime)
// 0.004179954528808594 - (1) ๋ฐฐ์ด
// 0.0066149234771728516 - (2) ์ฐ๊ฒฐ๋ฆฌ์คํธ
์๋ฌด ๋ฐ์ดํฐ๋ ๋ฃ์ด์ ๋์ ์ฑ๋ฅ์ ๋น๊ตํด ๋ดค๋๋ฐ, ๋ฐฐ์ด์ ๋ณดํต 0.004์ด๋๊ฐ ๋์๊ณ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ ๋ณดํต 0.006์ด๋๊ฐ ๋์๋ค.
์ฐ๊ฒฐ๋ฆฌ์คํธ๊ฐ ๋ ๋น ๋ฅผ๊ฑฐ๋ผ๋ ๋ด ์๊ฐ๊ณผ๋ ๋ค๋ฅธ ๊ฒฐ๊ณผ์๋ค๐ฎ
๊ทธ๋์ ํ์๋ ๋ฌ๋ฆฌ ์คํ์ ๋ฐ๋์ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ฅผ ํตํด ๊ตฌํํ ํ์๋ ์๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
์ด๋ฏธ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ฅผ ์ธ๋์ ๊ฐ์ ์๊ฐ๋ณต์ก๋(O(1)
)์ ๋ฉ์๋๋ฅผ ๋ฐฐ์ด์ ๋ฉ์๋์ ํ๋กํผํฐ(append()
, popLast()
, .last
)๋ก ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ด๋ค.
'ํ๋ก๊ทธ๋๋ฐ > Data Structures ์๋ฃ๊ตฌ์กฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift ์๋ฃ๊ตฌ์กฐ] 5. Queue ํ (0) | 2022.12.22 |
---|---|
[Swift ์๋ฃ๊ตฌ์กฐ] 3. Linked List ์ฐ๊ฒฐ ๋ฆฌ์คํธ (Singly Linked List) (0) | 2022.12.19 |
[Swift ์๋ฃ๊ตฌ์กฐ] 2. Dictionary ๋์ ๋๋ฆฌ (์์ฑ, CRUD) (0) | 2022.12.16 |
[Swift ์๋ฃ๊ตฌ์กฐ] 1. Array ๋ฐฐ์ด (์์ฑ, CRUD, COW) (0) | 2022.12.16 |
[Swift] ์ฐ๊ฒฐ๋ฆฌ์คํธ LinkedList, ์๋ฐฉํฅ ์ฐ๊ฒฐ๋ฆฌ์คํธ DoublyLinkedList (1) | 2022.10.06 |