1. 程式人生 > >【資料結構與演算法】【查詢】雜湊表的程式碼實現

【資料結構與演算法】【查詢】雜湊表的程式碼實現

// Filename: hash.c

#include <stdio.h>
#include <stdlib.h>
#include "public.h"
#include "hash.h"

// 雜湊表初始化,雜湊表長度為size
int InitHashTable(HashTable *pH, int size)
{
    int i = 0;

    if ((!pH) || (size <= 0))
    {
        return HASH_ERROR_INIT;
    }

    pH->pElem =  malloc(sizeof(HElemType) * size);
    if (!pH->pElem)
    {
        return HASH_ERROR_MALLOC;
    }

    for (i = 0; i < size; i++)
    {
        pH->pElem[i] = HASH_ELEM_INVALID_VALUE;
    }
    pH->totalnum = size;
    pH->existnum = 0;

    return OK;
}

// 雜湊函式:計算雜湊地址
int Hash(int key)
{
    return key % HASH_TABLE_SIZE;
}

// 查詢關鍵字,返回雜湊地址
int SearchHash(HashTable *pH, int key, int *pAddr)
{
    if ((!pH) || (!pAddr)) return ERROR;

    // key值不能和Hash表元素的初始預設值相同,否則就會被後面的元素覆蓋
    if (HASH_ELEM_INVALID_VALUE == key) return HASH_ERROR_KEY;

    // 進行查詢操作
    *pAddr = Hash(key);
    while (pH->pElem[*pAddr] != key)
    {
        *pAddr = (*pAddr + 1) % HASH_TABLE_SIZE;
        if ((HASH_ELEM_INVALID_VALUE == pH->pElem[*pAddr]) || (*pAddr == Hash(key)))
        {
            return HASH_ERROR_NOT_FOUND;
        }
    }

    return OK;
}

// 插入元素,衝突處理方法:開放定址法線性探測
int InsertHash(HashTable *pH, int key)
{
    int addr;

    if (!pH) return ERROR;

    // key值不能和Hash表元素的初始預設值相同,否則就會被後面的元素覆蓋
    if (HASH_ELEM_INVALID_VALUE == key) return HASH_ERROR_KEY;

    // 表滿則無法插入,返回錯誤
    if (pH->existnum >= pH->totalnum) return HASH_ERROR_FULL;

    // 已經插入的元素,不能重複插入
    if (OK == SearchHash(pH, key, &addr))
    {
        printf("該元素已經在雜湊表中,無需重複插入\n");
        return OK;
    }

    // 進行插入操作
    addr = Hash(key);
    while (HASH_ELEM_INVALID_VALUE != pH->pElem[addr])
    {
        addr = (addr + 1) % HASH_TABLE_SIZE;
    }

    pH->pElem[addr] = key;
    pH->existnum++;
    return OK;
}

// 刪除關鍵字,有則刪除,沒有不做操作
int DeleteHash(HashTable *pH, int key)
{
    int addr;

    if (!pH) return ERROR;

    // key值不能和Hash表元素的初始預設值相同,否則就會被後面的元素覆蓋
    if (HASH_ELEM_INVALID_VALUE == key) return HASH_ERROR_KEY;

    if (OK == SearchHash(pH, key, &addr))
    {
        if (pH->existnum <= 0) pH->existnum = 1; // 此處應提示異常,說明程式實現有問題;
        pH->pElem[addr] = HASH_ELEM_INVALID_VALUE;
        pH->existnum--;
    }

    //printf("DeleteHash(): 未找到待刪除元素%d.", key);
    return OK;
}

// 列印雜湊表
void PrintHash(HashTable *pH)
{
    int i;
    if (!pH) return;

    printf("雜湊表: 空間大小: %d, 元素數量: %d.\n", pH->totalnum, pH->existnum);
    printf("-----------------------------------\n");
    printf("下標    元素值\n");
    printf("-----------------------------------\n");

    for (i = 0; i < pH->totalnum; i++)
    {
        printf("%-8d%-6d\n", i, pH->pElem[i]);
    }
    printf("-----------------------------------\n");
    return;
}

int hash_main()
{
    int input;
    int addr;
    int key;
    int retCode;
    HashTable H;

	while (1)
	{
		printf("----------------------------------\n");
		printf("雜湊表基本操作\n");
		printf("----------------------------------\n");
		printf("0.建立/初始化雜湊表\n");
		printf("1.插入元素\n");
		printf("2.刪除元素\n");
		printf("3.查詢元素\n");
		printf("4.列印雜湊表\n");
		printf("9.退出系統\n");
		printf("----------------------------------\n");
		printf("請選擇:");
		scanf("%d", &input);
		getchar();

		switch (input)
		{
            case 0:
                retCode = InitHashTable(&H, HASH_TABLE_SIZE);
                if (OK == retCode)
                {
                    printf("建立/初始化雜湊表成功!\n");
                }
                else
                {
                    printf("建立/初始化雜湊表失敗!!!\n");
                }
                break;


            case 1:
                printf("請輸入待插入元素: --> ");
                scanf("%d", &key);
                retCode = InsertHash(&H, key);
                if (OK == retCode)
                {
                    printf("插入元素成功!\n");
                }
                else
                {
                    printf("插入元素失敗!!!\n");
                }
                break;

            case 2:
                printf("請輸入待刪除元素: --> ");
                scanf("%d", &key);
                retCode = DeleteHash(&H, key);
                if (OK == retCode)
                {
                    printf("刪除元素成功!\n");
                }
                else
                {
                    printf("刪除元素失敗!!!\n");
                }
                break;

            case 3:
                printf("請輸入待查詢元素: --> ");
                scanf("%d", &key);
                retCode = SearchHash(&H, key, &addr);
                if (OK == retCode)
                {
                    printf("查詢元素成功, 所在位置為: %d.\n", addr);
                }
                else
                {
                    printf("查詢元素失敗!!!\n");
                }
                break;

            case 4:
                PrintHash(&H);
                break;

            case 9:
                printf("系統已退出!\n");
                exit(0);

            default:
                printf("無效,請重新選擇操作!\n");
                exit(0);
		}
	}

    return 0;
}