zoukankan      html  css  js  c++  java
  • 数据结构----散列

    /*
    * 算法——散列
    * 散列表是基于数组进行设计的。数组的长度是预先设定的
    * 所有元素根据和该元素对应的键,保存在数组的特定位置,该键和我们前面讲到的字典中的键是类似的概念
    * 使用散列表存储数据时,通过一个散列函数将键映射为一个数字,这个数字的范围是 0 到散列表的长度。
    *
    * 这里所说的键 应该就是数组的索引 只不过 数组既然长度确定了,那么索引的个数也是确定了
    * 每个元素是无限的,每个元素的键值映射出来的索引也许就会发生重复或说碰撞。 这个叫有效碰撞。
    *
    * 键值映射到数组的索引 这个过程是由散列函数来完成。 散列函数的选择 要保证键值映射出来的索引是尽量不重复的
    *
    * simpleHash: 散列函数
    *
    * put: 在散列中增加元素
    *
    * showDistro: 展示散列中的元素
    * */
    function simpleHash(data) {
        var total = 0;
        for(var i = 0 ; i < data.length; i++) {
            total += data.charCodeAt(i);
        }
        return total % this.table.length;
    }
    function put(data) {
        var pos = this.simpleHash(data);
        this.table[pos] = data;
    }
    function showDistro() {
        for(var i = 0 ; i < this.table.length;i++) {
            if (this.table[i] !== undefined) {
                console.log(i + ":" +this.table[i])
            }
        }
    }
    function HashTable() {
        this.table = new Array(137);
        this.buildChains = buildChains;
        this.simpleHash = simpleHash;
        this.put = put;
        this.showDistro = showDistro;
    }
    var someNames = ["David", "Jennifer", "Donnie", "Raymond",
        "Cynthia", "Mike", "Clayton", "Danny", "Jonathan"],
        h = new HashTable();
    // h.buildChains();  //测试线性探测法 注释掉
    for (var i = 0; i< someNames.length;i++) {
        h.put(someNames[i]);
    }
    h.showDistro(); // 输出:35: Cynthia 45: Clayton 57: Donnie 77: David 95: Danny 116: Mike 132: Jennifer 134: Jonathan
    
    //是输出了8位少了一位? 记得上面的说明 散列函数可能会映射相同的索引出来 出现了有效碰撞。
    
    //更好的散列函数 数组长度是质数 计算过程中再乘以一个质数
    
    //为什么要选择一个质数呢? 质数特点:只有1 和 本身两个因数 而合数 有两个以上因数 如果除余合数 那么造成重复机会大
    //因为合数有多个因子 比如 20   50%20 70%20 是一样的
    
    //感觉这个质数不是特别靠谱 ^^ 下面有其它方法解决
    
    function simpleHash(data) {
        const H = 5;
        var total = 0;
        for (var i = 0; i < data.length; ++i) {
            total += H * total + data.charCodeAt(i);
        }
        return total % this.table.length;
    }
    
    /*碰撞处理
    * 1、开链法:开链法是指实现散列表的底层数组中,每个数组元素又是一个新的数据结构,比如另一个数组,这样就能存储多个键了
    * 2、线性探测法 线性探测法检查散列表中的下一个位置是否为空。如果为空,就将数据存入该位置;如果不为空,则继续检查下一个位置,直到找到一个空的位置为止
    * */
    /*
    * 两个方法该如何选择?
    * 当存储数据使用的数组特别大时,选择线性探测法要比开链法好。这里有一个公式,常常
     可以帮助我们选择使用哪种碰撞解决办法:如果数组的大小是待存储数据个数的 1.5 倍,
     那么使用开链法;如果数组的大小是待存储数据的两倍及两倍以上时,那么使用线性探
     测法。
    * */
    /*下面这些方法是对上面的方法重新或新增*/
    
    /*开链法*/
    
    function buildChains() {
        for(var i = 0; i < this.table.length;i++) {
            this.table[i] = new Array();
        }
    }
    // function showDistro() {
    //     for(var i = 0 ; i < this.table.length;i++) {
    //         if (this.table[i][0] !== undefined) {
    //             console.log(i + ":" +this.table[i])
    //         }
    //     }
    // }
    // function put(data) {
    //     var pos = this.simpleHash(data);
    //     this.table[pos].push(data);
    // }
    
    /*线性探测法*/
    
    function put(data) {
        var pos = this.simpleHash(data);
        while (this.table[pos] !== undefined) {
            pos++;
        }
        this.table[pos] = data;
    }
  • 相关阅读:
    idea中yml文件变成text样式并且没有提示
    挂载redhat镜像创建本地yum源
    Windows环境下Oracle数据库的自动备份脚本
    Oracle存储过程锁表
    DDL和客户端ip监控
    Linux 单实例oracle安装步骤
    Linux常用命令
    Linux常用目录
    oracle基础知识及语法
    Linux下Oracle新建用户并且将已有的数据dmp文件导入到新建的用户下的操作流程
  • 原文地址:https://www.cnblogs.com/yunnex-xw/p/9869993.html
Copyright © 2011-2022 走看看