哈希表以及用js封装一个哈希表

news2024/9/23 7:24:42

最近在学数据结构和算法,正好将学习的东西记录下来,我是跟着一个b站博主学习的,是使用js来进行讲解的,待会也会在文章后面附上视频链接地址,大家想学习的可以去看看

 本文主要讲解哈希表,其他数据结构后续学完也会持续更新!

目录

一、什么是哈希表

下面是 chatGPT 给出的解释:

下面是PPT中的讲解

 想要学习哈希表,那就不得不了解一些哈希表的概念

 二、哈希化时产生的问题:冲突 

注意:常见解决冲突的方法有两种,链地址法(拉链法)和开放地址法,但是相对来说链地址法的效率是要好于开放地址法的,所以等会在用 js 封装哈希表的时候,我们采用的也是链地址法。

三、哈希函数的实现

四、封装哈希表

1、创建哈希表

2、插入&修改数据

 3、获取方法

4、删除方法

5、其他方法

6、测试哈希表

7、完整代码

五、哈希表的扩容

1、哈希表的扩容思想

 2、哈希表的扩容实现

 下面修改插入&修改方法,如果添加东西太多,实现扩容

下面修改删除方法,如果删除东西太多,实现减容

六、实现容量恒为质数

下面是所有完善之后的代码


一、什么是哈希表

下面是 chatGPT 给出的解释:

哈希表(Hash Table)又称为散列表,是一种用于存储键值对的数据结构。它通过哈希函数将键映射到一个固定大小的数组中的位置,该位置称为哈希桶(Hash Bucket)。哈希表的优势在于可以快速插入、删除和查找数据。

哈希函数是哈希表的核心,它接受一个任意大小的输入(键),并通过计算返回一个固定大小的哈希值。哈希值被用作数组的索引,用于存储和检索对应的键值对。由于哈希函数的输出是固定的,不同的键可能会映射到相同的哈希值,这就产生了哈希冲突。

解决哈希冲突的一种常见方法是使用链表或其他数据结构来存储哈希冲突的键值对。当多个键被映射到同一个哈希桶时,它们会被链接在一起形成一个链表(或其他数据结构),并存储在同一个桶内。这样,当查找键值对时,可以先通过哈希函数找到对应的桶,然后在桶内顺序查找或通过进一步的数据结构快速查找目标键值对。

哈希表在平均情况下具有非常高效的插入、删除和查找操作。在理想情况下,哈希函数能够将键均匀地映射到不同的桶,从而实现常数时间复杂度的操作。然而,在某些情况下,哈希冲突可能会导致性能下降,甚至出现较差的情况。因此,在设计哈希函数时需要考虑均匀性和避免冲突的因素。

虽然文字有点多,但是讲的还是很好理解的。

下面是PPT中的讲解

 想要学习哈希表,那就不得不了解一些哈希表的概念

 二、哈希化时产生的问题:冲突 

注意:常见解决冲突的方法有两种,链地址法(拉链法)和开放地址法,但是相对来说链地址法的效率是要好于开放地址法的,所以等会在用 js 封装哈希表的时候,我们采用的也是链地址法。

三、哈希函数的实现

// 设计哈希函数
// 1 -> 将字符串转换成比较大的数字:hashCode
// 2 -> 将大的数字 hashCode 压缩到数组的范围之内
function hashFunc(str, size) {
    // 1、定义hashCode变量
    var hashCode = 0
    // 2、霍纳算法,用来计算hashCode的值
    // cats -> Unicode 编码
    for (var i = 0; i < str.length; i++) {
        // 一般选用 37 为那个质数 ,然后得到一个比较大的数字
        hashCode = 37 * hashCode + str.charCodeAt(i)
    }
    // 3、取余操作,得到压缩到数组范围内的数字
    var index = hashCode % size
    return index
}
console.log(hashFunc("abc", 7));

四、封装哈希表

1、创建哈希表

// 封装哈希表类
function HashTable() {
    // 属性
    this.storage = []
    this.count = 0
    this.limit = 7

    // 方法
    // 哈希函数的封装
    function hashFunc(str, size) {
        // 1、定义hashCode变量
        var hashCode = 0
        // 2、霍纳算法,用来计算hashCode的值
        // cats -> Unicode 编码
        for (var i = 0; i < str.length; i++) {
            // 一般选用 37 为那个质数 ,然后得到一个比较大的数字
            hashCode = 37 * hashCode + str.charCodeAt(i)
        }
        // 3、取余操作,得到压缩到数组范围内的数字
        var index = hashCode % size
        return index
    }
}

2、插入&修改数据

// 插入 & 修改操作的封装
HashTable.prototype.put = function(key, value) {
    // 1、根据 key 获取对应的 index
    var index = this.hashFunc(key, this.limit)

    // 2、根据 index 取出对应的 bucket
    var bucket = this.storage[index]

    // 3、判断该 bucket 是否为 null 
    if (bucket == null) {
        bucket = []
        this.storage[index] = bucket
    }

    // 4、判断是否是修改数据
    for (var i = 0; i < bucket.length; i++) {
        var tuple = bucket[i]
        if (tuple[0] == key) {
            tuple[1] = value
            return
        }
    }
    // 5、进行添加操作
    bucket.push([key, value])
}

 3、获取方法

// 获取操作的封装
HashTable.prototype.get = function(key) {
    // 1、根据 key 获取对应的 index 
    var index = this.hashFunc(key, this.limit)

    // 2、根据 index 取出对应的 bucket
    var bucket = this.storage[index]

    // 3、判断该 bucket 是否为 null
    if (bucket == null) {
        return null
    }

    // 4、如果有 bucket ,那么就进行线性查找
    for (var i = 0; i < bucket.length; i++) {
        var tuple = bucket[i]
        if (tuple[0] == key) {
            return tuple[1]
        }
    }

    // 5、依然没有找到,那么返回 null
    return null
}

4、删除方法

// 删除操作的封装
HashTable.prototype.remove = function(key) {
    // 1、根据 key 获取对应的 index
    var index = this.hashFunc(key, this.limit)

    // 2、根据 index 取出对应的 bucket 
    var bucket = this.storage[index]

    // 3、判断 bucket 是否为 null 
    if (bucket == null) {
        return null
    }

    // 4、如果有 bucket ,那么就进行线性查找,并且删除
    for (var i = 0; i < bucket.length; i++) {
        var tuple = bucket[i]
        if (tuple[0] == key) {
            bucket.splice(i, 1)
            this.count--
            return tuple[1]
        }
    }

    // 5、如果依然没有找到,那么返回 null
    return null
}

5、其他方法

// 封装其他方法
// 判断哈希表是否为 null 的封装
HashTable.prototype.isEmpty = function() {
    return this.count == 0
}

// 获取哈希表中元素个数的封装
HashTable.prototype.size = function() {
    return this.count
}

6、测试哈希表

// 测试哈希表
// 1、创建哈希表
var ht = new HashTable()

// 2、插入数据
ht.put("abc", "哈哈哈")
ht.put("cba", "啦啦啦")

// 3、获取数据
console.log(ht.get("abc"));  // 哈哈哈

// 4、修改方法
ht.put("abc", "哈哈哈哈哈")
console.log(ht.get("abc"));  // 哈哈哈哈哈

// 5、删除方法
ht.remove("abc")
console.log(ht.get("abc"));  // null

// 6、判断是否为空
console.log(ht.isEmpty());  // false

// 7、查看哈希表中元素的个数
console.log(ht.size());  // 1

7、完整代码

// 封装哈希表类
function HashTable() {
    // 属性
    this.storage = []
    this.count = 0
    this.limit = 7

    // 方法
    // 哈希函数的封装
    HashTable.prototype.hashFunc = function(str, size) {
        // 1、定义hashCode变量
        var hashCode = 0
        // 2、霍纳算法,用来计算hashCode的值
        // cats -> Unicode 编码
        for (var i = 0; i < str.length; i++) {
            // 一般选用 37 为那个质数 ,然后得到一个比较大的数字
            hashCode = 37 * hashCode + str.charCodeAt(i)
        }
        // 3、取余操作,得到压缩到数组范围内的数字
        var index = hashCode % size

        return index
    }

    // 插入 & 修改操作的封装
    HashTable.prototype.put = function(key, value) {
        // 1、根据 key 获取对应的 index
        var index = this.hashFunc(key, this.limit)

        // 2、根据 index 取出对应的 bucket
        var bucket = this.storage[index]

        // 3、判断该 bucket 是否为 null 
        if (bucket == null) {
            bucket = []
            this.storage[index] = bucket
        }

        // 4、判断是否是修改数据
        for (var i = 0; i < bucket.length; i++) {
            var tuple = bucket[i]
            if (tuple[0] == key) {
                tuple[1] = value
                return
            }
        }
        // 5、进行添加操作
        bucket.push([key, value])
        this.count += 1
    }

    // 获取操作的封装
    HashTable.prototype.get = function(key) {
        // 1、根据 key 获取对应的 index 
        var index = this.hashFunc(key, this.limit)

        // 2、根据 index 取出对应的 bucket
        var bucket = this.storage[index]

        // 3、判断该 bucket 是否为 null
        if (bucket == null) {
            return null
        }

        // 4、如果有 bucket ,那么就进行线性查找
        for (var i = 0; i < bucket.length; i++) {
            var tuple = bucket[i]
            if (tuple[0] == key) {
                return tuple[1]
            }
        }

        // 5、依然没有找到,那么返回 null
        return null
    }

    // 删除操作的封装
    HashTable.prototype.remove = function(key) {
        // 1、根据 key 获取对应的 index
        var index = this.hashFunc(key, this.limit)

        // 2、根据 index 取出对应的 bucket 
        var bucket = this.storage[index]

        // 3、判断 bucket 是否为 null 
        if (bucket == null) {
            return null
        }

        // 4、如果有 bucket ,那么就进行线性查找,并且删除
        for (var i = 0; i < bucket.length; i++) {
            var tuple = bucket[i]
            if (tuple[0] == key) {
                bucket.splice(i, 1)
                this.count--
                return tuple[1]
            }
        }

        // 5、如果依然没有找到,那么返回 null
        return null
    }

    // 封装其他方法
    // 判断哈希表是否为 null 的封装
    HashTable.prototype.isEmpty = function() {
        return this.count == 0
    }

    // 获取哈希表中元素个数的封装
    HashTable.prototype.size = function() {
        return this.count
    }
}

// 测试哈希表
// 1、创建哈希表
var ht = new HashTable()

// 2、插入数据
ht.put("abc", "哈哈哈")
ht.put("cba", "啦啦啦")

// 3、获取数据
console.log(ht.get("abc"));

// 4、修改方法
ht.put("abc", "哈哈哈哈哈")
console.log(ht.get("abc"));

// 5、删除方法
ht.remove("abc")
console.log(ht.get("abc"));

// 6、判断是否为空
console.log(ht.isEmpty());

// 7、查看哈希表中元素的个数
console.log(ht.size());

五、哈希表的扩容

1、哈希表的扩容思想

 2、哈希表的扩容实现

// 哈希表扩容/缩容封装
HashTable.prototype.resize = function(newLimit) {
    // 保存旧的数组内容
    var oldStorage = this.storage

    // 2、重置所有的属性
    this.storage = []
    this.conut = 0
    this.limit = newLimit

    // 3、遍历 oldStorage 中所有的 bucket
    for (var i = 0; i < oldStorage.length; i++) {
        // 3.1 取出对应的 bucket 
        var bucket = oldStorage[i]

        // 3.2 判断 bucket 是否为 null
        if (bucket == null) {
            continue
        }

        // 3.3 bucket 中有数据,那么取出数据,重新插入
        for (var j = 0; j < bucket.length; j++) {
            var tuple = bucket[j]
            this.put(tuple[0], tuple[1])
        }
    }
}

 下面修改插入&修改方法,如果添加东西太多,实现扩容

// 修改插入&修改方法,如果添加东西太多,实现扩容
// 插入 & 修改操作的封装
HashTable.prototype.put = function(key, value) {
    // 1、根据 key 获取对应的 index
    var index = this.hashFunc(key, this.limit)

    // 2、根据 index 取出对应的 bucket
    var bucket = this.storage[index]

    // 3、判断该 bucket 是否为 null 
    if (bucket == null) {
        bucket = []
        this.storage[index] = bucket
    }

    // 4、判断是否是修改数据
    for (var i = 0; i < bucket.length; i++) {
        var tuple = bucket[i]
        if (tuple[0] == key) {
            tuple[1] = value
            return
        }
    }
    // 5、进行添加操作
    bucket.push([key, value])
    this.count += 1

    // 6、判断是否需要扩容操作
    if (this.count > this.limit * 0.75) {
        this.resize(this.limit * 2)
    }
}

下面修改删除方法,如果删除东西太多,实现减容

// 修改删除方法,如果删除东西太多,实现减容
// 删除操作的封装
HashTable.prototype.remove = function(key) {
    // 1、根据 key 获取对应的 index
    var index = this.hashFunc(key, this.limit)

    // 2、根据 index 取出对应的 bucket 
    var bucket = this.storage[index]

    // 3、判断 bucket 是否为 null 
    if (bucket == null) {
        return null
    }
    // 4、如果有 bucket ,那么就进行线性查找,并且删除
    for (var i = 0; i < bucket.length; i++) {
        var tuple = bucket[i]
        if (tuple[0] == key) {
            bucket.splice(i, 1)
            this.count--
            return tuple[1]

            // 缩小容量
            if (this.limit > 7 && this.count < this.limit * 0.25) {
                // Math.floor 向下取整
                this.resize(Math.floor(this.limit / 2))
            }
        }
    }
    // 5、如果依然没有找到,那么返回 null
    return null
}

六、实现容量恒为质数

// 封装判断某个数字是否是质数
HashTable.prototype.isPrime = function(num) {
    // 1、获取 num 的平方根
    var temp = parseInt(Math.sqrt(num))

    // 2、循环判断
    for (var i = 2; i <= temp; i++) {
        if (num % i == 0) {
            return false
        }
    }
    return true
}

// 封装获取质数的方法
HashTable.prototype.getPrime = function(num) {
    // 循环判断这个数是否为质数,如果不是质数,就一直加一,什么时候是质数就返回这个数
    while (!this.isPrime(num)) {
        num++
    }
    return num
}

下面是所有完善之后的代码

// 封装哈希表类
function HashTable() {
    // 属性
    this.storage = []
    this.count = 0
    this.limit = 7

    // 方法
    // 哈希函数的封装
    HashTable.prototype.hashFunc = function(str, size) {
        // 1、定义hashCode变量
        var hashCode = 0
        // 2、霍纳算法,用来计算hashCode的值
        // cats -> Unicode 编码
        for (var i = 0; i < str.length; i++) {
            // 一般选用 37 为那个质数 ,然后得到一个比较大的数字
            hashCode = 37 * hashCode + str.charCodeAt(i)
        }
        // 3、取余操作,得到压缩到数组范围内的数字
        var index = hashCode % size

        return index
    }

    // 插入 & 修改操作的封装
    HashTable.prototype.put = function(key, value) {
        // 1、根据 key 获取对应的 index
        var index = this.hashFunc(key, this.limit)

        // 2、根据 index 取出对应的 bucket
        var bucket = this.storage[index]

        // 3、判断该 bucket 是否为 null 
        if (bucket == null) {
            bucket = []
            this.storage[index] = bucket
        }

        // 4、判断是否是修改数据
        for (var i = 0; i < bucket.length; i++) {
            var tuple = bucket[i]
            if (tuple[0] == key) {
                tuple[1] = value
                return
            }
        }
        // 5、进行添加操作
        bucket.push([key, value])
        this.count += 1

        // 6、判断是否需要扩容操作
        if (this.count > this.limit * 0.75) {
            var newSize = this.limit * 2
            var newPrime = this.getPrime(newSize)
            this.resize(newPrime)
        }
    }

    // 获取操作的封装
    HashTable.prototype.get = function(key) {
        // 1、根据 key 获取对应的 index 
        var index = this.hashFunc(key, this.limit)

        // 2、根据 index 取出对应的 bucket
        var bucket = this.storage[index]

        // 3、判断该 bucket 是否为 null
        if (bucket == null) {
            return null
        }

        // 4、如果有 bucket ,那么就进行线性查找
        for (var i = 0; i < bucket.length; i++) {
            var tuple = bucket[i]
            if (tuple[0] == key) {
                return tuple[1]
            }
        }

        // 5、依然没有找到,那么返回 null
        return null
    }

    // 删除操作的封装
    HashTable.prototype.remove = function(key) {
        // 1、根据 key 获取对应的 index
        var index = this.hashFunc(key, this.limit)

        // 2、根据 index 取出对应的 bucket 
        var bucket = this.storage[index]

        // 3、判断 bucket 是否为 null 
        if (bucket == null) {
            return null
        }

        // 4、如果有 bucket ,那么就进行线性查找,并且删除
        for (var i = 0; i < bucket.length; i++) {
            var tuple = bucket[i]
            if (tuple[0] == key) {
                bucket.splice(i, 1)
                this.count--
                return tuple[1]

                // 缩小容量
                if (this.limit > 7 && this.count < this.limit * 0.25) {
                    // Math.floor 向下取整
                    var newSize = Math.floor(this.limit / 2)
                    var newPrime = this.getPrime(newSize)
                    this.resize(newPrime)
                }
            }
        }

        // 5、如果依然没有找到,那么返回 null
        return null
    }

    // 封装其他方法
    // 判断哈希表是否为 null 的封装
    HashTable.prototype.isEmpty = function() {
        return this.count == 0
    }

    // 获取哈希表中元素个数的封装
    HashTable.prototype.size = function() {
        return this.count
    }

    // 哈希表扩容/缩容封装
    HashTable.prototype.resize = function(newLimit) {
        // 保存旧的数组内容
        var oldStorage = this.storage

        // 2、重置所有的属性
        this.storage = []
        this.conut = 0
        this.limit = newLimit

        // 3、遍历 oldStorage 中所有的 bucket
        for (var i = 0; i < oldStorage.length; i++) {
            // 3.1 取出对应的 bucket 
            var bucket = oldStorage[i]

            // 3.2 判断 bucket 是否为 null
            if (bucket == null) {
                continue
            }

            // 3.3 bucket 中有数据,那么取出数据,重新插入
            for (var j = 0; j < bucket.length; j++) {
                var tuple = bucket[j]
                this.put(tuple[0], tuple[1])
            }
        }
    }

    // 封装判断某个数字是否是质数
    HashTable.prototype.isPrime = function(num) {
        // 1、获取 num 的平方根
        var temp = parseInt(Math.sqrt(num))

        // 2、循环判断
        for (var i = 2; i <= temp; i++) {
            if (num % i == 0) {
                return false
            }
        }
        return true
    }

    // 封装获取质数的方法
    HashTable.prototype.getPrime = function(num) {
        // 循环判断这个数是否为质数,如果不是质数,就一直加一,什么时候是质数就返回这个数
        while (!this.isPrime(num)) {
            num++
        }
        return num
    }
}

// 测试哈希表
// 1、创建哈希表
var ht = new HashTable()

// 2、插入数据
ht.put("abc", "哈哈哈")
ht.put("cba", "啦啦啦")

// 3、获取数据
console.log(ht.get("abc"));

// 4、修改方法
ht.put("abc", "哈哈哈哈哈")
console.log(ht.get("abc"));

// 5、删除方法
ht.remove("abc")
console.log(ht.get("abc"));

// 6、判断是否为空
console.log(ht.isEmpty());

// 7、查看哈希表中元素的个数
console.log(ht.size());

下面附上b站视频链接,需要学习的可以去看看(JavaScript算法与数据结构),如果光看文章可能还是有点晦涩难懂,但是看老师视频的讲解,基本就能掌握了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/759014.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

轻松入门Python量化交易(三)

大家好&#xff0c;我们接第二部分继续分析金融数据。 配对图和相关矩阵 证券中的相关性分析为我们提供了有趣的投资策略。市场中一个广为人知的策略叫做“Long-Short”&#xff0c;即买入一家公司的证券&#xff0c;同时卖出另一家公司的证券&#xff0c;相信这两个资产在市…

《微服务架构设计模式》第八章 外部API模式

内容总结自《微服务架构设计模式》 外部API模式 一、API设计难题二、API Gateway 模式1、简介2、所有者模式3、好处和弊端4、设计问题5、实现一个API Gateway 三、使用GraphQL 实现API Gateway四、总结 一、API设计难题 1、移动客户端的API设计难题 在此设计中&#xff0c;移动…

动态规划(二) —— 打家劫舍系列问题总结

前言 除了背包系列问题&#xff0c;打家劫舍系列问题同样也是动态规划的经典题目。在这篇文章中荔枝将会把打家劫舍系列问题做一下总结&#xff0c;再仔细体会动态规划的思想&#xff0c;希望能帮到有需要的小伙伴~~~ 文章目录 前言 一、Leecode198.打家劫舍 1.1 分析 1.2 …

C2C、B2B、B2C、O2O电商定义区别

如今是电子商务高度发展的时代&#xff0c;大多数传统企业商家都开始采取转型战略帮助企业发展&#xff0c;商业模式的选择是转型的关键点&#xff0c;下面小编向你详细介绍一下B2B、B2C、C2C、O2O这些商务模式&#xff0c;帮助你快速理解它们。 BBusiness&#xff0c;即企业;…

Servlet实现文件下载的功能

download.html <% page contentType"text/html;charsetUTF-8" language"java" %> <html> <head><title>文件下载</title><base href"<%request.getContextPath()"/"%>>"> </head>…

前端基本功 用 React Hooks + Antd 实现一个 Todo-List

背景 使用 React Hooks 以及组件库 Antd 来实现一个可以 增删 标记是否完成 的 todo-list 思路 要实现一个 todo-list 首先想到用 useState 维护一个状态数组来保存当前 list &#xff0c;还要用一个状态维护添加框中的内容 const [todos, setTodos] useState(initialValu…

OpenCv图像基本变换

目录 一、图像翻转 二、图像旋转 三、仿射变换之平移 四、仿射变换之获取变换矩阵 五、仿射变换之透视变换 一、图像翻转 图像翻转不等同于旋转&#xff0c;类似于一些视频的拍摄&#xff0c;拍摄后实际是左右颠倒的&#xff0c;通过图像翻转可进行还原 案例代码如下: …

第十四章:Context Encoding for Semantic Segmentation ——语义分割的上下文编码

0.摘要 近期的研究在使用全卷积网络&#xff08;FCN&#xff09;框架改善像素级标注的空间分辨率方面取得了显著进展&#xff0c;通过采用扩张/空洞卷积、利用多尺度特征和细化边界等方法。本文通过引入上下文编码模块来探索全局上下文信息对语义分割的影响&#xff0c;该模块捕…

springMVC的开发步骤-15

第一步你用到前端核心控制器&#xff0c;你应该有他&#xff0c;因此导包&#xff1a; 第二步:配servlet 第三步&#xff1a;配控制器&#xff0c;用来调用视图 结束之后我要干嘛&#xff1f;这个springMvC,我能否将这个pojo放到容器内部当中&#xff0c;能否通过bean标签进行配…

Linux 系统编程-开发环境(三)

目录 16 vim 16.1 vi简介 16.1.1 命令行模式 16.1.2 文本输入模式 16.1.3 末行模式 16.2 vim基础操作 16.3 vim分屏操作 16.4 vim打造IDE 16.4.1 简洁版IDE 17 gcc 18 toolchain 19 静态库和共享库 19.1 静态库 19.2 共享库 19.2.1 基础班使 19.2.2 就业班使用…

BiSeNetv2(pytorch)测试、训练cityscapes

1. 源码&#xff1a; github: https://github.com/CoinCheung/BiSeNet git clone https://github.com/CoinCheung/BiSeNet.git2. 预训练模型&#xff1a; 工程下载后解压&#xff0c;并在其中创建文件夹【model】用于存放预训练模型&#xff1b; 3. 运行demo conda creat…

【安装】Linux环境下的 JDK的安装 安装配置 环境变量

目录 Linux安装java环境1.检查系统中是否有JDK2.删除原有的java相关的包3.上传jdk到指定的文件夹4.解压jdk-8u371-linux-x64.tar.gz5.配置jdk的环境变量6.让配置生效 运行一个jar包运行jar包进行测试 Oracle 甲骨文中国 | 云应用和云平台 windows环境下的 JDK官网下载 & 安…

Android实现抓包 使用Fiddler抓包

Fiddler下载&#xff1a;https://pan.baidu.com/s/1QzvL0xugp6XX7gbFBFlEJg?pwdbf6u 提取码&#xff1a;bf6u 1.Fiddler配置 如果用不到https可以不开启https抓包 电脑打开fiddler&#xff0c;手机电脑同一网段。fiddler打开https抓包(Tools->Options->HTTPS)&a…

re学习(17)Bugku-re-Tworld(使用DFS解决迷宫问题)

下载地址&#xff1a; 跳转提示 参考视频&#xff1a; 【Bugku/CTF/Re/WP】使用DFS解决迷宫问题CTF "Tworld"_哔哩哔哩_bilibili 载入IDA后发现有UPX壳&#xff0c;先用工具进行脱壳&#xff0c;然后载入IDA进行分析。 编写脚本&#xff1a; #全部代码 import…

【电路原理学习笔记】第3章:欧姆定律:3.3 电压的计算

第3章&#xff1a;欧姆定律 3.3 电压的计算 电压相关欧姆定律公式&#xff1a; V I R VIR VIR 【例3-11】在图3-10所示的电路中&#xff0c;产生5A电流需要多大电压&#xff1f; 【答】 V I R 5 A 100 Ω 500 V VIR5\rm A\times 100Ω500 V VIR5A100Ω500V 【同步练习…

N天爆肝数据库——MySQL(5)

本文主要对索引进行了讲解 这里写目录标题 本文主要对索引进行了讲解索引概述介绍优缺点索引结构二叉树红黑树B-Tree(多路平衡查找树)BTreeBTree与B-Tree区别: HashHash索引特点 为什么InnoDB存储引擎选择使用BTree索引结构&#xff1f;索引分类在InnoDB存储引擎中&#xff0c;…

详解JS的四种异步解决方案!

目录 同步&异步的概念 js中异步的应用场景 实现异步的四种方法 1、 回调函数 2、Promise 3、Generator 4、 async/await 「异步编程」是前端工程师日常开发中经常会用到的技术&#xff0c;也是校招面试过程中常考的一个知识点。 通过掌握「异步编程」的四种方式&…

redis 和mongodb基础操作练习

目录 redis作业 string、list、hash 数据类型 举例说明list和hash的应用场景&#xff0c;每个至少一个场景 mongodb作业 1. 创建一个数据库 名字grade 2. 数据库中创建一个集合名字 class 3. 集合中插入若干数据 文档格式如下 4. 查找 5. 增加、更新、删除、统计 re…

【电路原理学习笔记】第3章:欧姆定律:3.1 电压、电流与电阻的关系

第3章&#xff1a;欧姆定律 3.1 电压、电流与电阻的关系 欧姆定律指出&#xff1a;电流与电压成正比&#xff0c;与电阻成反比。即 I V R I\frac{V}{R} IRV​ 3.1.1 电压与电流之间的线性关系 数学上&#xff0c;线性指的是变量之间的关系在图形上是一条直线。线性方程所对…

数据结构与算法——希尔排序(引例、希尔增量序列、原始希尔排序、代码、时间复杂度、Hibbard增量序列、Sedgewick增量序列)

目录 引例 希尔增量序列 原始希尔排序 代码&#xff08;C语言&#xff09; 时间复杂度 更多增量序列 Hibbard增量序列 Sedgewick增量序列 希尔排序&#xff08;by Donald Shell&#xff09; 引例 给以下序列进行排序&#xff1a; 先以5的间隔进行插入排序&#xff1a…