泛型-哈希表

泛型

  • 自定义类型的TreeMap和TreeSet的要求:要么类型是Comparable,要么构造时传入Comparator

  • 泛型类/泛型方法

  • 把握E…是一个类型变量,有其作用域,类名称后面的是定义类型变量,其余后面都是使用

  • 谁是谁的父类问题
    List不是List的父类
    List<?>是List的父类

  • 泛型是编译期间的工作
    -不能使用静态类或者静态方法

哈希表

  • 构建步骤:
    1.内部数据结构是数组
    2.关键字经过变换(hash函数)得到int类型的值
    3.int类型的值变成一个合法的数组下标
    4.把关键字放入数组的该下标位置

  • 哈希冲突/哈希碰撞:对于不同的key,经过哈希后,找到了相同的下标

  • 负载因子=填入表中的元素个数 / 数组长度

  • 尽量避免哈希冲突,减少冲突的方法:
    1.哈希函数的设计,(尽可能的让出来的下标均匀分布)
    2.负载因子的调节:
    负载因子越少,冲突率越低
    数据个数不能动,所以吧数组长度扩大
    事先规定好一个值,来控制resize

  • 解决冲突的方法:闭散列 开散列
    【1】闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以 把key存放到冲突位置中的“下一个” 空位置中去。
    1.线性探测 2.二次探测法
    【2】开散列:又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子 集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。哈希桶

  • 试题:求查找成功的平均查找长度和查找失败的平均查找长度
    在这里插入图片描述

  • 时间复杂度为O(1).

//哈希表key-value模型
public class HashBucket {
    private static class Node{
        private int key;
        private int val;
        Node next;
        public Node(int ket,int val){
            this.key=key;
            this.val=val;
        }
    }
    private Node[]array;
    private int size;
    private static final double LOAD_FACTOR=0.75;

    public  HashBucket() {
        array=new Node[8];
        size=0;
    }

    //get
    public int get(int key){
        int index=key%array.length;
        for(Node cur=array[index];cur!=null;cur=cur.next){
            if(key==cur.key)
                return cur.val;
        }
        return -1;
    }
    //put
    public int put(int key,int val){
        // key => int
        // int 合法的下标
        int index=key%array.length;
        // 2. 在链表中查找 key 所在的结点
        //      如果找到了,更新
        //      所有结点都不是 key,插入一个新的结点
        for(Node cur=array[index];cur!=null;cur=cur.next){
            if(key==cur.key){
                int oldval=cur.val;
                cur.val=val;
                return oldval;
            }
        }
        //没找到就作头插
        Node node=new Node(key,val);
        node.next=array[index];
        array[index]=node;
        size++;
        if(loadfactor()>LOAD_FACTOR){
            resize();
        }
        return -1;
    }
/*扩容 需要考虑到 重新哈希  因为数组长度已经发生改变
两层循环  外层遍历数组  内层遍历链表
    */
    private void resize() {
      Node []newarray=new Node[array.length*2];
      for(int i=0;i<array.length;i++){
          Node next;
          for(Node cur=array[i];cur!=null;cur=next){
              next=cur.next;
              int index=cur.key%newarray.length;
              cur.next=newarray[index];
              newarray[index]=cur;
          }
      }
      array=newarray;
    }
    //负载因子
    private double loadfactor(){
        return size*1.0/array.length;
    }

    public static void main(String[] args) {
        
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值