javascript数据结构和算法——哈希表

javascript数据结构和算法——哈希表

哈希函数:将一个字符串转化成对应的下标的封装程序。
哈希表:据关键码值(Key value)而直接进行访问的数据结构。
哈细化:一个关键字将其转化成对应的数字,再将这个数据映射到对应的内存空间的范围,而这一映射的过程就是哈希化。
应用场景:
①如果在一个公司中,我想要根据一个人名,来查找这个人的全部信息如果按照直接查找,效率太低。而使用哈希表,可以将人名转化成对应的下标,根据下标来查找,可以提高效率。
②、可以应用在字典的查找与搜索过程中。
步骤一:
先将对应的字符根据对应的编码转化成数字。
步骤二
因为步骤一得到的数字太大,所以可以进行哈希化,就是根据一个操作将其转化成给定范围的地址。
步骤三:
如果出现冲突的情况,可以有两种操作的:一:开放地址法,二:链地址法,接下来的操作我们会使用链地址法进行相关的操作。
链地址法“:
javascript数据结构和算法——哈希表_第1张图片
上面的图就是链地址法的相关操作,将地址重复的数据全部在用指针指向一个数组。
代码操作
这里我们将哈希表封装成一个构造函数
需要的数据:①整个哈希表全部数据
②哈希表中限制长度
③哈希表中的元素数量
需要的方法:
①放入元素
②获取元素
③修改元素
④删除元素
⑤判断是否为空
⑥输出元素个数
⑦扩展空间

<script>
function hashTable() {
  this.storage = [];
  this.limit = 7;
  this.count = 0;
  hashTable.prototype.hashFunc = function (str, size) {
    let hashCode = 0;
    for (let i = 0; i < str.length; i++) {
      hashCode = hashCode * 37 + str.charCodeAt(i);
    }
    let hash = hashCode % size;
    return hash;
  }
  // 添加、更改哈希函数中的值
  hashTable.prototype.push = function (key, value) {
    // 先用哈希函数将其转化
    let index = this.hashFunc(key, this.limit);
    let bucket = this.storage[index];
    if (bucket == null) {
      bucket = [];
      this.storage[index] = bucket;
    }
    for (let i = 0; i < bucket.length; i++) {
      if (key == bucket[i][0]) {
        bucket[i][1] = value;
        return;
      }
    }
    // 指向到这里就不存在,则直接插入
    bucket.push([key, value]);
    this.count++;
    if (this.count >= this.limit * 0.75) {
      this.limit = this.getPrime(this.limit * 2);
      this.resize(this.limit);
    }
  }
  // 获取操作
  hashTable.prototype.get = function (key) {
    let index = this.hashFunc(key, this.limit);
    let bucket = this.storage[index];
    if (bucket == null) {
      return null;
    }
    for (let i = 0; i < bucket.length; i++) {
      if (key == bucket[i][0]) {
        return bucket[i][1];
      }
    }
    // 执行到这里说明不存在该值
    return null;
  }
  // 删除方法
  hashTable.prototype.remove = function (key) {
    let index = this.hashFunc(key, this.limit);
    let bucket = this.storage[index];
    if (bucket == null) {
      return null;
    }
    for (let i = 0; i < bucket.length; i++) {
      if (key == bucket[i][0]) {
        this.count--;
        if (this.limit <= 7 && this.count <= this.limit * 0.25) {
          this.limit = this.getPrime(this.limit);
          this.resize(this.limit);
        }
        return bucket[i][1];
      }
    }
    return null;
  }
  // 判断是否哈希表是否为空
  hashTable.prototype.isEmpty = function () {
    return this.count == 0;
  }
  // 输出哈希表的长度
  hashTable.prototype.size = function () {
    return this.count;
  }
  // 判断是否为质数
  hashTable.prototype.isPrime = function (num) {
    let sqrt = Math.sqrt(num);
    for (let i = 2; i <= sqrt; i++) {
      if (num % i == 0) {
        return false;
      }
    }
    return true;
  }
  // 获取一个质数
  hashTable.prototype.getPrime = function (num) {
    while (!this.isPrime(num)) {
      num++;
    }
    return num;
  }
  // 设置扩容,缩容操作
  hashTable.prototype.resize = function (newList) {
    // 重新定义变量
    let oldStorage = this.storage;
    this.storage = [];
    this.count = 0;
    this.limit = newList;
    for (let i = 0; i < oldStorage.length; i++) {
      let busket = oldStorage[i];
      if (busket == null) {
        continue;
      }
      for (let j = 0; j < busket.length; j++) {
        var tuple = busket[j];
        this.push(tuple[0],tuple[1]);
      }
    }
  }
}
let hs = new hashTable();
hs.push("dl", '201902091');
hs.push("xsy", "201902018");
console.log(hs);
hs.push("zcc", '201902091');
hs.push("bjr", "201902018");
hs.push("fzl", '201902091');
hs.push("hst", "201902018");
console.log(hs);
script>

解析:上面是完整的代码,其中包含扩容和缩容的操作,原因是:在哈希表中,如果在多余的元素中,使用链地址法,则可以存放无数个元素,当元素的个数多的时候,查找时,消耗的时间以及其效率都会增多。所以当满足某一个条件时,执行扩容操作。当满足某一个条件时,进行缩容操作,因为当元素个数较少时,如果容积比较大,比较浪费内存空间。
并且在上面代码中,增加了查找质数的函数,因为当哈希表的空间范围是质数的时候,元素分布比较均匀。

你可能感兴趣的:(数据结构,算法,javascript,数据结构,算法,哈希表)