数据结构-散列查找

散列函数:一个把查找表中的关键字映射成该关键字对应的地址的函数,记为Hash(key)=Addr。
散列函数可能会把两个或以上的不同关键字映射到同一地址,称这种情况为”冲突“,这些发生碰撞的不同关键字称为同义词。
一方面,设计好的散列函数应尽量减少这样的冲突;另一方面,由于这样的冲突是不可避免的,所以还要设计好处理冲突的方法。

散列表:是根据关键字而直接进行访问的数据结构。也就是说,散列表建立了关键字和存储地址之间的一种直接映射关系。

以下简单示例通过除留余数法的方式构造散列函数,通过开放地址法的方式处理冲突。

//
// Created by Administrator on 2018/7/12.
//
#include "stdio.h"
#include "stdlib.h"

#define HASHSIZE 10
#define NULLKEY NULL
typedef struct {
    int *elem; //通过指针的方式代替数组
    int size;  //当前容量
} HashTable;

/**
 * 初始化创建hashtable
 * @return
 */
HashTable createHashTable() {
    HashTable hashTable;
    hashTable.size = 0;
    hashTable.elem = (int *) malloc(HASHSIZE * sizeof(int));
    for (int i = 0; i < HASHSIZE; ++i) {
        //初始化数据
        hashTable.elem[i] = NULLKEY;
    }
    return hashTable;
}

/**
 * 通过除留余数法构造hash函数
 * @param key 关键字key
 * @return
 */
int hash(int key) {
    int hash = key % HASHSIZE;
    return hash;
}

/**
 * 向hashtable中插入元素
 * @param hashTable
 * @param key
 * @return
 */
HashTable put(HashTable hashTable, int key) {
    int addr = hash(key);
    while (hashTable.elem[addr] != NULLKEY) {
        //该位置已存在元素,使用简单的开放地址法处理冲突
        addr = (hash(key) + 1) % HASHSIZE;
    }
    hashTable.elem[addr] = key;
    hashTable.size++;
    return hashTable;
}

/**
 * 查找元素在hashtable中的位置
 * @param hashTable
 * @param key
 * @return
 */
int search(HashTable hashTable, int key) {
    int addr = hash(key);
    int elem = hashTable.elem[addr];
    while (elem != key) {
        addr = (addr + 1) % HASHSIZE;
        elem = hashTable.elem[addr];
        if (elem == NULLKEY || addr == hash(key)) {
            //遍历完成 仍然没有找到
            return -1;
        }
    }
    return addr;
}

int main() {
    HashTable hashTable = createHashTable();
    for (int i = 5; i < 15; i++) {
        hashTable = put(hashTable, i);
    }
    int key = 14;
    int addr = search(hashTable, key);
    printf("查找到key=%d的元素,地址=%d", key, addr);
    printf("\nhashtable 当前容量=%d", hashTable.size);
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值