zoukankan      html  css  js  c++  java
  • 【查找算法】基于存储的查找算法(哈希查找)

    哈希查找:又称散列查找

    哈希表:根据关键字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

  • 相关阅读:
    03-spring bean
    04-spring的依赖注入
    01-课程安排
    17-注解开发
    WIN10新机必要设置记录 for 3dsmax
    ps导出svg
    VS C# 共享项目
    在Maxscript中创建.Net类型
    C# 自定义索引
    C# ?
  • 原文地址:https://www.cnblogs.com/pukaifei/p/5136158.html
Copyright © 2011-2022 走看看