数据结构--散列表 Hash Table

文章目录

    • 1.线性探测 哈希表代码
    • 2.拉链法 哈希表代码

  • 1. 散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。
    在这里插入图片描述
  • 2. 散列函数,设计的基本要求
  1. 散列函数计算得到的散列值是一个非负整数( 因为数组下标从0开始)
  2. 如果 key1 = key2,那 hash(key1)== hash(key2)
  3. 如果 key1 != key2,那 hash(key1)!= hash(key2)

第3条是很难完全满足的,不满足称之,散列冲突

  • 3. 散列冲突 解决方法:
  1. 开放寻址法
    a.线性探测
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    线性探测法,当空闲位置越来越少时,几乎要遍历整个散列表,接近O(n)复杂度
    b. 二次探测:每次的步长是 1, 2, 4, 8, 16,…
    c. 双重散列:使用多个散列函数,先用第一个,如果位置被占,再用第二个散列函数。。。直到找到空闲位置
    不管哪种方法,空闲位置不多了,冲突概率会大大提高,尽量保证有一定比例的空闲(用装载因子表示,因子越大,空位越少,冲突越多,散列表性能下降)
  2. 链表法(更常用的解决冲突的办法)
    在这里插入图片描述
  • 4. 如何设计散列函数
    a. 散列函数的设计不能太复杂。过于复杂的散列函数,势必会消耗很多计算时间,也就间接的影响到散列表的性能。
    b. 散列函数生成的值要尽可能随机并且均匀分布,这样才能避免或者最小化散列冲突,即便出现冲突,散列到每个槽里的数据也会比较平均,不会出现某个槽内数据特别多的情况。
    c. 装载因子超过阈值,自动扩容,避免累积到最后一次性搬移数据,分批多次搬移,O(1)复杂度
    d. 数据量比较小,装载因子小的时候,适合采用开放寻址法
    e. 基于链表的散列冲突处理方法比较适合存储大对象、大数据量的散列表,而且,比起开放寻址法,它更加灵活,支持更多的优化策略,比如用红黑树代替链表。
    在这里插入图片描述

1.线性探测 哈希表代码

hashtable1.h

/*** @description: 哈希表,开放寻址--线性探测法* @author: michael ming* @date: 2019/5/6 10:26* @modified by: */
#ifndef SEARCH_HASHTABLE1_H
#define SEARCH_HASHTABLE1_H
#include <iostream>
enum KindOfItem {Empty, Active, Deleted};
template <class DataType>
struct HashItem
{DataType data;KindOfItem info;HashItem<DataType>(KindOfItem i = Empty):info(i){}HashItem<DataType>(const DataType &d, KindOfItem i = Empty):data(d), info(i){}int operator== (HashItem<DataType> &a){return data == a.data;}int operator!= (HashItem<DataType> &a){return data != a.data;}
};
template <class DataType>
class hashtable1
{
private:HashItem<DataType> *ht; //散列表数组int TableSize;  //散列表长度int currentSize;    //当前表项个数int deletedSize;    //删除标记的元素个数
public:hashtable1<DataType>(int m){TableSize = m;ht = new HashItem<DataType> [TableSize];currentSize = 0;deletedSize = 0;}~hashtable1<DataType>(){delete [] ht;}int hash(const DataType &newData) const{return newData%TableSize;   //留余数法}int find(const DataType &x) const;int find_de(const DataType &x) const;   //当有deleted标记的元素时,插入函数调用此查找int insert(const DataType &x);int delete_elem(const DataType &x);void print() const{for(int i = 0; i < TableSize; ++i){std::cout << ht[i].data << " " << ht[i].info << "->";}std::cout << std::endl;}int isInTable(const DataType &x){int i = find(x);return i >= 0 ? i : -1;}DataType getValue(int i) const{return ht[i].data;}
};
#endif //SEARCH_HASHTABLE1_H

hashtable1.cpp

/*** @description: 哈希表,开放寻址--线性探测法* @author: michael ming* @date: 2019/5/6 10:26* @modified by: */
#include "hashtable1.h"
template <class DataType>
int hashtable1<DataType>::find(const DataType &x) const
{int i = hash(x);int j = i;while(ht[j].info == Deleted || (ht[j].info == Active && ht[j].data != x))  //说明存在冲突{j = (j+1)%TableSize;    //用解决冲突的方法继续查找(开放定址法)if(j == i)return -TableSize;  //遍历整个散列表,未找到}if(ht[j].info == Active)return j;   //找到,返回正值elsereturn -j;  //没找到,返回负值
}
template <class DataType>
int hashtable1<DataType>::find_de(const DataType &x) const   //当有deleted标记的元素时,插入函数调用此查找
{int i = hash(x);int j = i;while(ht[j].info == Active)  //说明存在冲突{j = (j+1)%TableSize;    //用解决冲突的方法继续查找(开放定址法)if(j == i)return -TableSize;  //遍历整个散列表,没有空位}return j;   //返回标记为Empty或者Deleted的位置
}
template <class DataType>
int hashtable1<DataType>::insert(const DataType &x)
{int i = find(x);if(i > 0)return 0;   //元素x已存在else if(i != -TableSize && !deletedSize)    //元素x不存在,且散列表未满(且没有deleted标记){ht[-i].data = x;    //元素赋值ht[-i].info = Active;   //占用了,标记一下currentSize++;return 1;}else if(i != -TableSize && deletedSize)    //元素x不存在,且散列表未满(且有deleted标记){int j = find_de(x);if(j >= 0){if(ht[j].info == Deleted)deletedSize--;ht[j].data = x;    //元素赋值ht[j].info = Active;   //占用了,标记一下(删除标记改成占用标记 )currentSize++;return 1;}elsereturn 0;}else return 0;
}
template <class DataType>
int hashtable1<DataType>::delete_elem(const DataType &x)
{int i = find(x);if(i >= 0){ht[i].info = Deleted;   //找到了要删除的,标记删除currentSize--;deletedSize++;return 1;}else return 0;
}

hashtable1_test.cpp 测试程序

/*** @description: * @author: michael ming* @date: 2019/5/6 10:42* @modified by: */
#include "hashtable1.cpp"
#include <iostream>
int main()
{hashtable1<int> ht1(10);ht1.print();for(int i = 15; i < 18; ++i){ht1.insert(i);ht1.print();}for(int i = 25; i < 29; ++i){ht1.insert(i);ht1.print();}for(int i = 27; i < 29; ++i){ht1.delete_elem(i);ht1.print();}for(int i = 100; i < 103; ++i){ht1.insert(i);ht1.print();}for(int i = 200; i < 203; ++i){ht1.insert(i);ht1.print();}if(ht1.isInTable(109) >= 0)std::cout << ht1.getValue(ht1.isInTable(109));return 0;
}

测试结果:(data,标记位)标记 empty = 0,active = 1, deleted = 2
在这里插入图片描述

2.拉链法 哈希表代码

linkedHash.h

/*** @description: 拉链法散列表* @author: michael ming* @date: 2019/5/6 17:56* @modified by: */#ifndef SEARCH_LINKEDHASH_H
#define SEARCH_LINKEDHASH_H
#include <iostream>
template <class DataType>
struct linkedNode   //链表节点
{DataType data;linkedNode *next;linkedNode():next(NULL){}linkedNode(const DataType &d):next(NULL), data(d){}
};
template <class DataType>
class linkedList    //链表
{
public:linkedNode<DataType> *head;linkedList(){head = new linkedNode<DataType>();  //表头哨兵}~linkedList(){delete head;}
};
template <class DataType>
class linkedHash
{
private:linkedList<DataType> *htList; //散列表链表数组int bucket;  //散列表桶个数
public:linkedHash<DataType>(int m):bucket(m){htList = new linkedList<DataType> [bucket] ();}~linkedHash<DataType>(){for(int i = 0; i < bucket; ++i){linkedNode<DataType> *p = htList[i].head->next, *q = p;while(q != NULL){p = q;q = q->next;delete p;}}delete [] htList;}int hash(const DataType &newData) const{return newData%bucket;   //留余数法}linkedNode<DataType>* find(const DataType &x) const{int i = hash(x);linkedNode<DataType> *p = htList[i].head->next, *q = htList[i].head;while(p && p->data != x){q = p;p = p->next;}return q;   //返回找到元素的前一个节点,或者没有找到,返回最后一个元素}linkedNode<DataType>* insert(const DataType &x){int i = hash(x);linkedNode<DataType> *p = htList[i].head, *q = p;while(q != NULL){p = q;q = q->next;}p->next = new linkedNode<DataType>(x);return p->next;}void delete_elem(const DataType &x){linkedNode<DataType> *q = find(x), *p;if(q->next){p = q->next;q->next = q->next->next;delete p;}}void print() const{for(int i = 0; i < bucket; ++i){std::cout << i << "[ ]";linkedNode<DataType> *p = htList[i].head->next;while(p){std::cout << p->data << "->";p = p->next;}std::cout << std::endl;}std::cout << "----------------------" << std::endl;}
};
#endif //SEARCH_LINKEDHASH_H

linkedHash_test.cpp 测试程序

/*** @description: 拉链法散列表 测试* @author: michael ming* @date: 2019/5/6 17:57* @modified by: */
#include "linkedHash.h"
int main()
{linkedHash<int> ht2(10);for(int i = 15; i < 37; ++i){ht2.insert(i);ht2.print();}ht2.delete_elem(15);ht2.print();ht2.delete_elem(18);ht2.print();ht2.delete_elem(28);ht2.print();ht2.insert(88);ht2.print();ht2.delete_elem(100);ht2.print();return 0;
}

测试结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/480326.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文浅尝 | 面向自动分类归纳的端到端强化学习

动机术语层次在许多自然语言处理任务中扮演着重要角色。然而&#xff0c;大部分现有的术语层次是人工构建的&#xff0c;其覆盖范围有限&#xff0c;或者某些领域上不可用。因此&#xff0c;最近的工作集中在自动化的术语层次归纳(automatictaxonomy induction)上。之前的研究工…

最新天猫Java面试题(含总结):线程池+并发编程+分布式设计+中间件

一面&#xff1a; HashMap实现原理&#xff0c;ConcurrentHashMap实现原理 红黑树&#xff0c;为什么允许局部不平衡 TCP&#xff0c;UDP区别&#xff0c;为什么可靠和不可靠 一次HTTP请求的全过程&#xff0c;包括域名解析、定位主机等 TCP三次握手 MySQL事务是什么&…

重磅!吴恩达家的NLP课程发布啦!

关注小夕并星标&#xff0c;解锁自然语言处理搜索、推荐与算法岗求职秘籍文 | 灵魂写手rumor酱美 | 人美心细小谨思密达斯坦福计算机系副教授、人工智能实验室主任、Coursera平台联合创始人、前百度首席科学家、机器学习入门必备网课CS229的主讲人——吴恩达Andrew Ng老师再放大…

情报领域因果推理智能项目概览:以DAPAR为例

美国国防高级研究计划局&#xff08;Defense Advanced Research Projects Agency&#xff09;&#xff0c;简称DARPA&#xff0c;提出了旨在从推进人工智能常识推理能力发展、深化机器学习理论研究和推进国防部复杂问题中应用人工智能、深化美军对人工智能的研究和应用的“的下…

论文浅尝 | 基于模式的时间表达式识别

本文转载自公众号:南大Websoft. 时间表达式识别是自然语言理解中一个重要而基础的任务。在以前的研究工作中&#xff0c;研究人员已经发现时间词的类型信息可以给识别提供明显的帮助。本文中我们以词类型序列作为表达式模式&#xff0c;提出了基于模式的时间表达式识别方法&…

大数据项目(四)————用户画像

原文地址&#xff1a;https://blog.csdn.net/Jorocco/article/details/81428996 1、用户画像概述 用来勾画用户&#xff08;用户背景、特征、性格标签、行为场景等&#xff09;和联系用户需求与产品设计的&#xff0c;旨在通过从海量用户行为数据中炼银挖金&#xff0c;尽可能…

最强阿里面试126题:数据结构+并发编程+Redis+设计模式+微服务

BAT技术面试范围 数据结构与算法&#xff1a;最常见的各种排序&#xff0c;最好能手写 Java高级&#xff1a;JVM内存结构、垃圾回收器、回收算法、GC、并发编程相关&#xff08;多线程、线程池等&#xff09;、NIO/BIO、各种集合类的比较优劣势&#xff08;底层数据结构也要…

AdaX:一个比Adam更优秀,带”长期记忆“的优化器

关注小夕并星标&#xff0c;解锁自然语言处理搜索、推荐与算法岗求职秘籍文 | 苏剑林&#xff08;追一科技&#xff0c;人称苏神&#xff09;美 | 人美心细小谨思密达前言这篇文章简单介绍一个叫做AdaX的优化器&#xff0c;来自《AdaX: Adaptive Gradient Descent with Exponen…

金融情报挖掘:面向公开文本的期货事件聚合与传导因素分析

金融情报挖掘是情报领域的一个重要分支&#xff0c;通过对金融领域信息进行提取和分析&#xff0c;发现关联线索&#xff0c;对传导关联进行建模&#xff0c;能够挖掘出市场变动的规律&#xff0c;最终辅助决策。 例如&#xff0c;国内外资本市场&#xff0c;衍生品市场热点不断…

论文浅尝 | 知识图谱的单样本关系学习

链接&#xff1a;http://cn.arxiv.org/pdf/1808.09040动机如今的知识图谱规模很大但是完成度不高&#xff0c;long-tail关系在知识图谱中很常见&#xff0c;之前致力于完善知识图谱的方法对每个关系都需要大量的训练样本&#xff08;三元组&#xff09;&#xff0c;而新加入的关…

POJ 1200 Crazy Search 查找有多少种不同的子串(hash)

文章目录1.采用map解题2.采用hash查找题目链接&#xff1a; http://poj.org/problem?id1200题目大意&#xff1a;给定子串长度&#xff0c;字符中不同字符数量&#xff0c;以及一个字符串&#xff0c;求不同的子串数量。1.采用map解题 把子串插入map&#xff0c;map自动去重&…

金融行业如何用大数据构建精准用户画像?

原文地址&#xff1a;https://www.jianshu.com/p/6e0a0ca5948e 1. 什么是用户画像&#xff1f;2. 用户画像的四阶段用户画像的焦点工作就是为用户打“标签”&#xff0c;而一个标签通常是人为规定的高度精炼的特征标识&#xff0c;如年龄、性别、地域、用户偏好等&#xff0c;最…

最全BAT前端开发面试80题:算法+html+js+css!含答案大赠送!

最全前端开发面试题目&#xff1a;包含算法网络css面试jsh5面试题目&#xff0c;尾部有最全BAT前端面试经典77题和答案&#xff0c;想要的就快来领走吧~&#xff08;领取方式见文末&#xff09; 一、前端算法面试 1、基本排序的方式 冒泡、快排、桶排、堆排序、归并排序、插入…

超一流 | 从XLNet的多流机制看最新预训练模型的研究进展

关注小夕并星标&#xff0c;解锁自然语言处理搜索、推荐与算法岗求职秘籍文 | 老饕&#xff08;某厂研究员&#xff0c;祖传调参&#xff09;美 | 人美心细小谨思密达导读作为 NLP 近两年来的当红炸子鸡&#xff0c;以 ELMo/BERT 为代表的语言预训练技术相信大家已经很熟悉了。…

论文浅尝 | 神经网络与非神经网络简单知识问答方法的强基线分析

来源&#xff1a;NAACL 2018链接&#xff1a;http://aclweb.org/anthology/N18-2047本文关注任务为面向简单问题的知识库问答&#xff08;仅用KB中的一个事实就能回答问题&#xff09;。作者将任务划分为实体检测&#xff0c;实体链接&#xff0c;关系预测与证据整合&#xff0…

干货 | 搞定用户画像只需5个步骤

【转】http://www.sohu.com/a/115611583_445326有一句话是&#xff0c;千万人撩你&#xff0c;不如一人懂你&#xff0c;这句话在互联网圈可以说成是&#xff0c;真正的了解用户&#xff0c;才能得到用户&#xff0c;所以&#xff0c;用户画像的重要性不言而喻。什么是用户画像…

领域情报搜索实践:真实场景下的问答实施策略与风险分析

知识搜索&#xff0c;对于一个企业而言&#xff0c;目前无论是在对内管理还是对外服务的业务上&#xff0c;都有着大量的需求&#xff0c;并表现出急迫性的特征。 例如&#xff0c;很多企业都积累了大量的企业知识资产&#xff0c;并且规模以每年200%的速度增长&#xff0c;其…

数据结构--二叉树 Binary Tree

文章目录1.概念2.存储方式2.1 链式存储&#xff08;二叉树代码大部分是链式实现的&#xff09;2.2 顺序存储&#xff08;基于数组&#xff09;3.二叉树的遍历3.1 基于链表的二叉树实现代码3.2 基于数组的二叉树实现代码3.3 非递归法 二叉树遍历1.概念 二叉树&#xff0c;每个节…

算法工程师思维导图—数据结构与算法

卖萌屋的妹子们&#xff08;划掉&#xff09;作者团整理的算法工程师思维导图&#xff0c;求职/自我提升/查漏补缺神器。该手册一共分为数据结构与算法、数学基础、统计机器学习和深度学习四个部分。点击这里查看具体使用指南。该手册有两种获取方式&#xff1a;公众号后台回复…

通过预训练提升语言理解

官方地址&#xff1a;https://blog.openai.com/language-unsupervised/文章&#xff1a;https://s3-us-west-2.amazonaws.com/openai-assets/research-covers/language-unsupervised/language_understanding_paper.pdf代码&#xff1a;https://github.com/openai/finetune-tran…