【JavaScript数据结构——字典,hash表】

字典的增删改查以及字典的实际应用:hash表

字典的增删改查

function defaultToString(item) {
  if (item === null) {
    return "NULL";
  } else if (item === undefined) {
    return "UNDEFINED";
  } else if (typeof item === "string" || item instanceof String) {
    return `${item}`;//是字符串就直接返回
  }
  return item.toString();//否则调用toSring
}
//字典:table[key]={key,value}键值对
class valuePair {
  constructor(key, value) {
    this.value = value;
    this.key = key;
  }
  toString() {
    return `[${this.key}:${this.value}]`;
  }
}
class Dictionary {
  constructor(toStrFn = defaultToString) {
    this.toStrFn = toStrFn;
    this.table = {};
  }
  hasKey(key) {
    //JavaScript只允许我们使用字符串作为对象的键名或属性名。
    //如果传入一个复杂对象作为键,需要将它转化为一个字符串
    return this.table[this.toStrFn(key)] != null;
  }
  set(key, value) {
    if (key != null && value != null) {
      const tableKey = this.toStrFn(key);
      //每个元素都是一个键值对
      this.table[tableKey] = new valuePair(key, value);
      return true;
    }
    return false;
  }
  remove(key) {
    if (this.hasKey(key)) {
      delete this.table[this.toStrFn(key)];
      return true;
    }
    return false;
  }
  get(key) {
    const valuePair = this.table[this.toStrFn(key)];
    return valuePair == null ? undefined : valuePair.value;
  }
  keyValues() {
    //以数组形式返回字典所有valuePair:[{value:'abcd',key:'oyx'},{}]
    return Object.values(this.table);
  }
  keys() {
    //返回所有键名keys
    return this.keyValues().map((valuePair) => valuePair.key);
  }
  forEach(callbackFn) {
    //这个逻辑需要注意
    const valuePairs = this.keyValues(); // {1}
    for (let i = 0; i < valuePairs.length; i++) {
      // {2}
      const result = callbackFn(valuePairs[i].key, valuePairs[i].value); // {3}
      if (result === false) {
        break; // {4}
      }
    }
  }
  size() {
    return Object.keys(this.table).length;
  }
  isEmpty() {
    return this.size() === 0;
  }
  clear() {
    this.table = {};
  }
  toString() {
    if (this.isEmpty()) {
      return "";
    }
    const valuePairs = this.keyValues();
    let objString = `${valuePairs[0].toString()}`;
    for (let i = 1; i < valuePairs.length; i++) {
      objString = `${objString},${valuePairs[i].toString()}`;
    }
    return objString;
  }
}

字典的应用:hash表

区别在于增加了hashcode函数,先把key转成code值再放进去

hash表的实现

function defaultToString(item) {
  if (item === null) {
    return "NULL";
  } else if (item === undefined) {
    return "UNDEFINED";
  } else if (typeof item === "string" || item instanceof String) {
    return `${item}`;
  }
  return item.toString();
}
class valuePair {
  constructor(key, value) {
    this.value = value;
    this.key = key;
  }
  toString() {
    return `[${this.key}:${this.value}]`;
  }
}
class HashTable {
  constructor(toStrFn = defaultToString) {
    this.toStrFn = toStrFn;
    this.table = {};
  }
  djb2HashCode(key) {
    const tableKey = this.toStrFn(key); 
    let hash = 5381; 
    for (let i = 0; i < tableKey.length; i++) {
      hash = hash * 33 + tableKey.charCodeAt(i); 
    }
    return hash % 1013; 
  }

  hashCode(key) {
    return this.djb2HashCode(key);
  }
  put(key, value) {
    if (key != null && value != null) {
      const position = this.hashCode(key);
      this.table[position] = new valuePair(key, value);
      return true;
    }
    return false;
  }
  get(key) {
    const valuePair = this.table[this.hashCode(key)];
    return valuePair == null ? undefined : valuePair.value;
  }
  remove(key) {
    const hash = this.hashCode(key);
    const valuePair = this.table[hash];
    if (valuePair != null) {
      delete this.table[hash];
      return true;
    }
    return false;
  }
}

处理hash冲突:分离链表法

处理hash冲突:生成的code一致的问题
分离链接法:为散列表的每个位置生成一个链表

//处理hash冲突:生成的code一致的问题
//分离链接法:为散列表的每个位置生成一个链表
class HashTableSeparateChaining {
    constructor(toStrFn = defaultToString) {
      this.toStrFn = toStrFn;
      this.table = {};
    }
    put(key, value) {
        if (key != null && value != null) {
          const position = this.hashCode(key);
          if (this.table[position] == null) { 
            this.table[position] = new LinkedList(); 
          }
          this.table[position].push(new ValuePair(key, value)); //不同点
          return true;
        }
        return false;
    }
    get(key) {
        //把key转成code,找到位置后遍历list找到对应值
        const position = this.hashCode(key);
        const linkedList = this.table[position];
        if (linkedList != null && ! linkedList.isEmpty()) { 
          let current = linkedList.getHead(); 
          while (current != null) {
            if (current.element.key === key) {
              return current.element.value; 
            }
            current = current.next; 
          }
        }
        return undefined; 
    }
    remove(key) {
        //把key转成code,找到位置后遍历list找到对应值并删除,
        //删除后判断链表是否为空,为空就删除该位置
        const position = this.hashCode(key);
        const linkedList = this.table[position];
        if (linkedList != null && ! linkedList.isEmpty()) {
          let current = linkedList.getHead();
          while (current != null) {
            if (current.element.key === key) { 
              linkedList.remove(current.element); 
              if (linkedList.isEmpty()) { 
                delete this.table[position]; //链表为空就删除该位置
              }
              return true; 
            }
            current = current.next;
          }
        }
        return false;
      }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值