8JavaScript数据结构与算法--散列表(哈希表)

版权声明:本文为作者的原创文章,未经允许不得转载。 https://blog.csdn.net/lin5165352/article/details/81565664

散列表(哈希表)

散列算法的作用是尽可能快的在数据结构中找到指定的值。

通常情况下我们需要遍历整个数据结构才能找到它。如果使用散列函数,就可以通过索引快速找到该值。类似于中华字典的目录一样。

最常见的散列函数就是将每个键值名的每个字母的ASCII值相加,当然汉字也有ASCII值,也适用该方法。

但是得到的值是一个非常大的数字(成千上万的数字),这样将导致生成一个非常大的数组。浪费大量的资源。

所以为了得到一个较小的数字,会使用hash值和一个任意数字做余运算。

hash = hash%number;  这会产生一个新的问题。导致很多数据的哈希值都一样。如number = 5,当输入任意6个数据的时候必定有两个值是重复的。而且这种冲突是该方法无法避免的。

解决散列表中的冲突

处理冲突有几种方式:

  • 分离链接:该方法为每一个位置创建了一个链表。冲突的值会依次存储在链表中。
  • 线性探索:如果该位置被占用则尝试下一个位置。
  • 双散列法:

下面实现一下分离链接方法。方法中用到了前面的链表:LinkedList()类。

    function HashTable() {
        let table = [];
        let ValuePair = function (key,value) {
            this.key = key;
            this.value = value;
            this.toString = function () {
                return '['+this.key+'-'+this.value+']';
            }
        };
        let loseloseHashCode = function (key) {
            let hash = 0;
            for(let i=0;i<key.length;i++){
                hash += key.charCodeAt(i);
            }
            return hash%5;
        };
        this.put = function (key, value) {
            let position = loseloseHashCode(key);
            //console.log(position+'-'+key+'-'+value);
            if(table[position] === undefined){
                 table[position] = new LinkedList();
             }
            table[position].append(new ValuePair(key,value));
        };
        this.get = function (key) {
            let position = loseloseHashCode(key);
            if(table[position] !== undefined){
                let current = table[position].getHead();
                while (current.next){
                    if(current.element.key === key){
                        return current.element.value;
                    }
                    current = current.next;
                }
                if(current.element.key === key){
                    return current.element.value;
                }
            }
            return undefined;
        };
        this.remove = function (key) {
            let position = loseloseHashCode(key);
            if(table[position] !== undefined){
                let current = table[position].getHead();
                while(current.next){
                    if(current.element.key === key){
                        table[position].remove(current.element);
                        if(table[position].isEmpty()){
                            table[position] = undefined;
                        }
                        return true;
                    }
                    current = current.next;
                }
                if(current.element.key === key){
                    table[position].remove(current.element);
                    if(table[position].isEmpty()){
                        table[position] = undefined;
                    }
                    return true;
                }
            }
            return false;
        };
        this.print = function () {
            for(let i = 0;i<table.length;++i){
                if(table[i] !== undefined){
                    console.log(i+':'+table[i]);
                }
            }
        };
        this.clear = function () {
            table = [];
        }
    }

    let hash1 = new HashTable();
    hash1.clear();
    hash1.put('1','天安门广场');hash1.put('7','上地');
    hash1.put('2','菜市口');hash1.put('12','昌平');
    hash1.put('4','西街');hash1.put('8','王府井');
    hash1.put('17','西二旗');
    hash1.print();
    console.log('查找1:'+hash1.get('1'));
    console.log('删除1:'+hash1.remove('1'));
    hash1.print();

    console.log('----clear----');
    hash1.clear();
    hash1.put('2','西直门');
    hash1.print();

打印结果:

线性探查

在很多语言中数组的大小是制定的,会出现数组用完的情况,所以该方法会有BUG,但在JavaScript中数组的大小是自动改变。不存在这个问题。

暂时不演示该方法。

网上有许多散列函数的方法,可以参考。

猜你喜欢

转载自blog.csdn.net/lin5165352/article/details/81565664