1. 程式人生 > >雜湊三部曲:二:第一部分:C語言實現 靜態雜湊表

雜湊三部曲:二:第一部分:C語言實現 靜態雜湊表

在這個靜態雜湊表中

我們用一個容量為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
請按任意鍵繼續. . .