基于拉链法实现散列表

package chapter4;

import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.SeparateChainingHashST;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ChainingHashTable<Key extends Comparable<Key>,Value> {

    private int length;
    private int N;
    private ChainingTable<Key, Value>[] chainingTables;

    ChainingHashTable(){
        this(997);
    }

    public ChainingHashTable(int m){
        this.length = m;
        chainingTables = new ChainingTable[m];
        for(int i = 0 ; i < m; i++){
            chainingTables[i] = new ChainingTable<>();
        }
    }


    private void resize(int newLength){
        ChainingHashTable<Key,Value> temp = new ChainingHashTable(newLength);
        for(int i = 0; i < this.length; i++){
            for(Key key : this.chainingTables[i].keys()){
                temp.put(key, this.chainingTables[i].get(key));
            }
        }
        this.chainingTables = temp.chainingTables;
        this.N = temp.N;
        this.length = newLength;
    }


    public Value get(Key key){
        if(key == null){
            throw new IllegalArgumentException("key is null");
        }
        return this.chainingTables[hashCode(key)].get(key);
    }

    public void put(Key key, Value val){
        if(key == null){
            throw new IllegalArgumentException("key is null");
        }
        if(this.N > 10*this.length){
            resize(2*this.length);
        }

        if(!this.chainingTables[hashCode(key)].contains(key)){
            this.N++;
        }
        this.chainingTables[hashCode(key)].put(key,val);
    }

    // return keys in symbol table as an Iterable
    public Iterable<Key> keys() {
        Queue<Key> queue = new Queue<Key>();
        for (int i = 0; i < this.length; i++) {
            for (Key key : this.chainingTables[i].keys())
                queue.enqueue(key);
        }
        return queue;
    }

    private int hashCode(Key key){
        // s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
        //去掉高位,再平均分布到数组当中
        //length最好为素数,防止出现整除,影响分布均匀性
        return (key.hashCode() & 0x7fffffff) % this.length;
    }

    public void delete(Key key){
        if(this.chainingTables[hashCode(key)].contains(key)){
            this.N--;
        }
        this.chainingTables[hashCode(key)].delete(key);
        if(this.N < 2*this.length && this.length >= 4){
            resize(this.length/2);
        }
    }


    public static void main(String[] args) {
        SeparateChainingHashST<String, Integer> st = new SeparateChainingHashST<String, Integer>();
        for (int i = 0;  i < 10 ; i++) {

            String key = StdIn.readString();
            st.put(key, i);
        }

        // print keys
        for (String s : st.keys())
            StdOut.println(s + " " + st.get(s));

    }
}

class ChainingTable<Key extends Comparable<Key>,Value>{
    private int length;
    private Node head;

    ChainingTable(){
        this.head = null;
        this.length = 0;
    }
    
    private class Node{
        private Node next;
        private Key key;
        private Value value;

        Node(Key key, Value value){
            this.key = key;
            this.value = value;
            this.next = null;
        }

        public Value getValue() {
            return value;
        }
    }
    
    public Value get(Key key){
        Node temp = this.head;
        while(temp != null){
            if(temp.key.compareTo(key) == 0)
                return temp.getValue();
            temp = temp.next;
        }
        return null;
    }

    public void put(Key key, Value value){
        if(this.head == null){
            this.head = new Node(key,value);
        }else {
            Node temp = this.head;
            while(temp.next != null){
                temp = temp.next;
                if(temp.key.compareTo(key) == 0)
                    temp.value = value;
            }
            temp.next = new Node(key,value);
            this.length++;
        }

    }

    public void delete(Key key){
        if(this.head.key.compareTo(key) == 0){
            this.head = this.head.next;
            this.length--;
        }else{
            Node temp = this.head;
            Node preNode = null;
            while(temp != null){
                if(temp.key.compareTo(key) == 0 && preNode != null){
                    preNode.next = temp.next;
                    this.length--;
                }
                preNode = temp;
                temp = temp.next;
            }
        }
    }

    public boolean contains(Key key){
        Node temp = this.head;
        while(temp != null){
            if(temp.key.compareTo(key) == 0)
                return true;
            temp = temp.next;
        }
        return false;
    }

    public  List<Key> keys(){
        List<Key> keys = new ArrayList<>();
        Node temp = this.head;
        while(temp != null){
            keys.add(temp.key);
            temp = temp.next;
        }
        return keys;
    }


}

拉链法时数组加链表实现的散列表,主要时hashcode来保证数据的分布,java给不同类型的变量都实现了hashcode。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值