zoukankan      html  css  js  c++  java
  • 数据结构之哈希表

    一、哈希表概述

    1、散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

    2、散列函数:用于将键映射到特定的桶,理想的散列函数,将键均匀分布在哈希桶中,最大程度地减少散列冲突(哈希碰撞)。散列函数,常用取余法,即将key对base取余,对应的余数为哈希桶的索引;base通常取质数,可以尽量保证key均匀分布在哈希桶中;哈希桶的数量为base。

    3、散列冲突:不同的键通过哈希函数映射到同一个哈希桶中。解决散列冲突,常用拉链法和开放定址法(线性探测法)。拉链法,是指产生hash冲突后在存储数据后面加一个指针,指向后面冲突的数据,如下图:

    二、手动设计哈希集合与哈希映射

    leetcode_705. 设计哈希集合哈希集合:

    struct List {
        int val;
        struct List *next;
    };
    
    void listPush(struct List *head, int key)
    {
        // 头插法
        struct List *temp = (struct List *)malloc(sizeof(struct List));
        temp->val = key;
        temp->next = head->next;
        head->next = temp;
    }
    
    void listDelete(struct List *head, int key)
    {
        struct List *temp = head;
        while (temp->next != NULL) {
            if (temp->next->val == key) {
                struct List *node = temp->next;
                temp->next = node->next;
                free(node);
                return;
            }
            temp = temp->next;
        }
    }
    
    bool listContain(struct List *head, int key)
    {
        struct List *temp = head->next;
        while (temp != NULL) {
            if (temp->val == key) {
                return true;
            }
            temp = temp->next;
        }
        return false;
    }
    
    void listFree(struct List *head)
    {
        struct List *temp = NULL;
        while (head->next != NULL) {
            temp = head->next;
            head->next = temp->next;
            free(temp);
        }
    }
    
    const int base = 769;
    
    int hash(int key) {
        return key % base;
    }
    
    typedef struct {
        struct List *data;
    } MyHashSet;
    
    /** Initialize your data structure here. */
    
    MyHashSet* myHashSetCreate() {
        // 拉链法
        MyHashSet *obj = (MyHashSet*)malloc(sizeof(MyHashSet));
        obj->data = (struct List*)malloc(sizeof(struct List) * base);
        for (int i = 0; i < base; i++) {
            // 头节点不参加判断,赋任意值,不影响
            obj->data[i].val = 0;
            obj->data[i].next = NULL;
        }
        return obj;
    }
    
    void myHashSetAdd(MyHashSet* obj, int key) {
        int h = hash(key);
        if (listContain(&(obj->data[h]), key) != true) {
            listPush(&(obj->data[h]), key);
        }
    }
    
    void myHashSetRemove(MyHashSet* obj, int key) {
        int h = hash(key);
        listDelete(&(obj->data[h]), key);
    }
    
    /** Returns true if this set contains the specified element */
    bool myHashSetContains(MyHashSet* obj, int key) {
        int h = hash(key);
        return listContain(&(obj->data[h]), key);
    }
    
    void myHashSetFree(MyHashSet* obj) {
        for (int i = 0; i < base; i++) {
            listFree(&(obj->data[i]));
        }
        free(obj->data);
    }
    
    /**
     * Your MyHashSet struct will be instantiated and called as such:
     * MyHashSet* obj = myHashSetCreate();
     * myHashSetAdd(obj, key);
     
     * myHashSetRemove(obj, key);
     
     * bool param_3 = myHashSetContains(obj, key);
     
     * myHashSetFree(obj);
    */
    
    

    leetcode_706. 设计哈希映射

    struct List {
        int key;
        int val;
        struct List *next;
    };
    
    void hashMapPut(struct List *head, int key, int val)
    {
        // 头插法
        struct List *temp = head->next;
        while (temp != NULL) {
            if (temp->key == key) {
                return temp->val = val;
            }
            temp = temp->next;
        }
        
        struct List *node = (struct List *)malloc(sizeof(struct List));
        node->key = key;
        node->val = val;
        node->next = head->next;
    
        head->next = node;
    }
    
    int hashMapGet(struct List *head, int key)
    {
        struct List *temp = head->next;
        while (temp != NULL) {
            if (temp->key == key) {
                return temp->val;
            }
            temp = temp->next;
        }
        return -1;
    }
    
    void hashMapRemove(struct List *head, int key)
    {
        struct List *temp = NULL;
        while (head->next != NULL) {
            if (head->next->key == key) {
                temp = head->next;
                head->next = temp->next;
                free(temp);
                return;
            }
            head = head->next;
        }
    }
    
    void hashMapFree(struct List *head)
    {
        struct List *temp = NULL;
        while (head->next != NULL) {
            temp = head->next;
            head->next = temp->next;
            free(temp);
        }
    }
    const int base = 769;
    int hash(int key)
    {
        return key % 769;
    }
    
    
    typedef struct {
        struct List *data;
    } MyHashMap;
    
    /** Initialize your data structure here. */
    
    MyHashMap* myHashMapCreate() {
        MyHashMap *obj = (MyHashMap*)malloc(sizeof(MyHashMap));
        obj->data = (struct List*)malloc(base * sizeof(struct List));
        for (int i = 0; i < base; i++) {
            obj->data[i].key = 0;
            obj->data[i].val = 0;
            obj->data[i].next = NULL;
        }
        return obj;
    }
    
    /** value will always be non-negative. */
    void myHashMapPut(MyHashMap* obj, int key, int value) {
        int h = hash(key);
        hashMapPut(&(obj->data[h]), key, value);
    }
    
    /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
    int myHashMapGet(MyHashMap* obj, int key) {
        int h = hash(key);
        return hashMapGet(&(obj->data[h]), key);
    }
    
    /** Removes the mapping of the specified value key if this map contains a mapping for the key */
    void myHashMapRemove(MyHashMap* obj, int key) {
        int h = hash(key);
        hashMapRemove(&(obj->data[h]), key);
    }
    
    void myHashMapFree(MyHashMap* obj) {
        for (int i = 0; i < base; i++) {
            hashMapFree(&(obj->data[i]));
        }
        free(obj->data);
    }
    
    /**
     * Your MyHashMap struct will be instantiated and called as such:
     * MyHashMap* obj = myHashMapCreate();
     * myHashMapPut(obj, key, value);
     
     * int param_2 = myHashMapGet(obj, key);
     
     * myHashMapRemove(obj, key);
     
     * myHashMapFree(obj);
    */
    

    三、ustash使用

    1、概述
    (1)ustash是C语言中哈希函数集合,本质上是一组宏定义;使用时需要包含头文件uthash.h;

    (2)常用结构体:

    typedef struct {
        int id;
    	int val;
        UT_hash_handle hh;    // 必须定义
    } HASH_TABLE;
    
    

    (3)常用宏定义:
    参考: https://blog.csdn.net/fan_h_l/article/details/107241520

    增加元素:HASH_ADD_INT

    查找元素:HASH_FIND_INT

    删除元素:HASH_DEL

    遍历元素:HASH_ITER

    统计元素:HASH_COUNT

    2、leetcode_349. 两个数组的交集

    /**
     * Note: The returned array must be malloced, assume caller calls free().
     */
    typedef struct {
        int id;
        UT_hash_handle hh;
    } HASH_TABLE;
    
    int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize)
    {
        int i;
        int count = 0;
        // 指针必须初始化
        HASH_TABLE *table1 = NULL;
        HASH_TABLE *table2 = NULL;
        HASH_TABLE *temp= NULL;
        *returnSize = 0;
    
        for(i = 0; i < nums1Size; i++) {
            HASH_FIND_INT(table1, &(nums1[i]), temp);
            if (temp != NULL) {
                continue;
            }
            temp = (HASH_TABLE*)malloc(sizeof(HASH_TABLE));
            temp->id = nums1[i];
            HASH_ADD_INT(table1, id, temp);
        }
    
        for(i = 0; i < nums2Size; i++) {
            HASH_FIND_INT(table2, &(nums2[i]), temp);
            if (temp != NULL) {
                continue;
            }
            HASH_FIND_INT(table1, &(nums2[i]), temp);
            if (temp == NULL) {
                continue;
            }
    
            temp = (HASH_TABLE*)malloc(sizeof(HASH_TABLE));
            temp->id = nums2[i];
            HASH_ADD_INT(table2, id, temp);
            count++;     
        }
    
        int *ret = (int*)malloc(count * sizeof(int));
        for (temp = table2, i = 0; temp != NULL; temp = (HASH_TABLE*)temp->hh.next) {
            ret[i++] = temp->id;
        }
        
        *returnSize = count;
        return ret;
    }
    
    
  • 相关阅读:
    numpy 基础 —— np.linalg
    图像旋转后显示不完全
    opencv ---getRotationMatrix2D函数
    PS1--cannot be loaded because the execution of scripts is disabled on this system
    打开jnlp Faild to validate certificate, the application will not be executed.
    BATCH(BAT批处理命令语法)
    oracle vm virtualbox 如何让虚拟机可以上网
    merge 实现
    Windows batch,echo到文件不成功,只打印出ECHO is on.
    python2.7.6 , setuptools pip install, 报错:UnicodeDecodeError:'ascii' codec can't decode byte
  • 原文地址:https://www.cnblogs.com/HZL2017/p/15046998.html
Copyright © 2011-2022 走看看