数据结构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日

相关文章

  • 数据结构与算法大作业:走迷宫程序(C语言,DFS)(代码以及思路)

    好家伙,写大作业,本篇为代码的思路讲解   1.大作业要求 走迷宫程序 问题描述: 以一个 m * n 的长方阵表示迷宫, 0和1分别表示迷宫的通路和障碍。 设计一个程序, 对任意设定的迷宫, 求出一条从入口到出口的通路, 或得出没有通路的结论。 基本要求: (1) 实现一个以链表做存储的栈类型, 然后编写一个求解迷宫的非递归程序。 求的通路以三元组(i, …

    算法与数据结构 2023年5月9日
    00
  • 基于python实现模拟数据结构模型

    实现一个模拟数据结构模型的过程需要考虑以下几个步骤: 确定数据结构类型,例如链表、栈、队列、二叉树等。 设计数据结构的具体实现方法,例如链表可采用节点、指针的方式实现,栈可以使用列表或数组实现,队列可使用循环队列实现等。 使用Python编写数据结构相关的类、方法、函数等,确保代码的可读性、灵活性和易维护性。 使用示例数据测试数据结构的各种操作,例如插入、删…

    数据结构 2023年5月17日
    00
  • nginx内存池源码解析

    Nginx内存池源码解析 Nginx是一个高性能、高并发的Web服务器。为了提高其性能和速度,Nginx采用了特殊的内存管理机制,即内存池。 什么是内存池? 内存池是一种高效的内存分配和管理机制。它将一块内存划分成多个大小相等的块,并按需分配给系统。当内存块不再使用时,它并不被立即释放,而是留在内存池中待重复利用。 Nginx内存池结构 Nginx内存池主要…

    数据结构 2023年5月17日
    00
  • C语言数据结构之迷宫问题

    C语言数据结构之迷宫问题 迷宫问题是一种基本的搜索问题,其中需要在一个矩阵中寻找从起点到终点的路径。在本篇文章中,我们将以C语言为例,介绍迷宫问题的完整攻略。 准备工作 在开始之前,我们先要准备好数据结构。为了表示迷宫,我们使用一个二维数组。其中,0表示可以通过的路,1表示障碍物不可通过。为了记录路径,我们还需要使用一个二维数组来表示每个格子是否已经被访问过…

    数据结构 2023年5月17日
    00
  • C语言数据结构之栈和队列的实现及应用

    C语言数据结构之栈和队列的实现及应用 什么是栈和队列? 栈是一种具有后进先出(LIFO)特性的线性数据结构,可以理解为一个只能在一端进行插入和删除操作的数据结构。通常称插入元素的一端为栈顶,删除元素的一端为栈底。 队列是一种具有先进先出(FIFO)特性的线性数据结构,可以理解为一个只能在两端进行插入和删除操作的数据结构。一端进行插入操作,称之为队尾,一端进行…

    数据结构 2023年5月17日
    00
  • C语言实题讲解快速掌握单链表下

    C语言实题讲解快速掌握单链表下 简介 单链表是常见的一种数据结构,可以存储任意数量的数据,并且可以高效的进行插入、删除和查找操作。本篇文章将介绍如何使用C语言实现单链表,以及如何应对在实现单链表时所遇到的常见问题。 实现过程 数据结构设计 为了实现单链表,我们需要设计一个数据结构来存储节点信息,一般包含两个成员,一个是数据域,用来存储实际的数据,另一个是指针…

    数据结构 2023年5月17日
    00
  • AtCoder Beginner Contest 299

    A – Treasure Chest (abc299 a) 题目大意 给定一个包含 |*.的字符串,其中|两个,*一个,问*是否在两个|之间。 解题思路 找到两个|的下标\(l, r\)以及 *的下标\(mid\),看看是否满足 \(l < mid < r\)即可。 神奇的代码 #include <bits/stdc++.h> usi…

    算法与数据结构 2023年4月23日
    00
  • C语言数据结构二叉树简单应用

    C语言数据结构二叉树简单应用攻略 1. 什么是二叉树? 二叉树(Binary Tree)是一种树形结构,它的每个节点最多包含两个子节点,它是非线性数据结构,可以用来表示许多问题,例如家族关系、计算机文件系统等等。 2. 二叉树的基本操作 二叉树的基本操作包括插入、删除、查找等等,本攻略主要讲解插入和查找的实现。 插入操作的代码如下: // 二叉树的插入操作 …

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