雜湊表的運算演算法
阿新 • • 發佈:2020-07-28
一、開放定址法構造的雜湊表的運算演算法
1、雜湊表型別
#define NULLKEY-1 //定義空關鍵字
#define DELKEY-2 //定義被刪關鍵字
typedef int KeyType; //關鍵字型別
typedef struct
{
KeyType key; //關鍵字域
int count; //探測次數域
}HashTable;
2、插入建表演算法
void InsertHT(HashTable ha[],int &n,int m,int p,KeyType k) { int i,adr; adr=k%p; //計算雜湊函式值 if(ha[adr].key==NULLKEY||ha[adr].key==DELKEY) { ha[adr].key=k; //k可以直接放在雜湊表中 ha[adr].count=1; } else //發生衝突,用線性探測法解決衝突 { i=1; //i記錄k發生衝突的次數 do { ard=(ard+1)%m; //線性探測 i++; }while(ha[adr].key!=NULLKEY&&ha[adr].key!=DELKEY); ha[adr].key=k; //在adr處放置k ha[adr].count=i; //設定探測次數 } n++; //雜湊表中總元素個數增1 } void CreateHT(HashTable ha[],int &n,int m,int p,KeyType keys[],int nl) { for(int i=0;i<m;i++) { ha[i].key=NULLKEY; ha[i].count=0; } n=0; //雜湊表中總元素個數從0開始遞增 for(i=0;i<nl;i++) { InsertHT(ha,n,m,p,keys[i]); //插入n個關鍵字 } }
3、刪除演算法
bool DeleteHT(HashTable ha[],int &n,int m,int p,KeyType k) { int adr; adr=k%p; //計算雜湊函式值 while(ha[adr].key!=NULLKEY&&ha[adr].key!=k) { adr=(adr+1)%m; //線性探測 } if(ha[adr].key==k) //查詢成功 { ha[adr].key=DELKEY; //刪除k return true; } else return fales; }
4、查詢演算法
void SearchHT(HashTable ha[],int m,int p,KeyType k) { int i=1,adr; adr=k%p; while(ha[adr].key!=NULLKEY&&ha[adr].key!=k) { i++; //累計關鍵字比較次數 adr=(adr+1)%m; //線性探測 } if(ha[ard].key==k) //查詢成功 { printf("成功:關鍵字%d,比較%d次\n",k,i); } else { printf("失敗:關鍵字%d,比較%d次\n",k,i); } }
5、線性探測計算成功和不成功平均查詢長度
對於查詢不成功的理解:
根據雜湊函式地址為mod7,因此任何一個數經雜湊函式計算以後的初始地址只可能在0~6的位置
查詢0~6位置查詢失敗的查詢次數為:
地址0,到第一個關鍵字為空的地址2需要比較3次,因此查詢不成功的次數為3
地址1,到第一個關鍵字為空的地址2需要比較2次,因此查詢不成功的次數為2
地址2,到第一個關鍵字為空的地址2需要比較1次,因此查詢不成功的次數為1
地址3,到第一個關鍵字為空的地址4需要比較2次,因此查詢不成功的次數為2
地址4,到第一個關鍵字為空的地址4需要比較1次,因此查詢不成功的次數為1
地址5,到第一個關鍵字為空的地址2(比較到地址6,再迴圈回去)需要比較5次,因此查詢不成功的次數為5
地址6,到第一個關鍵字為空的地址2(比較到地址6,再迴圈回去)需要比較4次,因此查詢不成功的次數為4
二、拉鍊法構造的雜湊表的運算
1、雜湊表型別
typedef int KeyType; //關鍵字型別
typedef struct node
{
KeyType key; //關鍵字域
struct node *next; //下一個結點指標
}NodeType;
typedef struct
{
NodeType *firstp; //首節點指標
}HashTable;
2、插入建表演算法
void InsertHT(HashTable ha[],int &n,int p,KeyType k)
{
int adr;
adr=k%p; //計算雜湊函式值
NodeType *q;
q=(NodeType *)malloc(sizeof(NodeType));
q->key=k; //建立結點q,存放k
q->next=NULL;
if(ha[adr].firstp==NULL) //若單鏈表adr為空
{
ha[adr].firstp=q;
}
else
{
q->next=ha[adr].firstp; //頭插法
ha[adr].firstp=q;
}
n++; //雜湊表中結點總個數增1
}
void CreateHT(HashTable ha[],int &n,int m,int p,KeyType keys[],int nl)
{
for(int i=0;i<m;i++) //置初值
{
ha[i].firstp=NULL;
}
n=0;
for(i=0;i<nl;i++)
{
InsertHT(ha,n,p,keys[i]); //插入n個關鍵字
}
}
3、刪除演算法
bool DeleteHT(HashTable ha[],int &n,int m,int p,KeyType k)
{
int adr;
adr=k%p; //計算雜湊函式值
NodeType *q,*preq;
q=ha[adr].firstp; //q指向首節點
if(q==NULL)
return false;
if(q->key==k) //首節點為k
{
ha[adr].firstp=q->next; //刪除結點q
free(q);
n--;
return true;
}
preq=q; q=q->next; //首節點不為k
while(q!=NULL)
{
if(q->key==k) //查詢成功
break; //退出迴圈
q=q->next;
}
if(q!=NULL) //查詢成功
{
preq->next=q->next; //刪除結點q
free(q);
n--; //結點總數減1
return true;
}
else
return false;
}
4、查詢演算法
void SearchHT(HashTable ha[],int m,int p,KeyType k)
{
int i=1,adr;
adr=k%p;
NodeType *q;
q=ha[adr].firstp; //q指向對應單鏈表的首節點
while(q!=NULL) //掃描adr單鏈表所有結點
{
i++;
if(q->key==k) //查詢成功
break;
q=q->next;
}
if(q!=NULL)
{
printf("成功:關鍵字%d,比較%d次\n",k,i);
}
else
{
printf("失敗:關鍵字%d,比較%d次\n",k,i);
}
}