【查找算法】基于存储的查找算法(哈希查找)

哈希查找:又称散列查找

哈希表:根据关键字k,使用哈希函数i=f(k),计算出存储位置。

(1)哈希函数是一个映像,将关键字集合映射到地址集合上;

(2)哈希函数是压缩映像,可能产生冲突,即k1 != k2, 而f(k1)=f(k2),只能改进哈希函数减少冲突。

因此,一是要使用合适的哈希函数,二是选择冲突处理方法。

使用数组存储:

给定数列:{ 22,41,53,46,30,13,1,67 }

哈希函数:H(key) = key MOD 8 

线性探测解决冲突:Hi=(H(key)+di) MOD m ,di=1,2,…,m-1

使用链表:

编程:使用链表实现哈希表的创建、查询和删除。

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;

#define HASH_TABLE_LEN  100  
typedef struct _HashNode
{
    int key;
    int data;
    _HashNode *next;
}HashNode,*HashNodePtr;

typedef struct _HashRoot
{
    HashNode *next;
}HashRoot,*HashRootPtr;

//哈希表:表中每个元素是指向HashNode的一个指针
HashRootPtr HashTable[HASH_TABLE_LEN];


//添加节点时,动态分配空间
HashNodePtr InitHashNode(void)
{
    HashNodePtr node;
    node = (HashNode *)malloc(sizeof(HashNode));
    node->next = NULL;
    return node;
}

//初始化哈希表,表中每个HashNode指针都指向NULL
HashRootPtr InitHashTableHeader(void)
{
    HashRootPtr node;
    node = (HashRootPtr)malloc(sizeof(HashRootPtr));
    node->next = NULL;
    return node;
}

void InitHashTable(void)
{
    for (int i=0; i<HASH_TABLE_LEN; ++i)
    {
        HashTable[i] = InitHashTableHeader();
        HashTable[i]->next = NULL;
    }
}

//哈希函数:根据关键字获得在哈希表中的位置
int GetHashPosition(int key)
{
    int pos = 0;  
    pos = key % HASH_TABLE_LEN;  
    return pos;  
}

//添加节点
void AddHashNode(HashNodePtr new_node)
{
    HashNodePtr node;
    int pos = 0;
    new_node->next = NULL;
    pos = GetHashPosition(new_node->key);
    //如果哈希表当前位置还没有值
    if (HashTable[pos]->next == NULL)
    {
        HashTable[pos]->next = new_node;
    }
    //若根据哈希函数计算得到的位置相同,并且已经有节点,添加在该节点之后
    else
    {
        node = HashTable[pos]->next;
        while(node->next != NULL)
        {
            node = node->next;
        }
        node->next = new_node;
    }
}

//查找节点:root=1,说明是根节点
HashNodePtr SearchHashNode(int key, int *root)
{
    HashNodePtr node;
    int pos = 0;
    pos = GetHashPosition(key);
    node = HashTable[pos]->next;
    //空,说明该位置没有节点,没有关键字为key的节点
    if (node == NULL)
    {
        return 0;
    }
    //key是根节点
    if (node->key == key)
    {
        *root = 1;
        return node;
    }
    //key不是根节点
    else
    {
        *root = 0;
        while(node->next != NULL)
        {
            if (node->key == key)
            {
                return node;
            } 
            else
            {
                node = node->next;
            }
        }
        return 0;
    }
}


//删除节点
void DeleteHashNode(int key)
{
    int pos = GetHashPosition(key);
    HashNodePtr node, node_former;
    node = HashTable[pos]->next;
    //空,说明该位置没有节点,没有关键字为key的节点
    if(node == NULL)
    {
        cout<<"Current node does not exist!"<<endl;
    }
    else
    {
        //key是根节点
        if (node->key == key)
        {
            HashTable[pos]->next = node ->next;
            free(node);
        }
        else
        {        
            //key不是根节点,遍历该支链,保存该节点、该节点前面的节点
            while(node != NULL && node->key != key)
            {
                node_former = node;
                node = node->next;
            }
            if(node->key == key)
            {
                node_former->next = node->next;
                free(node);
            }
        }
    }
    

}

int GetNodeNumberOfHashTable(void)
{
    HashNodePtr node;
    int num = 0;
    for(int i=0; i<HASH_TABLE_LEN; ++i)
    {
        node = HashTable[i]->next;
        while(node != NULL)
        {
            num++;
            node = node->next;
        }
    }
    return num;
}

void PrintHashTable(void)
{
    cout<<"Current Hash Table:"<<endl;
    HashNodePtr node;
    int num = GetNodeNumberOfHashTable();
    for (int i=0; i<HASH_TABLE_LEN; ++i)
    {
        node = HashTable[i]->next;
        if (node == NULL)
        {
            continue;
        }
        else
        {
            while(node != NULL)
            {
                cout<<node->key<<' '<<node->data<<endl;
                node = node->next;
            }
        }
    }
}

void main()
{
    HashNodePtr node;
    InitHashTable();
    
    node = InitHashNode();
    node->key = 1;
    node->data = 11;
    AddHashNode(node);

    node = InitHashNode();
    node->key = 2;
    node->data = 22;
    AddHashNode(node);

    node = InitHashNode();
    node->key = 3;
    node->data = 33;
    AddHashNode(node);

    node = InitHashNode();
    node->key = 4;
    node->data = 44;
    AddHashNode(node);

    node = InitHashNode();
    node->key = 104;
    node->data = 144;
    AddHashNode(node);

    node = InitHashNode();
    node->key = 5;
    node->data = 55;
    AddHashNode(node);

    node = InitHashNode();
    node->key = 105;
    node->data = 155;
    AddHashNode(node);

    PrintHashTable();

    int key = 4;
    int root = 0;
    node = SearchHashNode(key, &root);
    cout<<node->data<<endl;
    key = 15;
    DeleteHashNode(key);
    PrintHashTable();
}
View Code

参考资料:http://wenku.baidu.com/view/7dc7080bf78a6529647d5339

原文地址:https://www.cnblogs.com/pukaifei/p/5136158.html