๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ–ฅ Computer Science/Data Structure

[Data Structure] ํ•ด์‰ฌ ํ…Œ์ด๋ธ”(Hash Table) ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ(feat. Swift)

by Fomagran ๐Ÿ’ป 2021. 11. 16.
728x90
๋ฐ˜์‘ํ˜•


์•ˆ๋…•ํ•˜์„ธ์š” 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

 

 

GitHub - raywenderlich/swift-algorithm-club: Algorithms and data structures in Swift, with explanations!

Algorithms and data structures in Swift, with explanations! - GitHub - raywenderlich/swift-algorithm-club: Algorithms and data structures in Swift, with explanations!

github.com

 

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€