面试必问:手撕哈希表

一、手撕哈希表?

哈希表包括插入,删除,包含操作
以插入操作为例,其手撕的过程主要分为以下几步:
1.把插入的对象转为int类型,调用hashCode()函数就可以了;
2.转为合法的下标(哈希函数:hash(key)=key%capacity),如:int index=hashValue%array.length;
3.遍历index位置处的链表,确定key在不在元素中
4.把key装进结点中,并插入到对应的链表中
5.维护元素的个数
6…通过维护负载因子,进而维护较低的负载因子

这六个步骤缺一不可,在面试的时候,主要是要用自己的将这六大步骤准确描述描述出来。这六大步骤记住了,代码也就比较容易写出来。

二、手撕过程

1.插入

插入过程就是以上六大步骤,主要在扩容的需要注意不能直接把原来链表的元素直接搬过去,扩容方法详细书写在后面。

public class MyHashTable {
    //实现一个HashTable首先需要一个数组
    private Node[] array=new Node[11];
    //维护哈希表中所有元素的个数
    private int size;

    //插入操作
    public boolean insert(Integer key){
        //1.把对象转为int类型
        int hashValue=key.hashCode();


        //2.把hashValue转成合法的下标
        int index=hashValue%array.length;

        //3.遍历index位置处的链表,确定key在不在元素中
        Node current=array[index];
        while(current!=null){
            if(key.equals(current.key)){
                return false;
            }

            current=current.next;
        }


        //4.把key装进结点中,并插入到对应的链表中
        Node node=new Node(key);
        node.next=array[index];
        array[index]=node;

        //5.维护元素的个数
        size++;

        //6.通过维护负载因子,进而维护较低的负载因子
        if(size/array.length*100>75){
            dilatation();
        }
        return true;
    }

2.删除

删除的过程也包括以上的六大步骤,不同的是还要定义一个要删除元素的前驱节点,容易出错的点就是:当prev为null时,删除的就是其头结点,不能忽略这一步。

 public boolean  remove(Integer key){
        //1.采用hashCode转为int类型
        int hashValue=key.hashCode();

        //2.得到合法的下标
        int index=hashValue%array.length;

        Node prev=null;
        Node current=array[index];
        while(current!=null){
            //删除操作
            if(key.equals(current.key)){
                if(prev!=null){
                    prev.next=current.next;
                }else{
                    //prev为null,删除的是头节点
                    array[index]=current.next;
                }
                size--;
                return true;

            }
            prev=current;
            current=current.next;

            }
        return false;

    }

3.包含

public boolean contains(Integer key){
        int hashValue=key.hashCode();
        int index=hashValue%array.length;
        Node current=array[index];
        while(current!=null){
            if(key.equals(current.key)){
                return true;
            }
            current=current.next;
        }
        return false;

    }

4.扩容

扩容的时候,要把原来的元素搬到新的数组中,但是不能按原链表搬,因为保存元素的下标和数组长度有关,数组的长度变了,下标也会变化,所以要重新计算每一个元素的下标。

public void dilatation(){
        Node[] newArray=new Node[array.length*2];
   
        for(int i=0;i<array.length;i++){
            Node current=array[i];
            while (current!=null){
                Integer key=current.key;
                int hashValue=key.hashCode();
                int index=hashValue%newArray.length;
                //头插
                Node node=new Node(key);
                node.next=newArray[index];
                newArray[index]=node;

                current=current.next;

            }
        }
        array=newArray;
    }

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI小艾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值