数据结构Typescript之哈希表实现详解

数据结构Typescript之哈希表实现详解

什么是哈希表

哈希表(Hash Table)又称为散列表,是一种根据关键字(Key)直接访问内存存储位置的数据结构。通俗的解释就是利用一个哈希函数(Hash Function)将关键字映射到哈希表中的一个位置(索引)来进行访问,从而快速、高效地查找、插入、删除元素。

哈希表的实现

本文将介绍使用Typescript实现一种基于闭散列(Closed Hashing,也称为拉链法Chaining)的简单哈希表。以下为该哈希表的基本实现思路:

  1. 声明一个“链表节点”类,用于存储哈希表中的元素;
  2. 声明一个哈希表类,该类包含以下方法:
  3. hash(key: string): number:基于关键字计算索引值;
  4. put(key: string, value: any): void:向哈希表中插入元素;
  5. remove(key: string): boolean:从哈希表中删除元素;
  6. get(key: string): any:在哈希表中查找指定的元素;
  7. print(): void:输出哈希表的所有元素。

下面让我们详细看一下这些方法的实现。

基于链表节点实现哈希表元素

先声明一个“链表节点”类,用于存储哈希表中的元素,包含元素的关键字(key)和值(value)两个属性:

class Node {
  constructor(public key: string, public value: any) {}
}

基于闭散列实现哈希表

接下来,我们需要根据关键字计算出哈希表元素的索引位置。为了能够直接通过关键字来计算哈希表元素的索引位置,我们需要编写一个哈希函数。这里我们使用最简单的字符串哈希函数——将字符串按字符拆分,并将其所在字符位置的ASCII值相加,得出的结果再取余哈希表的长度,得到哈希表元素的索引位置:

class HashTable {
  private table: any[] = [];

  private loseloseHashCode(key: string): number {
    let hash = 0;
    for (let i = 0; i < key.length; i++) {
      hash += key.charCodeAt(i);
    }
    return hash % this.table.length;
  }
}

在上述代码中,我们通过table数组来存储哈希表,loseloseHashCode函数就是我们的哈希函数。

插入元素

知道如何计算关键字的哈希值之后,我们就可以向哈希表中插入元素了。插入元素有两种情况:

  1. 当哈希表中不存在该关键字时,直接将元素添加到哈希表中;
  2. 当哈希表中已经存在该关键字时,更新该元素的值。

代码如下:

class HashTable {
  // ...

  public put(key: string, value: any): void {
    const position = this.loseloseHashCode(key);
    if (this.table[position] === undefined) {
      this.table[position] = new LinkedList();
    }
    this.table[position].append(new Node(key, value));
  }
}

当table数组中的某个元素为undefined时,说明该位置上未曾插入过元素。我们可以新建一个链表,并将该元素插入到链表的末尾。

当table数组中已经存在某个链表时,说明该位置上已经有元素,我们只需将新元素插入到该链表的末尾即可。

删除元素

删除元素也有两种情况:

  1. 当哈希表中不存在该关键字时,直接返回false;
  2. 当哈希表中存在该关键字时,删除该元素并返回true。

代码如下:

class HashTable {
  // ...

  public remove(key: string): boolean {
    const position = this.loseloseHashCode(key);
    const list = this.table[position];
    if (list !== undefined && !list.isEmpty()) {
      let current = list.getHead();
      while (current !== null) {
        if (current.element.key === key) {
          list.remove(current.element);
          if (list.isEmpty()) {
            this.table[position] = undefined;
          }
          return true;
        }
        current = current.next;
      }
    }
    return false;
  }
}

首先我们和插入操作一样找到该关键字所在的索引位置position以及对应的链表list。然后用循环遍历该链表,找到指定的元素,并将其从链表中删除。最后,我们还需要检查该链表是否为空,如果为空,需要将table数组中该元素的值设为undefined。

查找元素

查找元素也是基于关键字计算出哈希值,然后获取该关键字在哈希表中对应的链表。查找元素的方法只需要顺序遍历该链表,并返回找到的元素即可:

class HashTable {
  // ...

  public get(key: string): any {
    const position = this.loseloseHashCode(key);
    const list = this.table[position];
    if (!list.isEmpty()) {
      let current = list.getHead();
      while (current !== null) {
        if (current.element.key === key) {
          return current.element.value;
        }
        current = current.next;
      }
    }
  }
}

输出哈希表元素

输出哈希表的所有元素非常简单,只需要遍历每个链表并输出其节点元素的key和value属性即可:

class HashTable {
  // ...

  public print(): void {
    for (let i = 0; i < this.table.length; i++) {
      const list = this.table[i];
      if (list !== undefined && !list.isEmpty()) {
        let current = list.getHead();
        while (current !== null) {
          console.log(`${current.element.key} -> ${current.element.value}`);
          current = current.next;
        }
      }
    }
  }
}

示例说明

我们可以尝试向哈希表中插入以下元素:

const hashTable = new HashTable();
hashTable.put("Tom", "programmer");
hashTable.put("Jerry", "designer");
hashTable.put("Mary", "teacher");
hashTable.put("Peter", "student");
hashTable.put("John", "doctor");

然后,我们可以查找哈希表中的某个元素:

hashTable.get("Mary"); // "teacher"

或者从哈希表中删除某个元素:

hashTable.remove("Peter"); // true
hashTable.get("Peter"); // undefined

最后输出整个哈希表中的元素:

hashTable.print();

输出结果如下:

Tom -> programmer
Jerry -> designer
Mary -> teacher
John -> doctor

结论

借助于Typescript强大的类型检查功能,我们可以在代码编写的过程中更加自信和高效地开发出高质量的数据结构。虽然这种实现方式可能不是最高效的,但它值得我们学习和掌握,并为我们日常工作中的需求提供了不同的思路和实现方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:数据结构Typescript之哈希表实现详解 - Python技术站

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

相关文章

  • 浅谈Java数据结构之稀疏数组知识总结

    浅谈Java数据结构之稀疏数组知识总结 稀疏数组的定义 稀疏数组是指当一个数组中大部分元素是相同的值时,可以使用稀疏数组来保存该数组。稀疏数组的必要性在于节省内存空间,当数组中元素过多时,存储数组所需的内存空间也呈指数级增长。 稀疏数组的特点 稀疏数组存储的是一个原始的二维数组。 稀疏数组的第一行保存原始数组的基本信息,包括行数、列数、有效值的个数。 稀疏数…

    数据结构 2023年5月17日
    00
  • C语言结构体struct详解

    C语言结构体struct详解 什么是结构体? 在C语言中,结构体是一种用户自定义的数据类型,它可以将不同的数据类型组合在一起形成一个新的数据类型。结构体主要由结构体名、成员和符号构成。 使用结构体可以方便地定义一些复杂的数据类型,例如表示一个学生信息的数据类型,可以包括姓名、学号、性别、年龄等信息。 结构体的定义和声明 结构体的定义通常放在函数外部,以便在整…

    数据结构 2023年5月17日
    00
  • java数据结构基础:线性表

    Java数据结构基础:线性表 简介 线性表是指数据元素之间存在线性关系的数据结构,即数据元素之间有前后直接关系,且第一个元素没有前驱,最后一个元素没有后继。线性表可以用数组或者链表两种方式实现。 数组实现线性表 线性表的数组实现即为将线性表中的元素放在一个一维数组中,使用数组下标表示元素的位置。由于数组随机访问元素的时间复杂度为O(1),因此在随机访问比较多…

    数据结构 2023年5月17日
    00
  • 莫比乌斯反演,欧拉反演学习笔记

    (未更完) 我算法中也就差点数论没学了,这几周卷了,学了一下,分享一下啊。 我会讲得详细一点,关于我不懂得地方,让新手更容易理解。 学习反演有很多定义啥的必须要记的,学的时候容易崩溃,所以希望大家能坚持下来。   第一个定义: $\lfloor x\rfloor$:意思是小于等于 $x$ 的最大整数。 数论分块 学习反演之前,要先学习一些边角料,先来看数论分…

    算法与数据结构 2023年4月17日
    00
  • PAT甲级真题1020.树的遍历

    翻译和代码思路:Acwing 一个二叉树,树中每个节点的权值互不相同。 现在给出它的后序遍历和中序遍历,请你输出它的层序遍历。 输入格式 第一行包含整数 N,表示二叉树的节点数。 第二行包含 N个整数,表示二叉树的后序遍历。 第三行包含 N 个整数,表示二叉树的中序遍历。 输出格式 输出一行 N个整数,表示二叉树的层序遍历。 数据范围 1<=N<…

    算法与数据结构 2023年4月17日
    00
  • 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解

    解析从源码分析常见的基于Array的数据结构动态扩容机制的详解 什么是动态扩容机制 动态扩容机制是指,当一个数据结构达到其容量限制时,自动增加容量大小以继续存储新的数据。在动态扩容时,需要考虑到时间和空间的平衡,因为扩容需要分配新的内存空间,在处理大量数据时,需要尽可能减少空间浪费和分配内存的时间消耗。 基于Array的数据结构 Array是一种连续存储的数…

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

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

    数据结构 2023年5月17日
    00
  • C++数据结构与算法的基础知识和经典算法汇总

    C++数据结构与算法的基础知识和经典算法汇总 1. 基础知识 1.1 数据结构 数据结构是计算机存储、组织数据的方式。这里列出常见的数据结构,包括但不限于: 数组 链表 栈 队列 树 哈希表 1.2 算法 算法是解决问题的步骤和方法。下列是常见的算法: 排序算法 查找算法 字符串算法 图算法 1.3 复杂度 复杂度是算法性能的度量。常见的复杂度表示法有O(n…

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