015查找、排序、符号表、散列表等算法实现(1)

本文参考《算法(第4版)》

基本的查找、排序、符号表、散列表算法实现汇总1

1.比较和交换

package algorithms.model;

public class Smethod {
    public static void exch(int[] a,int i, int j){
    	int temp = a[i];
    	a[i] = a[j];
    	a[j] = temp;
    }
    public static int less(int[] a,int i, int j){
    	if(a[i] < a[j])
    		return -1;
    	else if(a[i] > a[j])
    		return 1;
    	else return 0;
    }  
}

2.选择排序

package algorithms.rank;

import java.util.Arrays;

import algorithms.model.Smethod;

class Selection {
    public static int[] sort(int[] a, int lo, int hi){ 
    	for(int i = lo; i < hi +1; i++){ 
 		   int min = i;
 		   for(int j = i+1; j < hi + 1; j++){
 			    if(a[min]>a[j])
 				    min = j;
    	   }
 		   Smethod.exch(a, i, min);
        }
    	return a;
    }
	public static void main(String[] args) { 
		 int[] a = {4,5,14,6,7,98,44,56,1,3}; 
		 for(int i : sort(a, 0, a.length-1))
			 System.out.print(i + " "); 
	}
}

3.插入排序

package algorithms.rank;  
import algorithms.model.Smethod; 

public class Insertion {
    public static int[] sort(int[] a, int lo, int hi){ 
    	for(int i = lo + 1; i < hi + 1; i++)
    		 for(int j = i; j > lo; j--){
    			 if(a[j] < a[j-1])
    				 Smethod.exch(a, j, j-1);
    		 }
    	return a;
    }
    //测试用例
	public static void main(String[] args) {
		int[] a = {4,5,14,6,7,98,44,56,1,3}; 
		 for(int i : sort(a, 0, a.length-1))
			 System.out.print(i + " ");  
	} 
}

4.希尔排序

package algorithms.rank;

import algorithms.model.Smethod;

class Shell { 
	public static int[] sort(int[] a, int lo, int hi){ 
		 int N = hi - lo + 1;
		 int h = 1; 
		 while(h < N)
			 h = 3*h + 1;
		 while(h > 0){
			 for(int i = h; i < hi + 1; i++)
				 for(int j = i; j - h > lo - 1; j = j - h){
					 if(a[j] < a[j-h])
						 Smethod.exch(a, j, j-h); 
				 } 
			 h = h/3;
		 }
		return a; 
		 
	}
	public static void main(String[] args) {
		int[] a = {4,5,14,6,7,98,44,56,1,3,24,54,67,78,89,81,13,15}; 
		 for(int i : sort(a, 0, a.length-1))
			 System.out.print(i + " "); 
	}

}

5.归并排序

package algorithms.rank;
import algorithms.model.Smethod;

class Merge {
    public static void merge(int[] a, int lo, int mid, int hi){
    	 int[] auk = new int[a.length];
    	 int i = lo;
    	 int j = mid + 1;
    	 for(int k = lo; k <= hi; k++)
    		 auk[k] = a[k];
    	 for(int k = lo; k <= hi; k++)
    		 if(i > mid) a[k] = auk[j++];
    		 else if  (j > hi) a[k] = auk[i++];
    		 else if  (Smethod.less(auk, i, j) < 0) a[k] = auk[i++];
    		 else a[k] = auk[j++];
    }
    public static void sort(int[] a, int lo, int hi){
    	 if(hi <= lo) return;
    	 int mid = lo + (hi - lo)/2;
    	 sort(a, lo, mid);
    	 sort(a, mid+1, hi);
    	 merge(a, lo, mid, hi);
    }
	public static void main(String[] args) { 
		int[] b = {1,12,13,14,5,6,17,35,56};
		merge(b,0,3,8);
		for(int i : b)
 			 System.out.print(i + " "); 
		System.out.println(); 
		
		int[] a = {11,9,2,3,4,5,11,1,71};  
 		sort(a,0,a.length-1); 
 		for(int i : a)
 			 System.out.print(i + " "); 
	}
}

6.快速排序

package algorithms.rank;

import algorithms.model.Smethod;

public class Quick {
    public static void sort(int[] a, int lo, int hi){
    	 if(hi<=lo) return;
    	 int j = position(a, lo, hi);
    	 sort(a, lo, j-1);
    	 sort(a, j+1, hi);
    }
    public static int position(int[] a, int lo, int hi){
    	int v = a[lo];
    	int i = lo; 
    	int j = hi + 1;
    	while(true){ 
   		    while(a[++i] < v) if(i == hi) break;
    	    while(a[--j] > v) if(j == lo) break;
    	    System.out.println(i +" : " + j);
    		if(i >= j)         break;
    		Smethod.exch(a, i, j);
    		for(int m : a){
    			System.out.print(m + " ");
    		}
    		System.out.println();   
    		
    	}
    	Smethod.exch(a, lo, j);
    	return j;
    }
	public static void main(String[] args) {
		 int[] a = {5,6,5,5,5,4};   
		 int[] b = {6,5,4,3,2,1}; 
		 //int[] a = {5, 4};
		 int N = a.length;
		 sort(a, 0, N-1); 
		 for(int i : a)
			 System.out.print(i + " "); 

	}

}

7.三向快速排序

package algorithms.rank;

import algorithms.model.Smethod;

class Quick3way {
    public static void sort(int[] a, int lo, int hi){
    	if(hi<=lo) return;
    	int v = a[lo];
    	int lt = lo; 
    	int i =  lt + 1;
    	int gt = hi;
    	while(i <= gt){
    		int cmp = a[i] - v;
    		if     (cmp < 0) Smethod.exch(a, lt++, i++);
    		else if(cmp > 0) Smethod.exch(a, gt--, i); 
    		else i++;
    	}
    	sort(a, lo, lt - 1);
    	sort(a, gt + 1, hi);
    	
    	
    }
	public static void main(String[] args) {
		int[] a = {11,9,11,11,78,56,81,35,32,31,33,45,78,64,11,11,11,11,33,33,33,33,33,2,3,4,5,11,1,71};  
		//System.out.print(a.length);
		sort(a,0,a.length-1); 
 		for(int i : a)
 			 System.out.print(i + " ");  
	}
}

8.基于二叉堆的优先队列及堆排序

基于二叉堆的最大优先队列以及堆排序实现:

 package algorithms.rank;
//基于二叉堆的最大优先队列以及堆排序实现
public class MaxPQ<T extends Comparable<T>>{
    private  T[] pq;      //基于的数组
    private  int N = 0;   //优先队列长度 ,持有元素的个数
	public MaxPQ(int MaxN){//预先设定数组大小
    	pq = (T[])new Comparable[MaxN + 1]; 
    } 
    public int size(){
    	return N;
    }
    public boolean isEmpty(){
    	return N == 0;
    }
    private boolean isFull(){
    	return N >= pq.length - 1;
    }  
	private void resize(int max){ 
		T[] temp = (T[])new Comparable[max]; //辅助数组,pq.length=max
		for(int i = 1; i <= N; i++)   
			temp[i] = pq[i];
		pq = temp;        
    }
    private void exch(int i, int j){
    	  T temp = pq[i];
    	  pq[i] = pq[j];
    	  pq[j] = temp;
    }
    private boolean less(int i, int j){
       //System.out.println("pq["+i+"]="+pq[i]+",pq["+j+"]="+pq[j]+";N="+N);
  	   return pq[i].compareTo(pq[j]) < 0;
    }
    private void swim(int k){//较大值上浮 
    	while(k > 1 && less(k/2, k)){//k > 1即k=2,3时
    		exch(k, k/2);
    		k = k/2; 
    	} 
    }
    private void sink(int k){//较小值下沉 
    	while(2*k <= N){
    		int j = 2*k;
    		if(j < N && less(j, j + 1)) j++;
    		if(!less(k, j))  break; 
    		exch(k, j);
    		k = j;
    	}
    }
    //在长度为M的数组中下沉
    private void sink(int k, int M){//较小值下沉 ;
    	while(2*k <= M){
    		int j = 2*k;
    		if(j < M && less(j, j + 1)) j++; //j < M在less(j, j + 1)之前;此处是j<M而不是j<N
    		if(!less(k, j)) break; 
    		exch(k, j);
    		k = j;
    	}
    }
    //上浮堆排序
    public void insert(T v){
    	if(isFull())    resize(2*pq.length);
    	pq[++N] = v;    //索引0处不存储元素。
    	swim(N); 
    } 
    public T delMax(){
    	 T max = pq[1];  //从根节点获取最大元素;
    	 exch(1, N--);   //根节点元素和最后一个交换,同时数组长度减1
    	 pq[N+1] = null; //防止越界
    	 sink(1);        //恢复堆有序 
    	 if(N > 0 && N < pq.length/4) resize(pq.length/2);
    	 //System.out.println("length= " + pq.length + " ,N = " + N); 
    	 return max; 
    }
    public void sort(){ //堆排序
    	int M = N;//N是pq的当前长度属性,而M是个临时变量。数组的长度和数组存放的元素数量是不一样的。
    	for(int k = M/2; k >= 1; k--) //堆的构造
    		sink(k, M);  
    	while(M > 1){      //下沉排序
    		exch(1, M--);
    		sink(1, M);  
    	}
    }
    public void print(){//从数组的位置1开始使用;打印堆有序数组
    	for(int i = 1; i <= N; i++)
    	   System.out.print(pq[i]+" ");
    }
    public void set(T[] b){
    	for(int i = 0; i < b.length; i++){
    		pq[i+1] = b[i];
    		N++;
    	} 
    }
    
	public static void main(String[] args) {  
		Integer[] b = {11,19,21,13,4,5,15,1,45,11,24,54,6,7,3,71}; 
	    MaxPQ<Integer> MaxPQ2 = new MaxPQ<Integer>(b.length+1);
	    for(Integer v : b)
	    	MaxPQ2.insert(v);
	    System.out.println("构造堆:"); 
	    MaxPQ2.print(); //71 54 45 24 21 19 15 13 11 4 11 5 6 7 3 1 
	    System.out.println();
	    System.out.println("逐个删除最大值"); 
	    while(MaxPQ2.size()>0)
		       System.out.println(MaxPQ2.delMax()+" "); // 71 54 45 24 21 19 15 13 11 11 7 6 5 4 3 1 
	     
	    MaxPQ<Integer> MaxPQ3 = new MaxPQ<Integer>(b.length+1);
	    for(Integer v : b)
	    	MaxPQ3.insert(v);
	    System.out.println();
	    System.out.println("构造堆:"); 
	    MaxPQ3.print(); //71 54 45 24 21 19 15 13 11 4 11 5 6 7 3 1 
	    System.out.println();
	    System.out.println("堆排序:"); 
	    MaxPQ3.sort(); 
	    MaxPQ3.print(); //1 3 4 5 6 7 11 11 13 15 19 21 24 45 54 71
	}

}


输出:

构造堆:
71 54 45 24 21 19 15 13 11 4 11 5 6 7 3 1 
逐个删除最大值
71 
54 
45 
24 
21 
19 
15 
13 
11 
11 
7 
6 
5 
4 
3 
1 

构造堆:
71 54 45 24 21 19 15 13 11 4 11 5 6 7 3 1 
堆排序:
1 3 4 5 6 7 11 11 13 15 19 21 24 45 54 71 

基于二叉堆的最小优先队列以及堆排序实现:

package algorithms.rank;
//基于二叉堆的最小优先队列以及堆排序实现
public class MinPQ<T extends Comparable<T>>{
    private  T[] pq;      //基于的数组
    private  int N = 0;   //优先队列长度 
	public MinPQ(int MaxN){//预先设定数组大小
    	pq = (T[])new Comparable[MaxN + 1]; 
    } 
    public int size(){
    	return N;
    }
    public boolean isEmpty(){
    	return N == 0;
    }
    private boolean isFull(){
    	return N == pq.length - 1;
    } 
    private void resize(int max){ 
		T[] temp = (T[])new Comparable[max]; //辅助数组
		for(int i = 1; i <= N; i++)   
			temp[i] = pq[i];
		pq = temp;        
    }
    private void exch(int i, int j){
    	  T temp = pq[i];
    	  pq[i] = pq[j];
    	  pq[j] = temp;
    }
    private boolean bigger(int i, int j){
  	   return pq[i].compareTo(pq[j]) > 0;
    } 
    private void swim(int k){//较小值上浮
    	if(k <= 1)   return;
    	while(k > 1 && bigger(k/2, k)){//k > 1即k=2,3时
    		exch(k, k/2);
    		k = k/2; 
    	} 
    }
    
    private void sink(int k){//较大值下沉
    	if(k < 1) return;
    	while(2*k <= N){
    		int j = 2*k;
    		if(j < N && bigger(j, j + 1)) j++;
    		if(!bigger(k, j))  break; 
    		exch(k, j);
    		k = j;
    	}
    }
    //在长度为M的数组中下沉
    private void sink(int k, int M){//较大值下沉 ;
    	if(k < 1) return;
    	while(2*k <= M){
    		int j = 2*k;
    		if(j < M && bigger(j, j + 1)) j++;//j < M在less(j, j + 1)之前;此处是j<M而不是j<N
    		if(!bigger(k, j)) break; 
    		exch(k, j);
    		k = j;
    	}
    }
    //使用上浮堆排序
    public void insert(T v){
    	if(isFull()) resize(2*pq.length);
    	pq[++N] = v; 
    	swim(N); 
    }
    public T delMin(){
    	 T min = pq[1];  //从根节点获取最小元素;
    	 exch(1, N--);   //根节点元素和最后一个交换,同时数组长度减1
    	 pq[N+1] = null; //防止越界取值
    	 sink(1);        //恢复堆有序 
    	 if(N > 0 && N < pq.length/4) resize(pq.length/2);
    	 //System.out.println("length= " + pq.length + " ,N = " + N); 
    	 return min; 
    }
    
    public void sort(){ //进行堆排序
    	int M = N;//N是pq的当前长度属性,而M是个临时变量。数组的长度和数组存放的元素数量是不一样的。
    	for(int k = M/2; k >= 1; k--)
    		sink(k, M);
    	while(M > 1){
    		exch(1, M--);
    		sink(1, M);
    	}
    }
    public void print(){//从数组的位置1开始使用
    	for(int i = 1; i <= N; i++)
    	   System.out.print(pq[i]+" ");
    }
    public void set(T[] b){
    	for(int i = 0; i < b.length; i++){
    		pq[i+1] = b[i];
    		N++;
    	} 
    }
	public static void main(String[] args) { 
	    Integer[] b = {11,19,21,13,4,5,15,1,45,11,24,54,6,7,3,71}; 
	    MinPQ<Integer> minPQ2 = new MinPQ<Integer>(b.length+1);
	    for(Integer v : b)
	    	minPQ2.insert(v);
	    System.out.println("构造堆:"); 
	    minPQ2.print(); //1 4 3 11 11 6 5 19 45 13 24 54 21 15 7 71
	    System.out.println();
	    System.out.println("逐个删除最小值"); 
	    while(minPQ2.size()>0)
		       System.out.println(minPQ2.delMin()+" "); // 1 3 4 5 6 7 11 11 13 15 19 21 24 45 54 71
	     
	    MinPQ<Integer> minPQ3 = new MinPQ<Integer>(b.length+1);
	    for(Integer v : b)
	    	minPQ3.insert(v);
	    System.out.println();
	    System.out.println("构造堆:"); 
	    minPQ3.print(); //1 4 3 11 11 6 5 19 45 13 24 54 21 15 7 71
	    System.out.println();
	    System.out.println("堆排序:"); 
	    minPQ3.sort(); 
	    minPQ3.print(); //71 13 54 19 45 15 21 7 11 11 24 6 5 4 3 1
	     
	    
	}

}

输出:

构造堆:
1 4 3 11 11 6 5 19 45 13 24 54 21 15 7 71 
逐个删除最小值
1 
3 
4 
5 
6 
7 
11 
11 
13 
15 
19 
21 
24 
45 
54 
71 

构造堆:
1 4 3 11 11 6 5 19 45 13 24 54 21 15 7 71 
堆排序:
71 54 45 24 21 19 15 13 11 11 7 6 5 4 3 1 

9.基于有序数组的二分查找实现符号表

package algorithms.search;
/**
 * 基于有序数组的二分查找实现符号表 
 * */ 
//Key, Value为泛型参数
public class BinarySearchST<Key extends Comparable<Key>, Value> {
    private Key[]   keys;
    private Value[] vals;
    private int N;
    BinarySearchST(int capacity){
    	keys = (Key[])new Comparable[capacity];
    	vals = (Value[])new Object[capacity];
    	this.N = 0;
    }
    public int size(){
    	return N;
    }
    public boolean isFull(){
    	return N == keys.length;
    }
    public boolean isEmpty(){
    	return N == 0;
    }
    
    public void put(Key key, Value val){
    	 int i = rank(key);
    	 if(i < N && key.compareTo(keys[i])==0){
    		 vals[i] = val; 
    		 return;   //跳出函数,不再往下执行;
    	 } 
		 for(int j = N; j > i; j--){
			 keys[j] = keys[j-1];
		     vals[j] = vals[j-1];
		 }
		 keys[i] = key;
		 vals[i] = val;
		 N++;  
    }
    public Value get(Key key){
    	if(isEmpty()) return null;
    	int i = rank(key);
    	if(i < N && key.compareTo(keys[i])==0)
    		return vals[i];
    	return null;
    }
    public Key min(){
    	return keys[0];
    }
    public Key max(){
    	return keys[N-1];
    }
    //选择排名为k的键;
    public Key select(int k){
    	if( k < N && k >= 0)
    	  return keys[k];
    	else return null;
    }
    //大于等于key的最小值
    public Key ceiling(Key key){
    	int i = rank(key);
    	if( i == N ) return null;
        return keys[i];
        //or
//        if( i < N) return keys[i];
//        else return null;
    }
    //小于等于key的最大值
    public Key floor(Key key){
    	int i = rank(key);
    	if(i < N && key.compareTo(keys[i])==0)
    		return keys[i];
    	return keys[i-1];
    }
    public boolean contains(Key key){
    	int i = rank(key);
    	if( i < N && key.compareTo(keys[i]) == 0)
    		return true;
    	return false;
    }
  //rank()方法返回小于键的键的数量,lo的取值范围为[0,N];
  //大于中间值,小的索引往右移;小于中间值,大的索引往左移动
    public  int rank(Key key){
    	int lo = 0;
    	int hi = N - 1;
    	while(lo <= hi){
    		int mid = lo + (hi - lo)/2;
    		int cmp = key.compareTo(keys[mid]);
    		if(cmp < 0)      hi = mid - 1;
    		else if(cmp > 0) lo = mid + 1;
    		else             return mid; 
    	}
    	return lo;
    }
    public String printKeys(){ 
    	return keys.toString();
    }
	public static void main(String[] args) {
		BinarySearchST<Integer , Integer> bst = new BinarySearchST<Integer, Integer>(50);
		for(int i = 0; i < 10; i++)
		   bst.put(i, i*2);
        System.out.println(bst.N);
        System.out.println(bst.printKeys());
        System.out.println(bst.select(3));
        System.out.println(bst.contains(3));
        System.out.println(bst.get(4));
        for(int i = 0; i < bst.N; i++)
        	System.out.print(bst.get(i)+ " ");
	}
}

10.二叉树

package algorithms.search;
/*
 * 二叉树实现
 * */
class BST2<Key extends Comparable<Key>, Value> {
	    private Node root;
	    private class Node{
	    	private Key key;
	    	private Value val;
	    	private Node left, right;
	    	private int N;
	    	Node(Key key, Value val, int N){
	    		this.key = key;
	    		this.val = val;
	    		this.N = N;
	    	}
	    }
	    public void print(){
	    	print(root);
	    }
	    private void print(Node x){
	    	 if(x == null) return;
	    	 print(x.left);
	    	 System.out.println(x.key);
	    	 print(x.right);
	    }
    	public int size(){
    		return size(root);
    	}
    	private int size(Node x){
    		if(x == null) return 0;
    		else return x.N;
    	}
    	public Value get(Key key){
    		return get(root, key);
    	}
    	private Value get(Node x, Key key){
    		if(x == null) return null;
    		int cmp = key.compareTo(x.key);
    		if(cmp < 0)      return get(x.left, key);
    		else if(cmp > 0) return get(x.right, key);
    		else return x.val;  
    	}
    	public void put(Key key, Value val){
    		root = put(root, key, val);
    	}
    	private Node put(Node x, Key key, Value val){
    		  if(x == null) return new Node(key, val, 1);
    		  int cmp = key.compareTo(x.key);
    		  if(cmp < 0)      x.left = put(x.left, key, val);
    		  else if(cmp > 0) x.right = put(x.right, key, val);
    		  else  x.val = val;  
    		  x.N = size(x.left) + size(x.right) + 1;
    		  return x;
    	} 
    	public Value min(){ 
    		 return min(root).val;
    	}
    	private Node min(Node x){
   		 if(x.left == null) return x;
   		 return min(x.left);
   	    }
    	public Value max(){ 
   		 return max(root).val;
   	    }
     	private Node max(Node x){
  		 if(x.right == null) return x;
  		 return max(x.right);
  	    }
     	public void deleteMin(){
     		root = deleteMin(root);
     	}
        private Node deleteMin(Node x){
        	 if(x.left == null)   return x.right;
        	 x.left = deleteMin(x.left);
        	 x.N = size(x.left) + size(x.right) + 1;
        	 return x;
     	}
        public Node delete(Key key){
        	return delete(root, key);
        }
        private Node delete(Node x, Key key){
        	if(x == null) return null;
        	int cmp = key.compareTo(x.key);
        	if(cmp < 0)        x.left = delete(x.left, key);
        	else if(cmp > 0)   x.right = delete(x.right, key);
        	else {
        		if(x.left == null)  return x.right;
        		if(x.right == null) return x.left;
        		Node t = x;
        		x = min(t.right);
        		x.right = deleteMin(t.right);
        		x.left = t.left;
        	} 
    		x.N = size(x.left) + size(x.right) + 1;
        	return x;
        }
        
        public Key select(int k){
        	return select(root, k).key;
        }
        private Node select(Node x, int k){
        	if(x == null)  return null;
        	int t = size(x.left);
        	if(t > k)      return select(x.left, k);
        	else if(t < k) return select(x.right, k-t-1);
        	else 		   return x;
        }
        
        private int rank(Key key, Node x){
        	if(x == null) return 0;
        	int cmp = key.compareTo(x.key);
        	if(cmp < 0)      return rank(key, x.left);
        	else if(cmp > 0) return 1 + size(x.left) + rank(key, x.right);
        	else             return size(x.left);
        }
        
    
	public static void main(String[] args) {
		BST2<String, Integer> bst = new BST2<String, Integer>();
		String[]  keys = "I love Beijing Gugong".split(" "); 
		Integer[] vals = {1,3,4,5}; 
		int i = 0;
		System.out.println(vals.toString());
		for(String str : keys)
		    bst.put(str, vals[i++]);
		bst.print();
		System.out.println(bst.size()); 
	}

}

package algorithms.search;
//基于拉链的散列表
public class SeparateChainingHashST<Key, Value> {
    private int M;
    private int N;
    private SeparateChainingHashST<Key, Value>[] st;
    public SeparateChainingHashST(){
    	this(997);
    }
    public SeparateChainingHashST(int M){
    	this.M = M;
    	st = (SeparateChainingHashST<Key, Value>[])new SeparateChainingHashST[M];
        for(int i = 0; i < M; i++)
        	st[i] = new SeparateChainingHashST();
    }
    public int hash(Key key){ 
    	//Key的hashCode()若未覆盖Object的hashCode(),则key.hashCode()为Object的版本,取对象地址
    	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);
    }
}

11.基于拉链的散列表

package algorithms.search;
//基于拉链的散列表
public class SeparateChainingHashST<Key, Value> {
    private int M;
    private int N;
    private SeparateChainingHashST<Key, Value>[] st;
    public SeparateChainingHashST(){
    	this(997);
    }
    public SeparateChainingHashST(int M){
    	this.M = M;
    	st = (SeparateChainingHashST<Key, Value>[])new SeparateChainingHashST[M];
        for(int i = 0; i < M; i++)
        	st[i] = new SeparateChainingHashST();
    }
    public int hash(Key key){ 
    	//Key的hashCode()若未覆盖Object的hashCode(),则key.hashCode()为Object的版本,取对象地址
    	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);
    }
}

12.基于线性探索的散列表

package algorithms.search; 
import java.util.ArrayList;   
import java.util.List;

import mPackage.newStack;

//基于线性探索的散列表
public class LinearProbingHashST<Key, Value> {
    private  int N;
    private  int M = 16;
    private Key[]   keys;
    private Value[] vals;
    LinearProbingHashST(){
    	keys = (Key[])new Object[M];
    	vals = (Value[])new Object[M];
    } 
    LinearProbingHashST(int cap){
    	keys = (Key[])new Object[cap];
    	vals = (Value[])new Object[cap];
    	this.M = cap;
    }
    //Key的hashCode()若未覆盖Object版本的hashCode(),此处是默认取地址,相同的键会产生不同的散列值
    //所以应该覆盖重写盖Object版本的hashCode(),保证相通的键产生相同的散列值
    //hash()只是散列表的散列函数,要首先在类Key中保证key.hashCode()覆盖重写
    //即要求Key的具体类型的类是同时覆盖equals()和hashCode()
    //尝试去掉KeyTest的hasCode()代码运行看下结果
    public int hash(Key key){
    	return (key.hashCode() & 0x7fffffff)%M;
    }
    public void put(Key key, Value val){
    	if(N >= M/2)   resize(2*M);
    	int i;
    	for(i = hash(key); keys[i] != null; i = (i+1)%M )
    		if(keys[i].equals(key)){
    			vals[i] = val;
    			return;
    		}
    	keys[i] = key;
    	vals[i] = val;
    	N++;
    }
    public Value get(Key key){
    	for(int i = hash(key); keys[i] != null; i = (i+1)%M)
		      if( keys[i].equals(key) )
		    	  return vals[i];
    	return null;
    }
    public void resize(int cap){
    	LinearProbingHashST<Key, Value> st;
    	st = new LinearProbingHashST<Key, Value>(cap);
    	for(int i = 0; i < M; i++){
    		if(keys[i] != null)
    		   st.put(keys[i], vals[i]);
    	}
    	keys = st.keys;
    	vals = st.vals; 
    	M = st.M; 
    }
    
    public boolean contains(Key key){
    	for(int i = hash(key); keys[i] != null; i = (i + 1)%M)
    		 if(keys[i].equals(key))
    			 return true;
    	return false;
    }
    
    public   void delete(Key key){
    	if(!contains(key)) return;  //防止为st空时进行删除;
    	int i = hash(key);
    	while(!keys[i].equals(key))
    		  i = (i + 1)%M;
    	keys[i] = null;
    	vals[i] = null;
    	i = (i + 1)%M;
    	while(keys[i]!=null){
    		 Key keyToRedo = keys[i];
    		 Value valToRedo = vals[i];
    		 keys[i] = null;
    		 vals[i] = null;
    		 N--;                      //N--;为什么放在put()前?
    		 put(keyToRedo,valToRedo); //重新插入(移动)删除键后面对的键的散列值,即更新键的散列值;
    		 i = (i + 1)%M; 
    	}
    	N--;//针对于被删除的键
    	if(N >0 && N == M/8) resize(M/2);
    }
    
    public int getN(){
    	return this.N;
    }
    
    public int getM(){
    	return this.M;
    }
   
	public static void main(String[] args) {
		LinearProbingHashST<KeyTest, ValueTest> st = 
				new LinearProbingHashST<KeyTest, ValueTest>();
		
		for(int i = 0; i < 10; i++)
           st.put(new KeyTest(i), new ValueTest(i*10));
		
		System.out.println(st.hash(new KeyTest(3)));
		System.out.println(st.hash(new KeyTest(3))); 
		System.out.println(st.hash(new KeyTest(4)));
		
		System.out.println(st.contains(new KeyTest(3)));
		
		System.out.println(st.get(new KeyTest(3)));
		
		st.delete(new KeyTest(3));
		System.out.println(st.contains(new KeyTest(3)));
		System.out.println(st.getN());
		
		LinearProbingHashST<KeyTest, ValueTest> st2 = 
				new LinearProbingHashST<KeyTest, ValueTest>();
		//测试resize()
		for(int i = 0; i < 100; i++)
	           st2.put(new KeyTest(i), new ValueTest(i*10));
		System.out.println(st2.getN());
		System.out.println(st2.getM());
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值