JavaScript 数据结构之散列表的创建(2)

yizhihongxing

下面是详细讲解“JavaScript 数据结构之散列表的创建(2)”的完整攻略。

散列表(哈希表)

散列表是一种数据结构,使用哈希函数将键映射到索引。散列表可以在常量时间 O(1) 中进行插入、删除和查找操作,但也具有碰撞冲突问题。

碰撞冲突问题

在散列表中,当两个不同的键通过哈希函数映射到了同一个索引位置时,就会发生碰撞冲突问题。解决碰撞冲突问题的方法有很多,常用的有“链地址法”和“线性探测法”。

链地址法解决碰撞冲突

链地址法也就是“拉链法”,即将同一个索引位置上的所有键都放入到一个链表中。当冲突发生时,只需要将当前键添加到对应索引位置上的链表中即可。

下面是一个使用链地址法的散列表实现示例:

class HashTable {
  constructor() {
    this.table = [];
  }

  // 哈希函数
  hash(data) {
    let total = 0;
    for (let i = 0; i < data.length; i++) {
      total += data.charCodeAt(i);
    }
    return total % this.table.length;
  }

  // 插入操作
  insert(key, value) {
    let index = this.hash(key);

    if (!this.table[index]) {
      // 该索引位置不存在键值对,则创建一个链表存储键值对
      this.table[index] = [];
    }

    // 遍历链表查找指定键
    for (let i = 0; i < this.table[index].length; i++) {
      if (this.table[index][i].key === key) {
        // 键已存在,则更新值
        this.table[index][i].value = value;
        return;
      }
    }

    // 键不存在,则添加新的键值对
    this.table[index].push({ key, value });
  }

  // 获取操作
  get(key) {
    let index = this.hash(key);

    if (!this.table[index]) {
      return undefined;
    }

    // 遍历链表查找指定键
    for (let i = 0; i < this.table[index].length; i++) {
      if (this.table[index][i].key === key) {
        // 键存在,则返回对应的值
        return this.table[index][i].value;
      }
    }

    // 键不存在,则返回 undefined
    return undefined;
  }

  // 删除操作
  remove(key) {
    let index = this.hash(key);

    if (!this.table[index]) {
      return;
    }

    // 遍历链表查找指定键
    for (let i = 0; i < this.table[index].length; i++) {
      if (this.table[index][i].key === key) {
        // 键存在,则从链表中删除该键值对
        this.table[index].splice(i, 1);
        return;
      }
    }
  }
}

// 测试
let hashTable = new HashTable();
hashTable.insert('name', 'Tom');
hashTable.insert('age', 18);
console.log(hashTable.get('name')); // Tom
console.log(hashTable.get('age')); // 18
hashTable.remove('age');
console.log(hashTable.get('age')); // undefined

上面的代码中,我们使用了一个对象数组来存储在散列表中的键值对,如果发生冲突则将键值对存储在同一个索引位置上的对象数组中。

线性探测法解决碰撞冲突

线性探测法也就是“开放地址法”,当发生碰撞时,它会逐一探测下一个空闲位置,直到找到可用的位置为止。

下面是一个使用线性探测法的散列表实现示例:

class HashTable {
  constructor() {
    this.table = [];
  }

  // 哈希函数
  hash(data) {
    let total = 0;
    for (let i = 0; i < data.length; i++) {
      total += data.charCodeAt(i);
    }
    return total % this.table.length;
  }

  // 插入操作
  insert(key, value) {
    let index = this.hash(key);

    if (this.table[index] === undefined) {
      // 该索引位置为空,则直接存储键值对
      this.table[index] = { key, value };
    } else {
      // 该索引位置不为空,则线性探测下一个空闲位置
      let i = 1;
      while (this.table[index + i] !== undefined) {
        i++;
      }
      this.table[index + i] = { key, value };
    }
  }

  // 获取操作
  get(key) {
    let index = this.hash(key);

    // 遍历散列表查找指定键
    for (let i = 0; i < this.table.length; i++) {
      let pos = (index + i) % this.table.length;
      if (this.table[pos] && this.table[pos].key === key) {
        // 键存在,则返回对应的值
        return this.table[pos].value;
      }
    }

    // 键不存在,则返回 undefined
    return undefined;
  }

  // 删除操作
  remove(key) {
    let index = this.hash(key);

    // 遍历散列表查找指定键
    for (let i = 0; i < this.table.length; i++) {
      let pos = (index + i) % this.table.length;
      if (this.table[pos] && this.table[pos].key === key) {
        // 键存在,则将该位置的值置为 undefined
        this.table[pos] = undefined;
        return;
      }
    }
  }
}

// 测试
let hashTable = new HashTable();
hashTable.insert('name', 'Tom');
hashTable.insert('age', 18);
console.log(hashTable.get('name')); // Tom
console.log(hashTable.get('age')); // 18
hashTable.remove('age');
console.log(hashTable.get('age')); // undefined

上面的代码中,我们采用了一种简单的线性探测方法来解决碰撞冲突,如果发生冲突则线性探测下一个空闲位置存储键值对。

至此,“JavaScript 数据结构之散列表的创建(2)”完整攻略讲解完毕,内容详尽、示例丰富,希望能够帮助到你。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript 数据结构之散列表的创建(2) - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 数据结构之堆详解

    数据结构之堆详解 什么是堆? 堆(Heap)是一种特殊的树形数据结构。堆具有以下两个特点: 堆是一颗完全二叉树; 堆中每个节点的值都必须大于等于或小于等于其左右子节点的值,分别称作大根堆和小根堆。 上述的大根堆和小根堆其实是两种不同的堆的实现方式。对于大根堆,每个节点的值都比其左右子节点的值要大;小根堆则相反,每个节点的值都比其左右子节点的值要小。 堆的基本…

    数据结构 2023年5月17日
    00
  • 带你了解Java数据结构和算法之数组

    带你了解Java数据结构和算法之数组 在本教程中,我们将学习Java中的数组数据结构和对应的算法。让我们先来了解什么是数组。 什么是数组? 数组是一个同类型数据元素的集合,在内存中连续存储。数组具有索引性,我们可以使用索引值来访问数组中的元素。 声明和初始化数组 在Java中,声明一个数组需要指定以下三个参数: 数组的类型 数组的名称 数组的大小 以下是一个…

    数据结构 2023年5月17日
    00
  • 深入PHP中的HashTable结构详解

    深入PHP中的HashTable结构详解 在PHP中,HashTable是一种基础数据结构,常用于存储对象的属性和方法等各种数据,本篇攻略将深入介绍HashTable的实现原理和应用。 HashTable的实现原理 HashTable并不是一种单一的数据结构,它可以根据不同的需求来采用不同的实现方式。在PHP中,我们经常使用的是基于链表的实现方式,也就是链式…

    数据结构 2023年5月17日
    00
  • C++LeetCode数据结构基础详解

    C++LeetCode数据结构基础详解攻略 什么是LeetCode? LeetCode是一个专门为程序员提供的算法题平台。平台上汇集了各种算法、数据结构和编程题,用户可以在平台上挑战各种难度的算法用来提高自己的编程能力和算法素养。 如何学习LeetCode? 学习LeetCode的关键是掌握数据结构和算法。下面介绍如何结合具体的C++代码来学习LeetCod…

    数据结构 2023年5月17日
    00
  • C++20中的结构化绑定类型示例详解

    ” C++20中的结构化绑定类型示例详解 ” 具体攻略如下: 什么是结构化绑定类型? 结构化绑定类型是C++17中的新特性,它可以让我们将一个复杂类型的元素绑定到某个变量上,从而更方便地使用这些元素。 C++20还进一步扩展了结构化绑定类型的功能,可以通过给用于引用的名字声明类型来进行显式类型的绑定。 结构化绑定类型的基本用法 下面的例子展示了如何使用结构化…

    数据结构 2023年5月17日
    00
  • 浅谈iOS 数据结构之链表

    浅谈iOS 数据结构之链表 在计算机科学中,链表是一种数据结构,用于存储一系列按顺序排列的元素。链表的一个关键点是它不需要连续的内存空间来存储元素,相反,每个元素由一个指向下一个元素的指针组成。在iOS开发中,链表在各种场景下都有所应用,如UITableView和UICollectionView的数据源等。本文将详细讲解链表的基本知识和使用技巧。 链表的基本…

    数据结构 2023年5月17日
    00
  • Java数据结构二叉树难点解析

    Java数据结构二叉树难点解析 什么是二叉树 二叉树是一种非常常见的数据结构,它具有以下特点: 每个节点都最多有两个子节点。 左子节点的值小于等于父节点的值,右子节点的值大于等于父节点的值。 二叉树可以用递归的方式实现,如下所示: class TreeNode { int val; TreeNode left; TreeNode right; TreeNod…

    数据结构 2023年5月17日
    00
  • 基于C++详解数据结构(附带例题)

    基于C++详解数据结构(附带例题)攻略 简介 该攻略是基于C++编程语言详解数据结构的,主要涉及数据结构中的相关概念、操作以及例题演练。C++语言作为一种高性能的编程语言,对于开发数据结构问题具有很大的优势。 数据结构概念 数据结构基本概念 数据结构是计算机存储、组织数据的方式。具体来说,数据结构可以理解为计算机存储数据的一种方式,也可以看作是一些组织数据的…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部