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

下面是详细讲解“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日

相关文章

  • 多维度深入分析Redis的5种基本数据结构

    多维度深入分析Redis的5种基本数据结构 Redis是一种高性能、内存数据存储系统,它支持多种数据结构,包括字符串、哈希表、列表、集合和有序集合。其中,每种数据结构都具有不同的特性和用途,本文将对这五种基本数据结构进行深入分析。 1. 字符串(string) 字符串是最基本的数据结构,一个字符串可以存储任意二进制数据,例如一个jpg图片或者一个序列化的对象…

    数据结构 2023年5月17日
    00
  • Redis底层数据结构详解

    Redis底层数据结构详解 前言 Redis是一款开源的,高性能的,基于内存的数据结构存储系统。Redis支持多种数据结构,包括简单的键值对、列表、集合、有序集合等等。本篇文章将深入分析Redis的底层数据结构,介绍它们的原理、优缺点和适用场景。 1. 哈希表(Hash Table) 哈希表是Redis中最常用的底层数据结构之一。可以通过以下命令在Redis…

    数据结构 2023年5月17日
    00
  • 纯C++代码详解二叉树相关操作

    纯C++代码详解二叉树相关操作 介绍 二叉树是一种非常常见的数据结构,适用于处理需要具有层级关系的数据。在本文中,我们将详细讲解如何使用C++来实现二叉树的基本操作,包括创建、遍历、插入、删除等。 创建二叉树 定义二叉树节点 在C++中实现二叉树的概念,需要先定义二叉树节点的结构,代码如下: struct BinaryTreeNode { int value…

    数据结构 2023年5月17日
    00
  • C语言 数据结构之数组模拟实现顺序表流程详解

    C语言 数据结构之数组模拟实现顺序表流程详解 什么是顺序表? 顺序表是一种基于连续存储结构的数据结构,它可以用一段连续的存储单元来存储线性表中的所有元素。 顺序表的实现思路 顺序表的实现主要依赖数组。我们可以定义一个数组来存储线性表的数据元素,同时再定义一个变量来保存线性表当前的长度。当需要对线性表进行插入、删除、查找等操作时,根据需求,可以通过数组的下标来…

    数据结构 2023年5月17日
    00
  • 图解AVL树数据结构输入与输出及实现示例

    请允许我为您详细讲解“图解AVL树数据结构输入与输出及实现示例”的完整攻略。 标题 AVL树数据结构简介 AVL树是一种平衡二叉搜索树,是由G.M. Adelson-Velsky和E.M. Landis在1962年发明的。它的特点是带有平衡条件,任意节点的左右子树高度差不超过1,通过左旋、右旋、左右旋、右左旋四种形态的调整操作,来维护树的平衡。这样可以保证树…

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

    带你了解Java数据结构和算法之哈希表 前言 哈希表是一种常用的数据结构,它可以高效地存储和查询数据。在计算机科学领域,哈希表广泛用于实现关联数组(Associative Array)和哈希集合(Hash Set)。本文将带领大家深入了解哈希表数据结构及常用算法实现。 哈希表的原理 哈希表是根据关键码值(Key Value)而直接进行访问的数据结构。也就是说…

    数据结构 2023年5月17日
    00
  • Golang实现数据结构Stack(堆栈)的示例详解

    Golang实现数据结构Stack(堆栈)的示例详解 什么是Stack? Stack,也称为堆栈,是一种先进后出(Last In First Out, LIFO)的数据结构。举个例子,比如一堆书,你按照一定的顺序叠起来,然后你想要拿出第一本,你需要先拿掉上面的书才能取到下面的。这就是典型的堆栈模型。 在编程中,Stack也是一种非常常见的数据结构,特别是在函…

    数据结构 2023年5月17日
    00
  • 中国剩余定理(CRT)学习笔记

    约定 \(A\perp B\) 表示 \(\gcd(A,B)=1\)。 \(A\mid B\) 表示 \(B\equiv 0\pmod{A}(A\neq0)\)。 引入 考虑以下这道题: 有物不知其數,三三數之剩二,五五數之剩三,七七數之剩二。 問物幾何?—— 《孫子算經》 也就是说,求出下列关于 \(x\) 方程组的最小整数解: \[\begin{case…

    算法与数据结构 2023年4月30日
    00
合作推广
合作推广
分享本页
返回顶部