1)、開放地址法中,通過在哈希表中再找一個空位解決衝突問題。
2)、鏈地址法中,某個數據項的關鍵字值還是像通常一樣映射到哈希表的單元,而數據項本身插入到這個單元的鏈表中,其他同樣映射到該位置的數據項只需要加入到鏈表中。
鏈地址法Java簡縮代碼:
/**
* 節點類
*/
class Link{
private int data;
public Link next;
public Link(int data){
this.data = data;
this.next = null;
}
public int getKey(){
return this.data;
}
public void display(){
System.out.println(this.data);
}
}
/**
* 優先級鏈表
*/
class SortedList{
private Link first;
public SortedList(){
this.first = null;
}
public void insert(Link theLink){
int key = theLink.getKey();
Link current = this.first;
Link previous = null;
while (current != null && key > current.getKey()){
previous = current;
current = current.next;
}
if (previous != null){
previous.next = theLink;
}else{
this.first = theLink;
}
theLink.next = current;
}
public Link find(int key){
Link current = this.first;
while (current != null && key != current.getKey()){
current = current.next;
}
return current;
}
public void display(){
Link current = this.first;
while (current != null){
current.display();
current = current.next;
}
}
}
/**
* 鏈地址哈希表
*/
class HashTableLink{
private SortedList[] hashArray;
private int arraySize;
public HashTableLink(int size){
this.arraySize = size;
this.hashArray = new SortedList[this.arraySize];
for (int i = 0; i < this.arraySize; i++){
this.hashArray[i] = new SortedList();
}
}
public int keyFunc(int key){
return key % this.arraySize;
}
public void insert(Link theLink){
int key = keyFunc(theLink.getKey());
this.hashArray[key].insert(theLink);
}
public Link find(int key){
key = keyFunc(key);
return this.hashArray[key].find(key);
}
public void display(){
for (int i = 0; i < this.arraySize; i++){
System.out.println("i: " + i);
this.hashArray[i].display();
}
}
}
public class HashTableTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
HashTableLink htl = new HashTableLink(3);
for (int i = 1; i < 12; i ++){
Link link = new Link(i);
htl.insert(link);
}
htl.display();
}
}
開放地址法
import java.io.InputStreamReader;
import java.io.BufferedReader;
/**
* @Class HashTableApp
* @Description 哈希表,開放地址法的線性探索算法
* @Company OpenData
* @author Chenlly
* @Date 2009-03-20
* @version 1.0 算法:關鍵字值的範圍是從0到200,數組的初始化大小是20,一般爲素數。哈希函數必須把關鍵字的範圍壓縮
* 到數組的範圍,所以用到的哈希函數是求模函數 arrayIndex = key%arraySize
*/
class DataItem {
private int iData;
public DataItem(int iData) {
this.iData = iData;
}
public int getIData() {
return iData;
}
public void setIData(int data) {
iData = data;
}
}
public class HashTableApp {
private static final int MAX_SIZE = 20;
private DataItem[] intArray;
private DataItem nonItem;
//構造函數
public HashTableApp(int size){
intArray = new DataItem[size];
//填充數據項爲-1對象
nonItem = new DataItem(-1);
}
// 哈希函數
public static int hashFunc(int key) {
return key % MAX_SIZE;
}
//顯示哈希表中的數據,如果還沒有數據項則以**填充,如果是被刪除的數據項則以-1填充
public void display() {
System.out.println("The Table:");
for (int i = 0;i<MAX_SIZE;i++ ) {
if (intArray[i] != null){
System.out.print(intArray[i].getIData()+"");
} else {
System.out.print("**");
}
System.out.print(" ");
}
}
// 插入數據項到哈希表中,經過哈希函數把關鍵字填充到數組,如果產出衝突,往後查找空白位,然後插入。
// 可能會出現分佈不均勻,把一連串連續的填充單元叫做聚焦
public void insert(DataItem dataItem) {
int key = dataItem.getIData();
int hashValue = HashTableApp.hashFunc(key);
while (intArray[hashValue] != null && intArray[hashValue].getIData() != -1) {//爲-1的數據項是刪除了的數據項,可以再填充
hashValue++;
}
intArray[hashValue] = dataItem;
}
// 如果對鍵入的關鍵字值經過哈希函數得到的數據下標就是要找的對象,則查找成功。否則衝突,產生衝突就的往後一個一個查找叫做探測
// 如果在探測過程中遇到空位說明查找失敗,因爲插入算法本應該把數據項插入這個位置的
public DataItem find(int key) {
int hashValue = HashTableApp.hashFunc(key);
while (intArray[hashValue] != null){
if (intArray[hashValue].getIData() == key){
return intArray[hashValue];
} else {
hashValue++;
hashValue %= MAX_SIZE;
}
}
return null;
}
// 刪除算法,是把要刪除的關鍵字值對應的數組值置-1。
public DataItem delete(int key) {
int hashValue = HashTableApp.hashFunc(key);
while (intArray[hashValue] != null) {
if (intArray[hashValue].getIData() == key) {
DataItem temp = intArray[hashValue];
intArray[hashValue] = nonItem;
return temp;
} else {
hashValue++;
hashValue %= MAX_SIZE;
}
}
return null;
}
//從鍵盤上讀取數據
public static String readStr() {
InputStreamReader ir = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(ir);
String str = "";
try {
str = br.readLine();
} catch (Exception ex) {
ex.printStackTrace();
}
return str;
}
//主調函數
public static void main(String []args){
System.out.println("請選擇操作序列");
System.out.println("1 插入數據項");
System.out.println("2 通過key查找數據項");
System.out.println("3 刪除一個數據項");
System.out.println("4 顯示哈希表");
System.out.println("5 退出");
HashTableApp hashTableApp = new HashTableApp(MAX_SIZE);
while (true) {
System.out.println("");
System.out.println("請選擇操作序列");
int op = Integer.parseInt(HashTableApp.readStr());
switch (op) {
case 1:
System.out.println("請輸入數據項,範圍0~200");
int nData = Integer.parseInt(HashTableApp.readStr());
DataItem dataItem = new DataItem(nData);
hashTableApp.insert(dataItem);
break;
case 2:
System.out.println("請輸入需要查找的關鍵字");
int key = Integer.parseInt(HashTableApp.readStr());
DataItem findItem = hashTableApp.find(key);
if (findItem == null) {
System.out.println("查找失敗");
} else {
System.out.println("the Data "+findItem.getIData());
}
break;
case 3:
System.out.println("請輸入需要刪除的關鍵字");
int delKey = Integer.parseInt(HashTableApp.readStr());
DataItem delItem = hashTableApp.delete(delKey);
if (delItem == null) {
System.out.println("刪除失敗");
} else {
System.out.println("the Data "+delItem.getIData()+"is deleted");
}
break;
case 4:
hashTableApp.display();
break;
case 5:
default:
System.exit(0);
}//end switch
}//end while
}//end main
}