實現數據結構:哈希表。swift
/* * 哈希表Key須要遵照的協議 * 用於生成hash值,即hash函數 */
public protocol HashedKey {
var hashValue: UInt32 { get }
}
/* * 哈希表內部元素表示 */
fileprivate struct HashElement<Key, Value>{
var key: Key;
var value: Value;
}
/* * 哈希表 */
public class Hash<Key, Value> where Key: HashedKey, Key: Equatable{
///內部數組
private var _storeArr:[HashElement<Key, Value>?];
///當前元素數量
private var _storeCount = 0;
///最小元素數量
private let MINSIZE = 1;
/* * 構造方法 */
public init() {
_storeArr = Array<HashElement<Key, Value>?>.init(repeating: nil, count: MINSIZE);
}
/** * 將內部數組的尺寸擴充爲2倍大小 */
private func _expand(){
let oldArr = _storeArr;
_storeArr = Array<HashElement<Key, Value>?>.init(repeating: nil, count: _storeArr.count * 2);
_storeCount = 0;
for case let e? in oldArr {
set(k: e.key, v: e.value);
}
}
/** * 插入數值 * @param {Key} - k 插入的key * @param {Value} - v 插入的value */
public func set(k: Key, v: Value){
if let i = self._index(k: k){
_storeArr[i]?.value = v;
return;
}
let capacity = _storeArr.count;
let hashValue = k.hashValue;
var idx = Int(hashValue) % capacity;
while _storeArr[idx] != nil {
idx = (idx + 1) % capacity;
}
_storeArr[idx] = HashElement.init(key: k, value: v);
_storeCount += 1;
if _storeCount >= capacity * 3 / 4 {
_expand();
}
}
/** * 查找參數k對應的數組下標值,用於判斷元素是否存在 * @param {Key} - k 傳入key值 * @return {Int?} - 返回數組下標,若key不存在,則返回nil */
private func _index(k: Key) -> Int?{
let capacity = _storeArr.count;
var idx = Int(k.hashValue) % capacity;
var count = 0;
while _storeArr[idx] != nil && _storeArr[idx]!.key != k && count < capacity {
idx = (idx + 1) % capacity;
count += 1;
}
if _storeArr[idx] != nil && count < capacity {
return idx;
}else{
return nil;
}
}
/** * 獲取數值 * @param {Key} - k 想要獲取數值的key * @return {Value?} - 返回的value */
public func get(k: Key) -> Value?{
if let i = self._index(k: k){
return _storeArr[i]?.value;
}else{
return nil;
}
}
/** * 支持以下操做: * hash[key] = value * let v = hash[key] */
public subscript(k: Key)->Value?{
set{
if case let v? = newValue {
set(k: k, v: v)
}
}
get{
return get(k: k);
}
}
}
複製代碼
function Hash(hashFunction) {
this._elements = new Array(1);
this._elementsCount = 0;
this._hashFunc = hashFunction;
}
Hash.prototype._expand = function(){
let capacity = this._elements.length;
let oldElements = this._elements;
this._elements = new Array(capacity * 2);
oldElements.forEach(element => {
this.set(element.key, element.value);
});
}
Hash.prototype.set = function(k, v){
let index = this._index(k);
if(index != undefined && this._elements[index] != v){
this._elements[index] = v;
return;
}
let capacity = this._elements.length;
let hashValue = this._hashFunc(k) % capacity;
while (this._elements[hashValue]) {
hashValue = (hashValue + 1) % capacity;
}
this._elements[hashValue] = {key:k, value:v};
this._elementsCount++;
if(this._elementsCount >= capacity * 3 / 4){
this._expand();
}
}
Hash.prototype._index = function(k){
let capacity = this._elements.length;
let hashValue = this._hashFunc(k) % capacity;
let count = 0;
while(this._elements[hashValue] && this._elements[hashValue].key != k && count < capacity){
hashValue = (hashValue + 1) % capacity;
count++;
}
if(this._elements[hashValue] && count < capacity){
return hashValue;
}
}
Hash.prototype.get = function(k){
let index = this._index(k);
if(index != undefined) {
return this._elements[index];
}
}
複製代碼