0. ์๋ก
๋ง์ฝ ๋ฐ์ดํฐ๊ฐ ๋ฌผ๋ฐ๋ฏ์ด ์์ฌ ์ฒ๋ฆฌํ ์ ์๋ ์๋๋ณด๋ค ๋น ๋ฅด๋ค๋ฉด, ๊ทธ๋์ ์์ด๋ ๋ฐ์ดํฐ๋ ์ด๋ป๊ฒ ํด์ผ ์ข์๊น์?
์์์ ์์ ์ฌ๋์ด ๋ง์ ์๋ฆฌ๊ฐ ์์ผ๋ฉด, ์ฌ๋๋ค์ ์ค์ ์์ฃ . ์๋ฆฌ๊ฐ ์๊ธฐ๋ฉด, ๋จผ์ ์จ ์ฌ๋์ด ๋จผ์ ์๋ฆฌ์ ์๋ฏ์ด
๋ฐ์ดํฐ๋ ์ค์ธ์ ์ฒ๋ฆฌ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ฒ ํ ์ ์์๊น์?
๋ค์ด์จ ์์๋๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ์ ์
์ ์ถ์ ์ํ ์๋ฃ๊ตฌ์กฐ, ์ด๋ฒ ๊ธ์ ํ์ ๋ํด ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค.
1. ๊ตฌ์กฐ
๋ด๊ฐ ๋จผ์ ์ผ!
์ ์
์ ์ถ, ์ด๋ฆฐ ์์ด๋ค๋ ์๊ณ ์๋ ์ธ์์ ์ด์น์
๋๋ค. ๋จผ์ ๋ฌด์ธ๊ฐ๋ฅผ ํ ๋
์์ด ์ฐ์ ๊ถ์ ๊ฐ๋๋ค!
ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ค์ธ์ ์ฒ๋ฆฌ๋ฅผ ๋๊ธฐ์ํต๋๋ค. ์ฒ๋ฆฌ๊ฐ ๋๋๋ฉด, ๋จผ์ ๋ค์ด์จ ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ์ฒ๋ฆฌํฉ๋๋ค.
๋ฐ์ดํฐ๋ ์์๊ฐ ์์ผ๋ ์๋ก๊ฐ ๋จผ์ ๋ผ๊ณ ์ฐ๊ธธ ์ผ์ ์๊ฒ ์ต๋๋ค๋ง, ์คํ๋ ค ์๋ก๊ฐ ์๋ฌด๋ง๋ ์์ด ๊ณจ์น์ธ ๋
์๋ค์ธ ๋ฐ์ดํฐ๋
์ฌ์ฉํ๋ ค๋ ์ฌ๋์ด ์ฒ๋ฆฌ ์์๋ฅผ ์ง์ ํด์ฃผ์ด์ผ ํฉ๋๋ค.
Swift์์ ์ฌ์ฉ์๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ ์
์ ์ถ์ ํํ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด์ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์ ์ ์๊ฒ ์ฃ .
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ๊ฐ๋ฐ์์ด๋ฏ๋ก, ์ ์
์ ์ถ์ ์์ด ๊ฐ๋ฐ์๋ผ๋ฆฌ์ ์ฝ์์ธ ํ(queue)๋ฅผ ์ฌ์ฉํ๋๊ฒ์ด ์ด๋กญ์ต๋๋ค.
์์ค์ฝ๋์ ํ๋ผ๋ ๋จ์ด๋ฅผ ๋ณด๋๊ฒ๋ง์ผ๋ก๋, ๋ฐ์ดํฐ๋ฅผ ์ ์
์ ์ถ๋ก ์ฒ๋ฆฌํ๊ฒ ๋ค๋ ์ ๋ณด๋ฅผ ์ค ์ ์์ผ๋ ๋ง์ด์ฃ !
์ฝ์์ด๋ ์ฐธ ํธ๋ฆฌํ ๋ฌผ๊ฑด์
๋๋ค.
2. ๊ตฌํ
ํ๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ ๋ํ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์ ์ ์๊ฒ ์ต๋๋ค๋ง, ๋จผ์ ์คํ 2๊ฐ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
์คํ 2๊ฐ๋ก ์ด๋ป๊ฒ ํ๋ฅผ ๊ตฌํํ๊ฒ ๋ค๋๊ฑด์ง ๊ถ๊ธํ์ง ์์ผ์ ๊ฐ์? ์ ์ด๋ ์ ๋ ๊ถ๊ธํ์ต๋๋ค.
์์ด๋์ด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- enqueue์ ์
๋ ฅ์ ๋ด๋นํ๋ ์คํ์ ๋ฐ์ดํฐ๋ฅผ appendํ๋ค.
์ด๋ก ์ธํด ๋จผ์ ๋ค์ด์จ ๋ฐ์ดํฐ๊ฐ ๋งจ ์, ๋์ค์ ๋ค์ด์จ ๋ฐ์ดํฐ๊ฐ ๋งจ ๋ค์ ์์นํ๋ค. - ์ถ๋ ฅ์ ๋ด๋นํ๋ ์คํ์, ์
๋ ฅ์ฉ ์คํ์ ๋ค์ง์ด ๋ณต์ฌํ๋ค.
์ด๋ก ์ธํด ๋จผ์ ๋ค์ด์จ ๋ฐ์ดํฐ๊ฐ ๋งจ ๋ค, ๋์ค์ ๋ค์ด์จ ๋ฐ์ดํฐ๊ฐ ๋งจ ์์ ์์นํ๋ค. - popLast ๋ฐ์๋ฅผ ํ์ฉํ์ฌ dequeueํ ๋, ์๊ธฐ ๊ณผ์ ์ ์ํด ํด๋น ์์๋ ๋จผ์ ๋ค์ด์จ ๋ฐ์ดํฐ์ด๋ค.
์์ ๊ณผ์ ๋๋ก๋ผ๋ฉด append์ popLast ๋ชจ๋ O(1)์ด๋ฏ๋ก ์์์๊ฐ ๋ด์ ์ํํ ์ ์์ต๋๋ค.
๋จ, ์คํ์ ๋ค์ง์ด ๋ณต์ฌํ๋ ๊ณผ์ ์ ์ ์ธํ๋ค๋ฉด ๋ง์ด์ง์.
Swift๋ Array ๋ด์ ์์๋ฅผ ๋ค์ง์ Array๋ฅผ ๋ฐํํด์ฃผ๋ ๋ฉ์๋ reversed()๋ฅผ ์ง์ํฉ๋๋ค๋ง
ํด๋น ์ด๋ฆ์ผ๋ก ์ ์๋ ๋ฉ์๋๊ฐ ๋ณต์๊ฐ์ด๋ฉฐ, ๋ฐ๋ผ์ ๋ฐํฉํ์ ๋ฐ๋ผ O(1) ๋๋ O(n)์ธ ๋ฉ์๋๊ฐ ๋์ํฉ๋๋ค.
(์ฌ๋ฌ ๋ธ๋ก๊ทธ์ ํด๋น ๋ฉ์๋๊ฐ O(1)์ผ๋ก ๋์ํ๋ค๋ ์ค๋ช
์ด ๋ง์๋ฐ, ์๋ฌด๋ฆฌ quick view๋ ๊ทธ๋ ์ง ์์๊ธฐ์ ์์๋ณด์์ต๋๋ค)
- ๋ฐํํ์ด Array์ผ ๊ฒฝ์ฐ
์ด๋ Sequence ์ ๊ตฌํ๋ผ์๋ ๋ฉ์๋๋ก, ๋ณต์ฌํ Array์ ๋ชจ๋ ์์๋ฅผ Swapํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
n๊ฐ์ ๋ฐ์ดํฐ ์ค n/2๊ฐ์ ์ ๊ทผํ๋ฏ๋ก O(n)์ Cost๊ฐ ๋ฐ์ํฉ๋๋ค. ์์ค์ฝ๋ ๋งํฌ - ๋ฐํํ์ด ReversedCollection์ผ ๊ฒฝ์ฐ
์ด๋ BidirectionalCollection์ ๊ตฌํ๋ผ์๋ ๋ฉ์๋๋ก, array๋ฅผ ๊ฑฐ๊พธ๋ก ์ ๊ทผํ๋๋ก ๋ํํ ์๋ฃํ์ธ
ReversedCollection๋ฅผ ๋ฐํํฉ๋๋ค. ์์ค์ฝ๋ ๋งํฌ
RerversedCollection์ RangeReplaceableCollection Protocol์ ์ฑํํ๊ณ ์์ง ์๊ธฐ ๋๋ฌธ์, popLast๋ฑ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ Sequence์์ ์ ๊ณตํ๋ reversed()๋ฅผ ์ฌ์ฉํ๊ฒ ๋๊ณ , ์ด๋ O(n)์ Cost๊ฐ ๋ฐ์ํ๊ธฐ์ deque์์ outbox๊ฐ ๋น์ด์์ ๋ O(n), ๊ทธ๋ ์ง ์๋ค๋ฉด O(1)์ Cost๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
์์ฝํ๋ฉด, dequeue์์ outbox์ ์๋ ์์๊ฐ ์ ์์๋ก, ์์ฃผ dequeueํ ์๋ก dequeue๋ ๋ ์์ฃผ O(n)์ Cost๊ฐ ๋ฐ์ํ๊ฒ ๊ตฐ์.
์ด๋ฅผ ํด์ํ๊ธฐ ์ํด front์ ์์น๋ฅผ ๊ธฐ์ตํ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ๋ ๋ฑ์ ๋ฐฉ๋ฒ์ด ์๊ฒ ์ต๋๋ค๋ง..!
๊ณ์ ์งํํ๊ฒ ์ต๋๋ค.
struct Queue<T>{
fileprivate var inbox: [T] = []
fileprivate var outbox: [T] = []
init(inbox: [T] = [], outbox: [T] = []) {
self.inbox = inbox
self.outbox = outbox
}
}
์์ด๋์ด๋๋ก ํ์ ๋ค์ด์ค๋ ๋ฐ์ดํฐ๋ฅผ ๋ด๋นํ๋ inbox, ๋๊ฐ๋ ๋ฐ์ดํฐ๋ฅผ ๋ด๋นํ๋ outbox๋ฅผ ์์ฑํ์์ต๋๋ค.
์์ฑ์๋ฅผ ํตํด ์ด๋ฏธ ์กด์ฌํ๋ Array๋ก ํ๋ฅผ ์์ฑํ ์ ์๊ตฐ์
mutating func enqueue(element: T){
inbox.append(element)
}
mutating func dequeue()->T?{
if outbox.isEmpty{
//outbox.isEmpty == true ์ผ๋๋ง O(n)์ธ reverse()๋ฅผ ์ฌ์ฉํ๊ธฐ๋๋ฌธ์ ์ ์ฒด์ ์ผ๋ก๋ O(1)์ด๋ผ๊ณ ํ ์ ์์
outbox = inbox.reversed()
//Array.removeAll()์ keepingCapacity๊ฐ false์ผ ๋, O(1)์ Performance๋ฅผ ๊ฐ๋๋ค.
//https://stackoverflow.com/questions/54133045/performance-array-removeall-vs
inbox.removeAll()
}
return outbox.popLast()
}
๊ธฐ๋ณธ์ ์ธ ์ฝ์
, ์ญ์ ์ฐ์ฐ์ธ enqueue์ dequeue์
๋๋ค.
dequeue์ reversed ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ณ , ์ด๋ inbox๋ฅผ removeAll ํ๊ณ ์์ต๋๋ค.
(removeAll()์ ํธ์ถํ๋๊ฒ๊ณผ []๋ฅผ ๋์
ํ๋ ๊ฒ์ ์ด๋ค ์ฐจ์ด๊ฐ ์๋์ง ๊ถ๊ธํ์ง ์์ผ์ ๊ฐ์? ๊ทธ๊ฒ์ ๋ฐ๋ก ํฌ์คํ
ํ๋๋ก ํ๊ฒ ์ต๋๋ค.)
var isEmpty: Bool{
return outbox.isEmpty && inbox.isEmpty
}
var front: T?{
return outbox.isEmpty ? inbox.first : outbox.last
}
var rear: T?{
if outbox.isEmpty { return inbox.last }
return outbox.first
}
var count: Int{
return outbox.count + inbox.count
}
ํ์ ์ํ์ ๊ฐ์ฅ ์ต๊ทผ์ ์ถ๊ฐํ ์์ rear, ๊ฐ์ฅ ์ฒ์์ ์ถ๊ฐํ ์์ front ํ๋กํผํฐ๋ฅผ ๊ฐ์ต๋๋ค.
์ ์ฒด ์์ค์ฝ๋์
๋๋ค.
struct Queue<T>{
fileprivate var inbox: [T] = []
fileprivate var outbox: [T] = []
init(inbox: [T] = [], outbox: [T] = []) {
self.inbox = inbox
self.outbox = outbox
}
var isEmpty: Bool{
return outbox.isEmpty && inbox.isEmpty
}
var front: T?{
return outbox.isEmpty ? inbox.first : outbox.last
}
var rear: T?{
if outbox.isEmpty { return inbox.last }
return outbox.first
}
var count: Int{
return outbox.count + inbox.count
}
mutating func enqueue(element: T){
inbox.append(element)
}
mutating func dequeue()->T?{
if outbox.isEmpty{
//outbox.isEmpty == true ์ผ๋๋ง O(n)์ธ reverse()๋ฅผ ์ฌ์ฉํ๊ธฐ๋๋ฌธ์ ์ ์ฒด์ ์ผ๋ก๋ O(1)์ด๋ผ๊ณ ํ ์ ์์
outbox = inbox.reversed()
//Array.removeAll()์ keepingCapacity๊ฐ false์ผ ๋, O(1)์ Performance๋ฅผ ๊ฐ๋๋ค.
//https://stackoverflow.com/questions/54133045/performance-array-removeall-vs
inbox.removeAll()
}
return outbox.popLast()
}
}
๋ง๋ฌด๋ฆฌ
์ด๋ก์จ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ์ ์ํ ๊ตฌํ์ ๋์
๋๋ค.
์ Swift๋ ํ๋ฅผ ๋ด์ฅํ์ง ์์์.... ํ๋ฅผ ์ธ ๋ ๋ง๋ค ์ด ๊ณ ์์....
ํ๋ฅผ ๊ตฌํํ๋ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ ์ค, ์คํ์ 1๊ฐ๋ง ์ฌ์ฉํ์ฌ ๊ตฌํํ๋ ๋ฐฉ๋ฒ ๋ํ ์กด์ฌํฉ๋๋ค.
๊ทธ๊ฒ์ ๋ค์ ํฌ์คํ
์์!
2๋ถ์์ ๋ต๊ฒ ์ต๋๋ค.