1.HashTable
散列表:可根據關鍵字直接訪問的數據結構。關鍵字與存儲地址存在映射關係。(以存儲空間換查找時間,空間換時間數據結構)
2.關鍵字與存儲地址的映射關係
通過散列函數將關鍵字映射指定地址。
設計散列函數:
1.直接定址:hash(key) = a*key+b 2.除留餘數法:hash(key) = key%p(簡單常用)
3.數字分析法 4.平方取中法 5.摺疊法
3.散列地址衝突
不同key映射相同散列會造成地址衝突,解決地址衝突的兩種方法:
1.開放地址:將地址衝突的key存儲到空閒的散列表中(Haddress=(hash(key)+d)%p,p爲表長)
d爲造成地址衝突後下一地址地增量
(1)d隨衝突次數增加而增加,稱線性探測法
(2)d隨隨衝突次數以平方增長,稱平方探測法
(3)d取對key再散列hash2*衝突次數,稱再散列法或雙散列法
(4)d取僞隨機序列(指有某種隨機特性的序列,序列元素間有確定關係存在),稱僞隨機序列法
2.鏈接法:
用鏈表存儲同地址衝突關鍵字,每一散列地址對應一鏈表。(有利於多元素的插入和刪除情況)
4.C實現(散列函數採取除留餘數法,地址衝突採取鏈接法解決)
#include <stdio.h>
#include <malloc.h>
#define OK 1
#define ERROR -1
#define CAPACITY 10
#define ElemType int
#define Status int
typedef struct _Node {
ElemType value;
_Node* next;
}Node;
typedef struct _HashTable {
Node elems[CAPACITY];
int count;
int capacity;
}HashTable;
Status InitHashTable(HashTable* ht);
Status InsertNode(HashTable* ht, ElemType elem);
Status Search(HashTable* ht, ElemType elem);
Node* new_Node();
int hash(int key); //計算key 對應地址, 求餘取址
Status addLinkNode(Node* list, ElemType elem);
void print_table(HashTable* ht) {
Node* head;
for (int i = 0; i < CAPACITY; i++) {
head = &ht->elems[i];
printf("elem[%d].head->:", i);
while (head->next) {
head = head->next;
printf(" %d ->", head->value);
}
printf("\n");
}
}
int main() {
int key[18] = { 1,2,4,55,11,44,22,33,77,4,5,10,8,9,666,12,14,15};
HashTable ht;
InitHashTable(&ht);
for (int i = 0; i < 18; i++) InsertNode(&ht, key[i]);
print_table(&ht);
int n; scanf("%d", &n);
return 0;
}
Status InitHashTable(HashTable* ht) {
for (int i = 0; i < CAPACITY; i++) {
ht->elems[i] = *new_Node();
ht->elems[i].value = -1;
ht->elems[i].next = NULL;
}
ht->capacity = CAPACITY;
return OK;
}
int hash(int key) {
return key % CAPACITY;
}
Status InsertNode(HashTable* ht, ElemType elem) {
int hash_address = hash(elem);
int status = addLinkNode(&ht->elems[hash_address],elem); //指定hashaddress的單鏈表添加元素
if (status == OK) {
ht->count++;
return OK;
}
return ERROR;
}
Status Search(HashTable* ht, ElemType elem) {
return 0;
}
Node* new_Node() {
return (Node*)malloc(sizeof(Node));
}
Status addLinkNode(Node* list, ElemType elem) {
Node* head = list;
while (head->next) {
head = head->next;
}
Node* newnode = new_Node();
newnode->value = elem;
newnode->next = NULL;
head->next = newnode;
return OK;
}