哈希表概念和实现,C/C++实现
body, table{font-family: 微软雅黑; font-size: 13.5pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}
散列技术既是一种存储方法,也是一种查找方法。
散列函数设计原则:简单、均匀、存储利用率高
两个关键字 key1 ≠ key2,但是却有 f(key1) ≠ f(key2),这种现象我们称为冲突(collision),并把key1和key2称为这个散列函数的同义词(synonym)。
处理散列冲突的方法
| 链地址法:将所有关键字为同义词的记录存储在一个单链表中,这种链表叫做同义词子表,使用除留余数法,就不存在冲突的问题了,只是在链表中增加一个结点。 |
公共溢出区法:
对所有冲突的关键字建立一个公共溢出区来存放
|
| | |
|
#include<iostream>
#include<stdlib.h>
#define max ~( 1<<(sizeof(int)*8-1) )
using namespace std;
//散列函数采用除留余数法
//冲突解决采用开放定址法的线性探测法
int hashFunc(int key,int length);
int initHashTable(int* hashTable,int length); //成功返回0,失败返回-1
int hashInsert(int* hashTable,int key,int length); //成功返回0,失败返回-1
static enum status{failture=-1,success=0} flag;
int hashSearch(int*hashTable,int key,int length);
void test();
int main()
{
test();
system("pause");
}
int initHashTable(int* hashTable,int length)
{
if(nullptr==hashTable || length<=0)
return -1;
for(int idx=0;idx!=length;++idx)
{
hashTable[idx] = max;
}
return 0;
}
int hashFunc(int key,int length)
{
if(key==max||length<=0)
return -1;
return key % length; //除留余数
}
int hashInsert(int* hashTable,int key,int length)
{
if(nullptr==hashTable||length<=0)
return -1;
int hashAddr = hashFunc(key,length);
if(-1==hashAddr)
return -1;
for(int idx=0;idx!=length;++idx) //循环,最大哈希表长度
{
if(hashTable[hashAddr]!=max) //冲突
hashAddr = (hashAddr+1) % 12; //开放定址法的线性探测法,查找下一个可存放数据的空间
else
break;
}
if(max==hashTable[hashAddr])
{
hashTable[hashAddr] = key;
return 0;
}
return -1;
}
|
void test()
{
int arr[12] = {12,67,56,16,25,37,22,29,15,47,48,34};
int* hashTable = new int[12]();
int ret = initHashTable(hashTable,12);
if(-1==ret)
cout<<"initHashTable fail!"<<endl;
cout<<"哈希表待插入元素:";
for(int idx=0;idx!=12;++idx)
{
cout<<arr[idx]<<" ";
hashInsert(hashTable,arr[idx],12);
}
cout<<endl;
cout<<"哈希表:";
for(int idx=0;idx!=12;++idx)
{
cout<<hashTable[idx]<<" ";
}
cout<<endl;
cout<<"对应插入元素序列在哈希表查找元素:";
for(int idx=0;idx!=12;++idx)
{
int ret = hashSearch(hashTable,arr[idx],12);
if( ret==-1 && flag == failture)
{
cout<<"search "<<arr[idx]<<" fail"<<endl;
}
cout<<hashTable[ret]<<" ";
}
cout<<endl;
cout<<"查找1:"<<endl;
int rett = hashSearch(hashTable,1,12);
if( rett==-1 && flag == failture)
{
cout<<"search "<<1<<" fail"<<endl;
return ;
}
cout<<hashTable[rett]<<endl;
}
int hashSearch(int*hashTable,int key,int length)
{
flag = success;
if(nullptr==hashTable||length<=0)
{
flag = failture;
return -1;
}
int hashAddr = hashFunc(key,length);
while(key!=hashTable[hashAddr])
{
hashAddr = (hashAddr+1) % length;
if(max==hashTable[hashAddr] || hashAddr == hashFunc(key,length)) //如果探测到下一个地址为空,还没有找到,或者循环找了一遍又回到最开始的hashAddr
{
flag = failture;
return -1;
}
}
return hashAddr;
}
|
哈希表概念和实现,C/C++实现的更多相关文章
- 哈希表(hash table)基础概念
哈希是什么 引入:我们在学习数组的时候,使用数组元素的下标值即可访问到该元素,所花费的时间是O(1),与数组元素的个数n没有关系,这就是哈希方法的核心思想. 哈希方法:以关键值K为自变量,通过一定的函 ...
- 什么叫哈希表(Hash Table)
散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构 ...
- Berkeley DB的数据存储结构——哈希表(Hash Table)、B树(BTree)、队列(Queue)、记录号(Recno)
Berkeley DB的数据存储结构 BDB支持四种数据存储结构及相应算法,官方称为访问方法(Access Method),分别是哈希表(Hash Table).B树(BTree).队列(Queue) ...
- 从HashMap透析哈希表
##扯数据结构 先看一下哈希表的概念: 哈希表是一种数据结构,它可以提供快速的插入操作和查找操作.第一次接触哈希表,他会让人难以置信,因为它的插入和删除.查找都接近O(1)的时间级别.用哈希表,很多操 ...
- 哈希表的C++实现(转)
哈希表的几个概念: 映像:由哈希函数得到的哈希表是一个映像. 冲突:如果两个关键字的哈希函数值相等,这种现象称为冲突. 处理冲突的几个方法: 1.开放地址法:用开放地址处理冲突就是当冲突发生时,形成一 ...
- 散列表 (Hash table,也叫哈希表)
散列表是根据关键字(Key value)而直接访问在内存存储位置的数据结构.也就是说,它通过把键值通过一个函数的计算,映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录 ...
- C#中哈希表与List的比较
简单概念 在c#中,List是顺序线性表(非链表),用一组地址连续的存储单元依次存储数据元素的线性结构. 哈希表也叫散列表,是一种通过把关键码值映射到表中一个位置来访问记录的数据结构.c#中的哈希表有 ...
- 哈希,哈希表,哈希Map
数组: 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1):数组的特点是:寻址容易,插入和删除困难: 链表: 链表存储区间离散,占用内存比较宽松,故空间复杂 ...
- perl5 第九章 关联数组/哈希表
第九章 关联数组/哈希表 by flamephoenix 一.数组变量的限制二.定义三.访问关联数组的元素四.增加元素五.创建关联数组六.从数组变量复制到关联数组七.元素的增删八.列出数组的索引和值九 ...
随机推荐
- Virtualbox主机和虚拟机之间文件夹共享及双向拷贝
把文件发到VirtualBox的方法有很多,下面推荐两种: 1.把要共享的文件夹挂载到虚拟机某一个文件上: (1)打开虚拟机的设置,点击左边的“共享文件夹”,点击带加号的文件按钮,在文件夹路径选择要共 ...
- 表结构中updated_time设计为ON UPDATE CURRENT_TIMESTAMP时,使用过程的一个坑
一.mysql表结构中存在如下设计时 表结构中updated_time设计为ON UPDATE CURRENT_TIMESTAMP时,如下 `updated_time` datetime NOT NU ...
- LeetCode--415--字符串相加
问题描述: 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和. 注意: num1 和num2 的长度都小于 5100. num1 和num2 都只包含数字 0-9. num1 和nu ...
- Vue音乐项目笔记(三)
1. 音乐播放前进后退的实现 https://blog.csdn.net/weixin_40814356/article/details/80379606 2. 音乐进度条实现(单独一个组件) h ...
- memcached的部署
window下memcached注册服务 cmd:在学习Memcached时,为了模拟分布存储,常常需要建多个Memcached服务,如何建呢,只能使用命令行了 以管理员身份运行cmd,输入如下命令 ...
- adb 获取包名
1.aapt dump badging 指定的路径 +包名 ======= adb logcat|findstr START 2.顶部和尾部有包名和activity
- Leetcode 692 - Note
1. 题目要求 Given a non-empty list of words, return the k most frequent elements. Your answer should be ...
- Leetcode笔记(整理中.......)
1.树的层序遍历 使用两个List 数组 或者 两个queue队列,交替进行,将遍历到的一层放在第一个里面,之后再将遍历到的第二层放在第二个里面. 2.将一个无符号整数的二进制表示形式逆向输出 需要将 ...
- 【JS】【4】字符串数字比较大小
两个转换函数: parseInt():把值转换成整数 parseFloat():把值转换成浮点数 也有其他方法,详情请看参考博客,但个人认为转换函数是最好的方法 参考文档: 1,js.jquery字符 ...
- subline 自己使用的插件
http://blog.csdn.net/jianhua0902/article/details/43761899 https://www.cnblogs.com/qingkong/p/5039527 ...