【数据结构】哈希表的原理及实现

简介: 【数据结构】哈希表的原理及实现

1.什么是哈希表

  • 哈希表又称为散列表,它是一种以键值对形式来存储数据的结构,只要输入待查找的key,就可以通过该key寻找到对应的值。对应函数:y = f(key)
  • 通过把关键码映射到表中的对应位置来访问对应信息,来加快查找速度
  • 哈希表用的是数据支持下标随机、访问数据的特性来实现的,所以说哈希表是数组的扩展,是由数组演化而成。
  • 数据储存 可以通过 数组+链表 的方式来实现
  • 哈希表示意图:
  • 88bd6512a89a4f44b8f6fdc00c5ee0c2.jpg

为什么要使用哈希表?

  • 我们知道,在使用数据进行数据查找是,是从头来进行查询的,这样即查找的方式即慢,又不方便。但使用哈希表就可以提高检索速度,减少资源的消耗。

2.哈希表功能实现

哈希表中增加数据 put(K key,V value)
根据key获取对应的value V get(K key)
删除指定key的元素 remove(K key)
输出哈希表中所有元素 show()

(1)哈希表初始化


ca2932973f6e42e2a652fcdab576a656.jpg

(2)新增哈希表中数据

fee5796bb5714724bc15e0734625512c.jpg

(3)修改哈希表中指定key 的value

651509acecd9489e8be62a561d760048.jpg

(4)删除哈希表中指定key的元素

14e65dab069e486abacf5c22c7bd98ef.jpg

(5)遍历输出哈希表中所有数据

0d9b3f088ab5446f9715dbb93fd26bab.jpg

3.哈希表代码实现

(1)整体代码实现

/**
 * 哈希表实现
 * @param <K>
 * @param <V>
 */
public class HashTable<K,V> {
    public static void main(String[] args) {
        HashTable<Integer,String> hashTable = new HashTable<>();
        hashTable.put(1,"李祥");
        hashTable.put(2,"张三");
        hashTable.put(3,"李四");
        System.out.println("新增三个元素 :李祥,张三,李四");
        System.out.println("打印当前哈希表:");
        hashTable.show();
        System.out.println("获取key为3的元素value:"+ hashTable.get(3));
        System.out.println("修改key为3的元素value为 小李 :");
        hashTable.put(3,"小李");
        System.out.println("打印当前哈希表:");
        hashTable.show();
        System.out.println("删除key为2的元素:");
        hashTable.remove(2);
        hashTable.show();
    }
    /**
     * 定义链表数组
     */
    private final LinkedList<K,V>[] linkedArr;
    /**
     * 默认数组长度
     */
    private final static int DEFAULT_LENGTH = 10;
    /**
     * 定义数组的容量
     */
    public int maxSize;
    /**
     * 构造方法初始化
     */
    public HashTable(){
        //定义数组的最大长度
        this.maxSize = DEFAULT_LENGTH;
        //初始化数组
        linkedArr = (LinkedList<K,V>[]) new LinkedList[maxSize];
        //对数组中的每一条链表都要初始化
        for(int i=0;i<maxSize;i++){
            linkedArr[i]=new LinkedList<>();
        }
    }
    /**
     * put 元素
     * @param key
     * @param value
     */
    public void put(K key,V value){
        //key取hashcode根据数组长度取余获取index
        int hashCode = key.hashCode();
        int index =(hashCode % maxSize);
        //把对应的课程 插入到对应的哈希表
        Node<K, V> oldNode = linkedArr[index].get(key);
        //如果当前key 不存在 则表示新增,如果key存在表示替换原有的value
        if(oldNode==null){
            //创建Node节点
            Node<K,V> node = new Node<>(key,value);
            linkedArr[index].add(node);
        }else{
            linkedArr[index].update(key,value);
        }
    }
    /**
     * 根据key值获取value
     * @param key
     * @return
     */
    public V get(K key){
        //获取数组的index
        int hashCode = key.hashCode();
        int index =(hashCode % maxSize);
        //链表中查找key对应的value
        Node<K, V> node = linkedArr[index].get(key);
        return node.value;
    }
    /**
     * 根据key值获取value
     * @param key
     * @return
     */
    public void remove(K key){
        //获取数组的index
        int hashCode = key.hashCode();
        int index =(hashCode % maxSize);
        //链表中查找key对应的value
        linkedArr[index].remove(key);
    }
    /**
     * 输出当前哈希表中的所有元素
     */
    public void show(){
        List<String> showStr = new ArrayList<>();
        for (int i = 0; i < linkedArr.length; i++) {
            List<Node<K, V>> list = linkedArr[i].list();
            for (Node<K, V> node : list) {
                String strNode = "{key="+node.key+",value="+node.value+"}";
                showStr.add(strNode);
            }
        }
        System.out.println("["+String.join(",",showStr)+"]");
    }
    /**
     * 链表存储数据
     * @param <K>
     * @param <V>
     */
    class LinkedList<K,V>{
        /**
         * 定义头节点
         */
        private Node<K,V> head;
        /**
         * 链表中增加数据
         * @param course
         */
        public void add(Node<K,V> data){
            //如果说 head==null  把第一个元素加进去
            if(head==null){
                head=data;
                return;
            }
            // 遍历添加
            Node<K,V> cur=head;
            while (cur.next != null) {
                //跳出循环的条件
                //找到最后一个节点
                cur = cur.next;
            }
            cur.next=data;
        }
        /**
         * 获取链表中全部数据
         */
        public List<Node<K,V>> list(){
            List<Node<K,V>> nodeList = new ArrayList<>();
            if(head==null){
                return nodeList;
            }
            //获取每一项加入到集合中
            Node<K,V> cur=head;
            while (true){
                nodeList.add(cur);
                if(cur.next==null){
                    break;
                }
                cur=cur.next;
            }
            return nodeList;
        }
        /**
         * 根据key 获取对应的node
         * @param key
         * @return
         */
        public Node<K,V> get(K key){
            if(head==null){
                return null;
            }
            //链表有课程 遍历输出 创建一个辅助指针
            Node<K,V> cur=head;
            while (!cur.key.equals(key)) {
                cur = cur.next;
            }
            return cur;
        }
        /**
         * 修改链表中的对应key的值
         * @param key
         * @param value
         */
        public void update(K key, V value) {
            //如果说 head==null,直接返回
            if(head==null){
                return;
            }
            //添加的不是第一门课程 遍历添加
            Node<K,V> cur=head;
            do {
                if(cur.key.equals(key)){
                    cur.value = value;
                    break;
                }
                cur = cur.next;
            }while(cur.next != null);
        }
        /**
         * 删除对应key的node
         * @param key
         * @return
         */
        public void remove(K key) {
            //如果说 head==null,直接返回
            if(head==null){
                return;
            }
            //遍历查找到对应key的node节点
            int x = 0;
            Node<K,V> cur = head;
            while(cur != null) {
                x++;
                if(cur.key.equals(key)){
                    break;
                }
                cur = cur.next;
            }
            //当 cur 为空或这cur.next为空时
            if(cur==null||cur.next==null){
                //判断寻找节点是不是只有一个元素
                if(x == 1){
                    //只有一个元素时,将头节点改成null
                    head = null;
                }else{
                    //当是最后一个元素时,找到当前节点的前一个元素,将前一个元素的next改成null
                    Node<K,V> prev = head;
                    while(prev.next!=null){
                        if (prev.next.key.equals(key)){
                            break;
                        }
                        prev = prev.next;
                    }
                    prev.next=null;
                }
                return;
            }
            cur.key = cur.next.key;
            cur.value = cur.next.value;
            cur.next = cur.next.next;
        }
    }
    class Node<K,V>{
        /**
         * 定义数据
         */
        public V value;
        /**
         * 定义key
         */
        public K key;
        /**
         * 定义下一个节点的
         */
        public Node<K,V> next;
        public Node(K key,V value) {
            this.value = value;
            this.key = key;
        }
    }
}

(2)代码测试

176af755dd144da396181ceaae704996.jpg

相关文章
|
2月前
|
算法
数据结构-哈希表(二)
数据结构-哈希表(二)
35 0
|
1天前
|
存储 算法 C++
数据结构/C++:哈希表
数据结构/C++:哈希表
7 2
|
1天前
|
存储 算法 安全
数据结构与算法 哈希表
数据结构与算法 哈希表
6 0
|
11天前
|
存储 算法 Java
22个常用数据结构实现与原理分析
前两天V哥跟一个老学员吃饭,聊起面试大厂的事,说为啥大厂面试第一看基本条件,第二就是考数据结构算法,其他高阶的内容会比较少,最近V哥也在跟大厂对接这一块业务,了解得多一些,这是因为考察基本功能力被放到了重要位置,大厂认为硬性条件,比如学历过关,基本功够扎实,那对于实际工作用的上层技能,内部培养就好,也就是相比你掌握了多少多少牛逼的高阶技术,他们更在乎你的基本功,所以,进大厂,基本功必须要搞稳,否则白扯,今天 V 哥把总结好的22个常用的数据结构实现原理,和示例分析分享给大家,希望对你有帮助,觉得内容有收获,请帮忙转发给更多需求的朋友,共同进步。
|
25天前
|
存储 机器学习/深度学习 移动开发
数据结构 第5 6 章作业 图 哈希表 西安石油大学
数据结构 第5 6 章作业 图 哈希表 西安石油大学
20 0
|
25天前
|
存储 算法 安全
上机实验四 哈希表设计 西安石油大学数据结构
上机实验四 哈希表设计 西安石油大学数据结构
16 0
|
1月前
|
算法 调度 C++
[数据结构与算法]贪心算法(原理+代码)
[数据结构与算法]贪心算法(原理+代码)
|
1月前
|
存储 算法 编译器
【数据结构】栈算法(算法原理+源码)
【数据结构】栈算法(算法原理+源码)
【数据结构】栈算法(算法原理+源码)
|
1月前
|
算法 搜索推荐 数据库
【数据结构】二叉树算法讲解(定义+算法原理+源码)
【数据结构】二叉树算法讲解(定义+算法原理+源码)
|
1月前
|
缓存 算法 搜索推荐
【数据结构】链表(单链表与双链表实现+原理+源码)
【数据结构】链表(单链表与双链表实现+原理+源码)