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

 更新时间:2023年01月30日 09:28:08   作者:前端技术獭  
这篇文章主要为大家介绍了数据结构Typescript之哈希表实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

哈希表的结构特点

相比链表繁杂的遍历处理,哈希表的作用是存储无固定顺序的键值对哈希表的元素查找时间复杂度为O(1)

尝试手动构建一个哈希表。过程如下:

function HashCode(str) { // 散列函数
    let address = 0
    for (let i = 0; i < str.length; i++) {
        address += str.charCodeAt(i)
    }
    return address % 37 // 生成的哈希码
}
let table = {} // 哈希表
let keyValuePair = { key: "苹果手机", value: "4999元" } // 哈希表的基本单元: 键值对
table[HashCode(keyValuePair.key)] = keyValuePair // table添加对象,属性为哈希码,值为keyValuePair
console.log(table) // 输出哈希表: table { 28: { key: "苹果手机", value: "4999元" } }

我们需要清楚哈希表、键值对、哈希码和散列函数这四者的关系。过程分析如下:

第一步:创建哈希表table、键值对keyValuePair和散列函数HashCode

第二步:基于keyValuePair.key即"苹果手机"这个字符串特征,通过散列函数生成哈希码HashCode(keyValuePair.key)

第三步:执行table[HashCode(keyValuePair.key)] = keyValuePair。即在table对象上新增一个HashCode(keyValuePair.key)属性,而它的值就是键值对keyValuePair

总结:键值对中的key可通过散列函数生成哈希码,而生成的哈希码则作为哈希表的属性存储对应的键值对。

面向对象方法封装哈希表

哈希冲突

试着考虑以下这种情况,我们需要存储的键由相同字母构成,但字母的排序不同。

console.log(HashCode('Mike')) // 20
console.log(HashCode('Meki')) // 20
console.log(HashCode('keMi')) // 20

显然,相同字符构成但排序不同的字符串会生成相同的哈希码。即在哈希表中我们原来存储的键值对可能会因为哈希冲突而产生被覆盖的情况。有很多手段可以解决哈希冲突的问题。本文采取的是链地址方法。

构造函数

基本单元:键值对

class keyValuePair {
    key: any
    value: any
    constructor(key: any, value: any) {
        this.key = key
        this.value = value
    }
}

主体:哈希表

class HashTable {
    length: number
    table: { [index: number]: LinkedList }
    constructor() {
        this.length = 0
        this.table = {}
    }
}

增加键值对

增加键值对的情况分为两种。如下分析:

  • 哈希表中没有这个哈希码属性:创建一个新链表,然后将键值对作为头节点插入链表。
  • 哈希表中已存在相同的哈希码:即存在哈希冲突,在已创建的链表上追加一个键值对。
set(key: any, value: any): HashTable {
    if (this.table[HashCode(key)] === undefined) {
        this.table[HashCode(key)] = new LinkedList()
    }
    this.table[HashCode(key)].insert(new keyValuePair(key, value))
    this.length++
    return this
}

获取键值

获取键值的情况分为三种。如下分析:

  • 哈希表为空:抛出错误。
  • 哈希表中不存在这个哈希码属性:抛出错误。
  • 哈希表中存在这个哈希码属性:从头节点开始,遍历链表找到这个key参数对应的键值返回,否则抛出错误。
get(key: any): (void | any) {
    if (this.isEmpty()) {
        throw new Error(`HashTable is empty`)
    } else if (this.table[HashCode(key)] === undefined) {
        throw new Error(`${key} is not defined`)
    } else {
        let current: (null | LinkedListNode) = this.table[HashCode(key)].head
        while (current !== null) {
            if (key === current!.element!.key) {
                return current!.element!.value
            }
            current = current!.next
        }
        if (!current) { throw new Error(`${key} does not exist`) }
    }
}

删除键值对

删除键值对的情况分为三种。如下分析:

  • 哈希表为空:抛出错误。
  • 哈希表中不存在这个哈希码属性:抛出错误。
  • 哈希表中存在这个哈希码属性:链表长度为1,直接删除这个哈希码属性。链表长度大于1,遍历链表获取这个键值对在链表中对应的序号,然后利用链表方法删除这个键值对。
remove(key: any): HashTable {
    if (this.isEmpty()) {
        throw new Error(`HashTable is empty`)
    } else if (this.table[HashCode(key)] === undefined) {
        throw new Error(`${key} is not defined`)
    } else if (this.table[HashCode(key)].length === 1) {
        delete this.table[HashCode(key)]
    } else if (this.table[HashCode(key)].length &gt; 1) {
        let current: (null | LinkedListNode) = this.table[HashCode(key)].head
        for (let i = 0; i &lt; this.table[HashCode(key)].length; i++) {
            if (key === current!.element!.key) {
                this.table[HashCode(key)].remove(i)
                break
            }
            current = current!.next
        }
        if (!current) { throw new Error(`${key} does not exist`) }
    }
    this.length--
    return this
}

本文相关代码已放置我的Github仓库 👇

项目地址:Algorithmlib|HashTable

以上就是数据结构Typescript之哈希表实现详解的详细内容,更多关于Typescript数据结构哈希表的资料请关注脚本之家其它相关文章!

相关文章

  • typescript type类型使用梳理总结

    typescript type类型使用梳理总结

    这篇文章主要为大家介绍了typescript type类型使用梳理总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • TypeScript类型操作之字符串处理功能详解

    TypeScript类型操作之字符串处理功能详解

    这篇文章主要为大家介绍了TypeScript类型操作之字符串处理功能详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • TypeScript 泛型接口具体使用实战

    TypeScript 泛型接口具体使用实战

    这篇文章主要为大家介绍了TypeScript 泛型接口具体使用实战,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • ThreeJS使用纹理贴图创建一个我的世界草地方块

    ThreeJS使用纹理贴图创建一个我的世界草地方块

    这篇文章主要为大家介绍了ThreeJS使用纹理贴图创建一个我的世界草地方块的实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • TypeScript类型编程中的extends和infer示例解析

    TypeScript类型编程中的extends和infer示例解析

    这篇文章主要为大家介绍了TypeScript类型编程中的extends和infer示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • Typescript extends 关键字继承类型约束及条件类型判断实现示例解析

    Typescript extends 关键字继承类型约束及条件类型判断实现示例解析

    这篇文章主要介绍了Typescript extends 关键字继承类型约束及条件类型判断实现示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • Typescript是必须要学习吗?如何学习TS全栈开发

    Typescript是必须要学习吗?如何学习TS全栈开发

    Typescript目前在前端,网站,小程序中的位置基本无可替代,同时也可以构建完美的CLI应用。在移动,桌面,后端方面,性能不是要求很高的情况下完全可以胜任,并且在区块链,嵌入式,人工智能方面也开始茁壮成长。
    2022-12-12
  • 微信小程序实现图片自适应(支持多图)

    微信小程序实现图片自适应(支持多图)

    这篇文章主要介绍了微信小程序如何实现图片自适应的相关资料,文中介绍的方法同样适应于多图,有需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • typescript快速上手的基础知识篇

    typescript快速上手的基础知识篇

    静态类型的typescript与传统动态弱类型语言javascript不同,在执行前会先编译成javascript,因为它强大的type类型系统加持,能让我们在编写代码时增加更多严谨的限制。注意,它并不是一门全新的语言,所以并没有增加额外的学习成本
    2022-12-12
  • TypeScript防抖节流函数示例详解

    TypeScript防抖节流函数示例详解

    这篇文章主要为大家介绍了TypeScript防抖节流函数示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08

最新评论