数据结构复习之散列查找

2023-10-17 14:10

本文主要是介绍数据结构复习之散列查找,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

散列表查找

  • 散列表概念
    • 如何构造散列函数
    • 处理冲突的方法
      • 开放定址法
        • 线性探查法 必考
          • 扩展
        • 二次探查法
        • 双重散列法
      • 拉链法(链地址法)
        • 例子
  • 散列表查找
    • 开放定址法数据结构
      • 线性探查法查找算法
      • 插入算法
    • 拉链法数据结构定义
      • 查找算法
      • 插入算法
  • 处理冲突平均查找长度方法比较

数据结构,最后一部分内容

散列表概念

基本思想是通过由散列函数决定的键值与散列地址之间的对应关系来实现存储组织和查找运算。既是一种存储方式,又是一种查找方法。
散列技术时需要考虑的两个主要问题是:①如何构造(选择)"均匀的"散列函数?②用什么方法解决冲突?

如何构造散列函数

  1. 直接地址法
    直接地址法是以关键字key本身或关键字加上某个常量C作为散列地址的方法。对 应的散列函数H(key)为:H(key)=key+C
    特点:方法计算简单,并且没有冲突。它适合于关键字的分布基本连续的情况,若关键字分布不连续,空号较多,将会造成较大的空间浪费。
  2. 数字分析法
    数字分析法是假设有一组关键字,每个关键字由n位数字组成,数字分析法是从中提取数字分布比较均匀的若干位作为散列地址。
  3. 除余数法
    除余数法是一种最简单也最常用的一种散列函数构造方法。散列函数:H(k)=k%p
    其中,p最好选取小于或等于表长m的最大素数1
  4. 平方取中法
    取关键字平方的中间几位作为散列地址的方法
  5. 折叠法
    折叠法是首先把关键字分割成位数相同的几段(最后一段的位数可少一些),段的位数取决于散列地址的位数,由实际情况而定,然后将它们的叠加和(舍去最高进位)作为散列地址的方法。
    关键字k=98 123 658,散列地址为3位,则将关键字从左到右每三位一段进行划分,得到的三个段为981、236和58,叠加后值为1275,取低3位275作为关键字98 123 658的元素的散列地址

处理冲突的方法

开放定址法

开放定址法的思想:使用某种方法在散列表中形成一个探查序列,沿着此序列逐个单元进行查找,直到找到一个空闲的单元时将新结点存入其中。开放定址法又分为线性探插法、二次探查法和双重散列法。

线性探查法 必考

探查序列可以由下述公式得到:di=(d+i) % m
其中:di表示第i次探查的地址,m表示散列表的长度。d由散列函数计算出的地址。
如题:2021年4月
在这里插入图片描述

解:根据散列函数计算,散列地址
h(15)=1;h(72)=2;h(52)=3;h(65)=2;h(23)=2;h(68)=5,先填上没有重复的值

下标0123456
散列表157252656823
探查次数111315

查找成功时的平均查找长度ASL=(1*4+3*1+5*1)/ 6=2

扩展

查找不成功平均查找长度:计算不成功的查找次数,要查找的数字肯定不在散列表中,根据哈希函数地址为MOD7,因此任何一个数经散列函数计算以后的初始地址只可能在0~6的位置。
计算查找不成功的次数就直接找该关键字到第一个地址上关键字为空的距离即可。上题中,1到0需要探查7次,2到0探查6次…所以查找不成功的次数就是:(7+6+5+4+3+2+1)/ 7

注意:查找成功时,分母为哈希表元素个数,查找不成功时,分母为哈希表长度。
相关软考总结:软考考点之散列表(哈希)等概率平均查找长度

二次探查法

二次探查法的探查序列为:加减 平方形式
d0=H(K),
d1=(d0+1^2)% m
d2=(d0 -1^2)% m,
d3=(d0+2^2)% m,
d4=(d0 -2^2)% m,
……

双重散列法

思想:与线性探查法一样,唯一的不同是它不是检查冲突位置后的每一个位置,而是采用另一个散列函数产生一个固定的增量。(跳跃式检查和插入,减小聚焦大小)

双重散列法是几种方法中最好的方法,它的探查序列为:hi=(H(key)+i*H1(key))%m (0≤i≤m-1)
即探查序列为:d=H(key),(d+i*H1(key))%m,(d+2*H1(key))%m,…等。

拉链法(链地址法)

把具有相同散列地址的关键字(同义词)值放在同一个单链表中,称为同义词链表。

例子

设散列函数为h(key)=key%1l;,对关键字序列{27,13,55,32,18,49,24,38,43),用拉链法构造散列表,并计算查找成功时的平均查找长度。

在这里插入图片描述

散列表查找

开放定址法数据结构

# define M 997 //M定义为表长,一般M为一个素数
typedef struct { //定义散列表结点类型KeyType key;DataType data;
} NodeType;
typedef NodeType HashTable[M]; //散列表类型

线性探查法查找算法

int HashSearchl(HashTable HT, KeyType K, int m)
{//在长度为m的散列表HT中查找关键字值为K的元素位置int d, temp;d = K % m; //计算散列地址temp = d; //temp作为哨卡,防止进入重复循环while (HT[d].key != -32768) { //当散列地址中的key域不为空,则循环if (HT[d].key == K)return d; //查找成功返回其下标delsed = (d + 1) % m; //计算下一个地址if (d == temp)return -1; //查找一周仍无空位置,返回-1表示失败}return d; //遇到空单元,查找失败
}

插入算法

int HashInsertl(HashTable HT, NodeType s, int m)
{//在HT表上插入一个新结点sint d;d = HashSearchl(HT, s.key, m); //查找插入位置if (d == -1) return -1; //表满,不能插入else {if (HT[d].key == s.key)return 0; //表中已有该结点!else { //找到一个开放的地址HT[d] = s; //插入新结点Sreturn 1; //插入成功}}}

拉链法数据结构定义

typedef struct node { //定义结点类型KeyType key;DataType data;struct node *next;
} HTNode;typedef HTNode *HT[M];  //定义散列表类型

查找算法

HTNode *HashSearch2(HT T, KeyType K, int m)
{//在长度为m的散列表T中查找关键字值为K的元素位置HTNode *p = T[K%m]; //取K所在链表的头指针while (p != NULL && p->key != K)p = p->next; //顺链查找return p; //查找成功p指向K结点的位置,不成功返回NULL
}

插入算法

int HashInsert2(HT T, HTNode *s, int m)
{//采用头插法在T表上插入一个新结点int d;HTNode *p = HashSearch2(T, s->key, m); //查找表中有无待插结点if (P != NULL) return 0; //说明表中已有该结点else { //将*s插入在相应链表的表头上d = s->key % m;s->next = T[d];T[d] = s;return 1; //说明插入成功}
}

处理冲突平均查找长度方法比较

结点个数n,散列表长度为m,散列表的平均查找长度不是n的函数,而是装填因子a=n/m的函数,采用四种不同方法处理冲突时得出的散列表的平均查找长度:
在这里插入图片描述


  1. 素数又称质数。所谓素数是指除了 1 和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被 2~16 的任一整数整除。比1大但不是素数的数称为合数。1和0既非素数也非合数。 ↩︎

这篇关于数据结构复习之散列查找的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/225905

相关文章

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

Verybot之OpenCV应用二:霍夫变换查找圆

其实我是想通过这个程序来测试一下,OpenCV在Verybot上跑得怎么样,霍夫变换的原理就不多说了,下面是程序: #include "cv.h"#include "highgui.h"#include "stdio.h"int main(int argc, char** argv){cvNamedWindow("vedio",0);CvCapture* capture;i

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

浙大数据结构:树的定义与操作

四种遍历 #include<iostream>#include<queue>using namespace std;typedef struct treenode *BinTree;typedef BinTree position;typedef int ElementType;struct treenode{ElementType data;BinTree left;BinTre

Python 内置的一些数据结构

文章目录 1. 列表 (List)2. 元组 (Tuple)3. 字典 (Dictionary)4. 集合 (Set)5. 字符串 (String) Python 提供了几种内置的数据结构来存储和操作数据,每种都有其独特的特点和用途。下面是一些常用的数据结构及其简要说明: 1. 列表 (List) 列表是一种可变的有序集合,可以存放任意类型的数据。列表中的元素可以通过索

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

【数据结构入门】排序算法之交换排序与归并排序

前言         在前一篇博客,我们学习了排序算法中的插入排序和选择排序,接下来我们将继续探索交换排序与归并排序,这两个排序都是重头戏,让我们接着往下看。  一、交换排序 1.1 冒泡排序 冒泡排序是一种简单的排序算法。 1.1.1 基本思想 它的基本思想是通过相邻元素的比较和交换,让较大的元素逐渐向右移动,从而将最大的元素移动到最右边。 动画演示: 1.1.2 具体步