1. 程式人生 > >基於拉鍊法的散列表(來自:演算法)

基於拉鍊法的散列表(來自:演算法)

下列程式碼主要實現了基於拉鍊法的散列表的新增元素put(),查詢元素get(),刪除元素delete(),遍歷元素keys()等方法,我們需要首先根據元素值呼叫hash()方法找到該元素所對應的陣列,而每一個數組都是一個連結串列,遍歷連結串列,若元素不存在,則可以實現元素的新增,若存在,則可以實現元素的更新,刪除等操作.

對於每一條連結串列的操作

package cn.edu.zzuli.api;

import edu.princeton.cs.algs4.Queue;

public class SequentialSearchST<Key, Value> {
    private Node first;//連結串列首結點
	private class Node{
		//連結串列結點的定義
		private final Key key;
		private Value val;
		private Node next;
		
		public Node(Key key, Value val, Node next) {
			this.key = key;
			this.val = val;
			this.next = next;
		}
		public Key getKey() {
			return key;
		}

		public Value getVal() {
			return val;
		}

		public void setVal(Value val) {
			this.val = val;
		}

		public Node getNext() {
			return next;
		}

		public void setNext(Node next) {
			this.next = next;
		}
		
	}
	//查詢給定的鍵,返回相關聯的值
	public Value get(Key key) {
		for(Node i = first; i != null; i = i.next) {
            if(key.equals(i.key))
            	return i.val;
		}
		return null;
	}
	//查詢給定的鍵,找到則更新其值,否則在表中新建結點
	public void put(Key key, Value val) {
		for(Node i = first; i != null; i = i.next) {
			if(key.equals(i.key)) {
				i.val = val;
				return;
			}
		}
		first = new Node(key, val, first);
	}
	//刪除結點
	public void delete(Key key) {
		first = delete(first, key);
	}
	private Node delete(Node x, Key key) {
		if(x == null) {
			return null;
		}
		if(key.equals(x.key)) {
			return x.next;
		}
		x.next = delete(x.next, key);
		return x;
	}
	public Iterable<Key> keys(){
		Queue<Key> q = new Queue<Key>();
		for(Node i = first;  i != null; i = i.next) {
			q.enqueue(i.key);
		}
		return q;
	}
	public Key getKey() {
		return first.key;
	}
}

基於拉鍊法的散列表

package cn.edu.zzuli.api;

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

public class SeparateChainingHashST<Key, Value> {
	//SequetialSearchST
	private int N;//鍵值對總數
	private int M;//散列表的大小
	private SequentialSearchST<Key, Value>[] st;//存放連結串列物件的陣列
    public SeparateChainingHashST() {//預設的建構函式會使用997條連結串列
    	this(997);
    }
    public SeparateChainingHashST(int M) {
    	//建立M條連結串列
    	this.M = M;
    	//創造一個(SequentialSearchST<Key, Value>[])型別的,長度為M的陣列
    	st = (SequentialSearchST<Key, Value>[]) new SequentialSearchST[M];
    	for(int i = 0; i < M; i++) {
    		//為每一個數組元素申請一個空間
    		st[i] = new SequentialSearchST();
    	}
    }
    private int hash(Key key) {
    	return (key.hashCode() & 0x7fffffff) % M;
    }
    public Value get(Key key) {
    	return (Value)st[hash(key)].get(key);
    }
    public void put(Key key, Value val) {
    	st[hash(key)].put(key, val);
    }
    public void delete(Key key) {
    	st[hash(key)].delete(key);
    }
    public Iterable<Key> keys(){
    	Queue<Key> queue = new Queue<Key>();
    	for(int i = 0; i < M; i++) {
    		System.out.println("第" + i +"個元素的連結串列");
    		for(Key key : st[i].keys()) {
    			queue.enqueue(key);
    			System.out.print(key + " " + get(key) + " ,");
    		}
    		System.out.println();
    	}
    	return queue;
    }
    public static void main(String[] args) {
    	SeparateChainingHashST<String, Integer> st = new SeparateChainingHashST<String, Integer>(5);
        for (int i = 0; i < 13; i++) {
            String key = StdIn.readString();
            st.put(key, i);
        }
        for (String s : st.keys())
            StdOut.println(s + " " + st.get(s));
        st.delete("M");
        StdOut.println("*************************************");
        for (String s : st.keys()) {
        	 StdOut.println(s + " " + st.get(s));
        }
    }
}

測試用例

S E A R C H E X A M P L E