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

  • 相关阅读:
    e621. Activating a Keystroke When Any Child Component Has Focus
    e587. Filling Basic Shapes
    e591. Drawing Simple Text
    e595. Drawing an Image
    e586. Drawing Simple Shapes
    e636. Listening to All Key Events Before Delivery to Focused Component
    在 PL/SQL 块的哪部分可以对初始变量赋予新值? (选择1项)
    Oracle数据库中,在SQL语句中连接字符串的方法是哪个?(选择1项)
    你判断下面语句,有什么作用?(单选)
    Oracle数据库表空间与数据文件的关系描述正确的是( )
  • 原文地址:https://www.cnblogs.com/pukaifei/p/5136158.html
Copyright © 2011-2022 走看看