数据结构与算法——哈希表

哈希表代码实现

package com.gykalc.hashtable;

import java.util.Iterator;

/**
 * 哈希表:是一种数据结构
 *  存入的数据与数组的下标是通过一个hash函数得出的,即hash(value)得到存放的数组的位置
 *  但是hash(value)不能保证所有不同的value,得出的下标都不一样,这就是hash冲突的问题
 *  如何避免hash冲突呢?就是我们数组中存放的是一个链表,当两个值得到一样的下标,那么就
 *  使用链表存放这些值,下面我们自定义一个哈希表
 */
public class HashTableDemo {

    public static void main(String[] args) {
        MyHashTable<String, String> myHashTable = new MyHashTable<>();
        myHashTable.put("NO001", "贵永康");
        myHashTable.put("NO002", "刘畅");
        myHashTable.put("123", "444");
        System.out.println(myHashTable.get("NO002"));
        System.out.println(myHashTable.get("NO003"));
        System.out.println(myHashTable.toString());

    }

    static class MyHashTable<K, V> {
        // 默认nodes的数组容量
        private static final int DEFAULT_CAPITAL = 16;
        // 实际nodes的数组容量
        private int capital;
        // 哈希表中的元素个数
        private int size;
        // 链表数组
        private MyLinkedList<Node>[] nodeListArray;

        public MyHashTable() {
            this(DEFAULT_CAPITAL);
        }

        public MyHashTable(int capital) {
            this.capital = capital;
            nodeListArray = new MyLinkedList[capital];
        }


        public void put(K key, V value) {
            int n = hash(key);
            Node newNode = new Node<>(key, value);
            if (nodeListArray[n] == null) {
                nodeListArray[n] = new MyLinkedList<>();
            }
            nodeListArray[n].add(newNode);
            this.size++;
        }

        public V get(K key) {
            int n = hash(key);
            if (nodeListArray[n] != null) {
                Iterator<Node<K, V>> it = nodeListArray[n].iterator();
                while(it.hasNext()) {
                    Node<K, V> next = it.next();
                    if (next.key.equals(key)) { // 找到了
                        return next.value;
                    }
                }
            }
            return null;
        }

        /**
         * hash算法,就只是取容量的模
         * @param key
         * @return
         */
        public int hash(K key) {
            return key.hashCode() % capital;
        }

        class Node<K, V> {
            private K key;
            private V value;

            public Node(K key, V value) {
                this.key = key;
                this.value = value;
            }
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("MyHashTable{");
            for (int i = 0; i < capital; i++) {
                if (nodeListArray[i] == null) {
                    break;
                }
                Iterator<Node<K, V>> iterators = nodeListArray[i].iterator();
                while (iterators.hasNext()) {
                    Node<K, V> next = iterators.next();
                    sb.append(next.key.toString() + ": " + next.value + ", ");
                }
            }
            // 去掉尾部的逗号
            sb.delete(sb.lastIndexOf(","), sb.length());
            sb.append("}");
            return sb.toString();
        }
    }
}

class MyLinkedList<E> implements Iterable{
    private Node head = null;
    private int size = 0;

    class MyLinkedListIterator implements Iterator {
        private int index = 0;
        @Override
        public boolean hasNext() {
            return index < size();
        }

        @Override
        public E next() {
            E e = get(index);
            index++;
            return e;
        }
    }

    /**
     * 往链表中添加元素
     * @param e
     */
    public void add(E e) {
        Node newNode = new Node(e);
        if (head == null) {
            head = newNode;
        }else {
            Node temp = head;
            while(temp.next != null) {
                temp = temp.next;
            }
            temp.next = newNode;
        }
        this.size++;
    }

    /**
     * 根据下标获取元素
     * @param index
     * @return
     */
    public E get(int index) {
        int i = 0;
        Node temp = head;
        while(temp != null) {
            if (index == i) {
                break;
            }
            i++;
            temp = temp.next;
        }
        if (temp != null) {
            return temp.e;
        }else {
            return null;
        }
    }

    /**
     * 获取链表长度
     * @return
     */
    public int size() {
        return this.size;
    }

    /**
     * 删除指定元素
     * @param e
     */
    public void remove(E e) {
        Node temp = head;
        Node preNode = temp;
        while(temp != null && !temp.e.equals(e)) {
            if (temp.next == null) {
                break;
            }
            preNode = temp;
            temp = temp.next;
        }
        if (temp != null && temp.e.equals(e)) { // 说明找到了
            if (preNode == head) { // 如果前一个元素就是head,将head制空
                head = null;
                this.size--;
            }else {
                // 找到被删除节点的下一个节点
                preNode.next = temp.next;
                this.size--;
            }
        }
    }

    /**
     * 遍历打印链表数据
     */
    public void list() {
        Node temp = head;
        while(temp != null) {
            System.out.print(temp.e + " ");
            temp = temp.next;
        }
    }

    @Override
    public Iterator iterator() {
        return new MyLinkedListIterator();
    }

    class Node {
        private E e;
        private Node next;

        public Node(E e) {
            this.e = e;
        }

        public Node getNext() {
            return next;
        }

        public void setNext(Node next) {
            this.next = next;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值