์๋
ํ์ธ์ Foma ๐ป ์
๋๋ค!
์ค๋์ ์ ๋ฒ ๊ธ์์ ํด์ฌ ํ
์ด๋ธ์ ์ด๋ก ์ ์ด์ด์ ์ง์ ๊ตฌํํด ๋ณด๋ ค๊ณ ํฉ๋๋ค!
(ํน์ ์ ๋ฒ ๊ธ์ ์๋ณด์
จ๋ค๋ฉด ์ฌ๊ธฐ ๋ฅผ ํตํด์ ๋ณด๊ณ ์์ฃผ์ธ์~)
๋ฐ๋ก ์์ํ ๊ฒ์~
HashTable
๋จผ์ ์ ๋ ํด์ฌ ํจ์๋ฅผ Digit Folding ์๊ณ ๋ฆฌ์ฆ์ ์ด์ฉํด์ ๋ง๋ค ๊ฒ์ด๊ธฐ ๋๋ฌธ์ key๊ฐ์ String์ผ๋ก ์ค์ ํ์ต๋๋ค.
๋ํ ์ถฉ๋์ด ๋ฌ์ ๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก Chaining ๊ธฐ๋ฒ์ ์ฌ์ฉํ์์ง๋ง ์ฐ๊ฒฐ ๋ฆฌ์คํธ ๋์ ๋ฐฐ์ด์ ์ฌ์ฉํ์ต๋๋ค.
์๋์ ๊ฐ์ด typealias๋ก ๋ณ์นญ์ ์ค์ ํด์ฃผ๊ณ ๋ฒํท์ ์ด์ค๋ฐฐ์ด๋ก ์ ์ธํ์ต๋๋ค.
public struct HashTable<String,Value> {
public typealias Key = String
private typealias Element = (key:Key,value:Value)
private var bucket:[[Element]] = [] ...
Initialize
์ด๊ธฐํ๋ ํด์ฌ ํ
์ด๋ธ์ ๋ง๋ค ๋ ๋ฒํท์ฌ์ด์ฆ๋ฅผ ์ค์ ํ๋๋ก ํด๋๊ณ ๊ทธ ํฌ๊ธฐ๋งํผ ๋ฒํท์ ๋ง๋ค์ด์ฃผ์์ต๋๋ค.
public init(bucketSize:Int) {
bucket = Array<[Element]>(repeating:[], count: bucketSize)
}
subscript๋ฅผ ์ฌ์ฉํด์ get์ผ ๋ key๊ฐ์ ๋ฐ๋ผ value๋ฅผ ๋ฐํํ๊ณ , set์ผ ๋ nil์ด ์๋๋ผ๋ฉด ์๋ก์ด ๊ฐ์ผ๋ก update๋ฅผ ํด์ฃผ๊ณ
nil์ด๋ผ๋ฉด ์ญ์ ๋ฅผ ํ์ต๋๋ค.
public subscript(key: String) -> Value? {
get {
return value(forKey: key)
}
set {
if let value = newValue {
updateValue(value, forKey: key)
} else {
removeValue(forKey: key)
}
}
}
Hash Function
index๋ฅผ ์ฐพ๊ธฐ ์ํ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์์ ์ค๋ช
ํ๋ค์ํผ digitFolding์ ์ฌ์ฉํด์ ๋ฐํํด ์ค๋๋ค.
private func findIndexByDigitFolding(forKey key:Key) -> Int {
return "\(key)".unicodeScalars.reduce(0, { $0 + Int($1.value) }) % bucket.count
}
Search
key๊ฐ์ ๋ฐ๋ฅธ value๊ฐ์ ๋ฐํํ ๋๋ ์๋์ ๊ฐ์ด index๋ฅผ digitFoliding์ผ๋ก key๊ฐ์ ๋ณํํด์ค ๊ฐ์ผ๋ก ์ค์ ํ๊ณ ,
๋ฒํท ์์ index์ ๋ฐฐ์ด ์์์ ํ์ฌ key๊ฐ๊ณผ ๊ฐ์ ๊ฐ์ ๊ฐ์ง value๋ฅผ ๋ฐํํด์ฃผ๊ณ ์๋ค๋ฉด nil์ ๋ฐํํด์ค๋๋ค.
public func value(forKey key: Key) -> Value? {
let index = findIndexByDigitFolding(forKey: key)
for element in bucket[index] {
if "\(element.key)" == "\(key)" {
return element.value
}
}
return nil
}
Append(Update)
๊ฐ์ ์ฝ์ผํ ๋ ๋ฒํท ์์ ๊ฐ๋ค์ ์ฐพ์์ ๋ง์ฝ ์๋ค๋ฉด update๋ฅผ ํ๊ณ ์๋ค๋ฉด append๋ฅผ ํด์ฃผ์์ต๋๋ค.
public mutating func updateValue(_ value: Value, forKey key: Key) {
let index = findIndexByDigitFolding(forKey: key)
for (i, element) in bucket[index].enumerated() {
if "\(element.key)" == "\(key)" {
bucket[index][i].value = value
}
}
bucket[index].append((key: key, value: value))
}
Remove
์ญ์ ๋ ๋ฒํท์ ํด๋น index์ ์๋ ๋ฐฐ์ด ์์ ๋๊ฐ์ key๊ฐ์ ์ฐพ์ nil๋ก ๋ง๋ค์ด ์ค๋๋ค.
public mutating func removeValue(forKey key: Key) {
let index = findIndexByDigitFolding(forKey: key)
for (i, element) in bucket[index].enumerated() {
if "\(element.key)" == "\(key)" {
bucket[index].remove(at: i)
}
}
}
์คํ๊ฒฐ๊ณผ
var hashTable = HashTable<String, Any>(bucketSize: 13) //์ฝ์
hashTable["foma"] = "foma"
hashTable["gran"] = "gran" //์ถฉ๋(foma์ mofa๋ digitfolding์ ์ํด ๋๊ฐ์ ์ธ๋ฑ์ค๊ฐ ๋์ต๋๋ค.)
hashTable["mofa"] = "mofa"
print(hashTable["foma"],hashTable["gran"],hashTable["mofa"],hashTable["fomagran"]) //Optional("foma") Optional("gran") Optional("mofa") nil
hashTable["foma"] = nil //์ญ์
hashTable["gran"] = "foma" //์
๋ฐ์ดํธ
print(hashTable["foma"],hashTable["gran"],hashTable["mofa"],hashTable["fomagran"]) //nil Optional("foma") Optional("mofa") nil
Reference
๋๊ธ