雜湊三部曲:二:第一部分:C語言實現 靜態雜湊表
阿新 • • 發佈:2018-12-13
在這個靜態雜湊表中
我們用一個容量為10 的靜態陣列作為雜湊表的底層構造
但是陣列的每一個儲存空間中又分為兩個部分
資料區:data
記錄所儲存的資料
狀態區:state
狀態區主要記錄這個空間的狀態;分別為:EXIST:表示這個位置已經存有元素
EMPTY:表示這個位置為空
DELET:表示這個位置存的元素是無效的被刪除的元素
新建標頭檔案;HashTable.h
底層構建:
#pragma once ////////////////////////靜態雜湊表/////////////////////////////////// #define MAX_SIZE 10 typedef int DataType; typedef enum {EXIST,EMPTY,DELET}State; typedef struct HTElem { DataType _data; //資料 State _state; //狀態 }HTElem; typedef struct HashTable { HTElem _array[MAX_SIZE]; int _size; //記錄雜湊表格中有效元素個數 int _total; //雜湊表中總元素個數:包含狀態為 存在的和刪除的 int _IsLineDetective; //是否是線性探測 int _capacity; }HT; void HashTableInit(HT *ht,int capacity,int IsLineDetective); //初始化 void HashTableInsert(HT *ht, DataType data); //插入元素 void HashTableDelet(HT *ht, DataType data); //刪除元素 int HashTableFind(HT *ht, DataType data); //查詢 int HashTableSize(HT *ht); //求有效元素個數 int HashTableEmpty(HT *ht); //判空 void PrintfHashBucket(HT* ht); //列印
操作函式
#include<stdio.h> #include<windows.h> #include<assert.h> int HashFunc(DataType data) //獲得雜湊地址 ( 插入和查詢時使用 ) { return data % MAX_SIZE; //除留餘數法 } int DetectiveLine(int hashAddr) //線性探測 ( 插入和查詢時使用 ) { hashAddr++; if (hashAddr == MAX_SIZE) // 處理越界 如果地址走到末尾,則又回到起始位置; hashAddr = 0; return hashAddr; } int Detective2(int hashAddr, int i) //二次探測 ( 插入和查詢時使用 ) { hashAddr = hashAddr + 2 * i + 1; if (hashAddr >= MAX_SIZE) // 處理越界 hashAddr %= MAX_SIZE; return hashAddr; } void HashTableInit(HT *ht,int capacity,int IsLineDetective) //初始化 { int i = 0; for (; i < MAX_SIZE; ++i) ht->_array[i]._state = EMPTY; ht->_size = 0; ht->_total = 0; ht->_capacity = capacity; ht->_IsLineDetective = IsLineDetective; } void HashTableInsert(HT *ht, DataType data) //插入 { int hashAddr = 0; int i = 0; assert(ht); if (ht->_total == MAX_SIZE) //空間已滿 return; //計算雜湊地址 hashAddr = HashFunc(data); while (EMPTY != ht->_array[hashAddr]._state) { //如果當前雜湊地址上已經有了元素 if (EXIST == ht->_array[hashAddr]._state) { if (data == ht->_array[hashAddr]._data) return; //如果當前位置上已經有了相同的元素;則不再重複插入 } //需要找下一個空位置 if (ht->_IsLineDetective) hashAddr=DetectiveLine(hashAddr); //以線性探測法找 else hashAddr =Detective2(hashAddr, ++i); //以二次探測法找 } //對找到的哈西地址進行插入元素 ht->_array[hashAddr]._data = data; ht->_array[hashAddr]._state = EXIST; ht->_size++; ht->_total++; } void HashTableDelete(HT * ht, DataType data) //刪除 { int ret = -1; assert(ht); ret = HashTableFind(ht, data); if(-1 !=ret) { ht->_array[ret]._state = DELET; ht->_size--; } } int HashTableFind(HT *ht, DataType data) //從當前雜湊地址找到下一個空位置 { int hashAddr = -1, starAddr = -1; //開始查詢的起始位置 int i = 0; assert(ht); hashAddr = HashFunc(data); //雜湊地址 starAddr = hashAddr; while (EMPTY != ht->_array[hashAddr]._state) //看地址內是否有資料 { if (EXIST == ht->_array[hashAddr]._state) //看當前地址的狀態 { if (data == ht->_array[hashAddr]._data) //看資料是否是我們查詢的 return hashAddr; } //到此說明在求得的哈西地址內沒有找到我們需要的資料,那麼就繼續往後找; if (ht->_IsLineDetective) { hashAddr=DetectiveLine(hashAddr); //以線性探測法找 if (hashAddr == starAddr) //找了一圈,又回到起始位置 都沒有找到 return -1; } else hashAddr=Detective2(hashAddr, ++i); //以二次探測法找 } return -1; } int HashTableSize(HT *ht) { assert(ht); return ht->_size; } int HashTableEmpty(HT *ht) { assert(ht); return 0 == ht->_size; } void PrintfHashBucket(HT* ht) //列印 { int i = 0; for (; i < ht->_capacity; i++) { if (EXIST == ht->_array[i]._state) printf("雜湊地址為%d的資料為:%d\n", i, ht->_array[i]._data); } }
進行測試
新建原始檔:Hash.c
#include"HashTable.h"
int main()
{
HT ht;
HashTableInit(&ht, 10, 1); //初始化
HashTableInsert(&ht, 1);
HashTableInsert(&ht, 4);
HashTableInsert(&ht, 6);
HashTableInsert(&ht, 5);
HashTableInsert(&ht, 3);
HashTableInsert(&ht, 15);
PrintfHashBucket(&ht);
printf("size為:%d \n", HashTableSize(&ht));
HashTableDelete(&ht, 3);
PrintfHashBucket(&ht);
printf("size為:%d \n", HashTableSize(&ht));
system("pause");
return 0;
}
執行結果:
雜湊地址為1的資料為:1
雜湊地址為3的資料為:3
雜湊地址為4的資料為:4
雜湊地址為5的資料為:5
雜湊地址為6的資料為:6
雜湊地址為7的資料為:15
size為:6
雜湊地址為1的資料為:1
雜湊地址為4的資料為:4
雜湊地址為5的資料為:5
雜湊地址為6的資料為:6
雜湊地址為7的資料為:15
size為:5
請按任意鍵繼續. . .