数据结构-散列查找
散列函數(shù):一個(gè)把查找表中的關(guān)鍵字映射成該關(guān)鍵字對(duì)應(yīng)的地址的函數(shù),記為Hash(key)=Addr。
散列函數(shù)可能會(huì)把兩個(gè)或以上的不同關(guān)鍵字映射到同一地址,稱(chēng)這種情況為”沖突“,這些發(fā)生碰撞的不同關(guān)鍵字稱(chēng)為同義詞。
一方面,設(shè)計(jì)好的散列函數(shù)應(yīng)盡量減少這樣的沖突;另一方面,由于這樣的沖突是不可避免的,所以還要設(shè)計(jì)好處理沖突的方法。
散列表:是根據(jù)關(guān)鍵字而直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu)。也就是說(shuō),散列表建立了關(guān)鍵字和存儲(chǔ)地址之間的一種直接映射關(guān)系。
以下簡(jiǎn)單示例通過(guò)除留余數(shù)法的方式構(gòu)造散列函數(shù),通過(guò)開(kāi)放地址法的方式處理沖突。
// // Created by Administrator on 2018/7/12. // #include "stdio.h" #include "stdlib.h"#define HASHSIZE 10 #define NULLKEY NULL typedef struct {int *elem; //通過(guò)指針的方式代替數(shù)組int size; //當(dāng)前容量 } HashTable;/*** 初始化創(chuàng)建hashtable* @return*/ HashTable createHashTable() {HashTable hashTable;hashTable.size = 0;hashTable.elem = (int *) malloc(HASHSIZE * sizeof(int));for (int i = 0; i < HASHSIZE; ++i) {//初始化數(shù)據(jù)hashTable.elem[i] = NULLKEY;}return hashTable; }/*** 通過(guò)除留余數(shù)法構(gòu)造hash函數(shù)* @param key 關(guān)鍵字key* @return*/ int hash(int key) {int hash = key % HASHSIZE;return hash; }/*** 向hashtable中插入元素* @param hashTable* @param key* @return*/ HashTable put(HashTable hashTable, int key) {int addr = hash(key);while (hashTable.elem[addr] != NULLKEY) {//該位置已存在元素,使用簡(jiǎn)單的開(kāi)放地址法處理沖突addr = (hash(key) + 1) % HASHSIZE;}hashTable.elem[addr] = key;hashTable.size++;return hashTable; }/*** 查找元素在hashtable中的位置* @param hashTable* @param key* @return*/ int search(HashTable hashTable, int key) {int addr = hash(key);int elem = hashTable.elem[addr];while (elem != key) {addr = (addr + 1) % HASHSIZE;elem = hashTable.elem[addr];if (elem == NULLKEY || addr == hash(key)) {//遍歷完成 仍然沒(méi)有找到return -1;}}return addr; }int main() {HashTable hashTable = createHashTable();for (int i = 5; i < 15; i++) {hashTable = put(hashTable, i);}int key = 14;int addr = search(hashTable, key);printf("查找到key=%d的元素,地址=%d", key, addr);printf("\nhashtable 當(dāng)前容量=%d", hashTable.size); }總結(jié)
- 上一篇: 数据结构-顺序查找和折半查找
- 下一篇: 二进制四则运算