博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据结构期末复习------查找汇总
阅读量:2148 次
发布时间:2019-04-30

本文共 4501 字,大约阅读时间需要 15 分钟。

数据结构复习------查找汇总

值期末考试之际,汇总查找的相关内容

期末了!

零、基础概念

  • 关键字:可以标识一个记录的数据项

    • 主关键字:可以唯一标识一个记录的数据项
    • 次关键字:可以识别若干记录的数据项
  • 查找:

    • 静态查找:查询某个特定的元素,不插入新元素或删除元素
    • 动态查找:查找的过程中,同时插入查找表中不存在的数据元素
  • 查找表:

    • 静态查找表:

      • 顺序表,顺序查找

      • 线性链表,顺序查找

      • 有序的顺序表,折半查找

        ​ 斐波那契查找法,插值查找法

      • 索引顺序表/分块表,分块查找

    • 动态查找表:

      • 二叉排序树,平衡二叉树(AVL树)
      • B树,B+树,键树
    • 哈希(Hash)表

  • 平均查找长度:查找一个记录时比较关键字次数的平均值

一、静态查找表

1、顺序表与顺序查找法

元素类型为记录(结构)------包含关键字和名称

#define maxsize 100typedef struct node{
keytype key; char name[6];}ElemType;typedef struct{
ElemType elem[maxsize+1];//maxsize+1个记录,elem[0]为监视哨 int length;}SSTable;SSTable ST1,ST2;

算法1:不使用监视哨

int sequsearch(SSTable ST,keytype k){
int i=ST.length; //从第n个记录开始查找 while(i>=1&&k!=ST.elem[i].key)i--;//继续扫描 if(i) printf("success\n"); //查找成功! else printf("fail\n"); //查找失败! return i; //返回记录的下标i,没找到就返回0了}

算法2:使用监视哨elem[0]

int sequsearch(SSTable ST,keytype k){
int i=ST.length; //从第n个记录开始查找 ST.elem[0].key=k; //将k填入0位置 while(k!=ST.elem[i].key)i--; //继续扫描 return i; //返回记录的下标i}

分析:

  • 查找成功

    ​ ASL=(n+1)/2

  • 查找失败

    使用监视哨elem[0],为n+1

    不使用监视哨elem[0],为n

    ASL=3(n+1)/4

2、有序的顺序表的查找和折半查找法

折半查找(binary search,对半查找,二分查找)–一种分治的思想

算法1:

int binsearch(SSTable ST,keytype k){
int low,mid,high; low=1; high=ST.length; while(low<=high){
mid=(low+high)/2; if(k

算法2:

int binsearch(SSTable ST,keytype k){
int low,mid,high; low=1;high=ST.length; while(low<=high){
mid=(low+high)/2; if(k

判定树:描述折半查找的二叉树

若n=2k-1,则判定树为满二叉树,其深度为k=log2(n+1)

假定Pi=1/n,比较关键字的次数:

  • 最少 C=1

  • 最多 C=log2(n+1)

  • ASL=(n+1)/nlog2(n+1)-1

3、索引顺序表(分块表)与分块查找法

  • 条件:分块表“按块有序”,索引表“按key有序”

  • n个记录分为b块,每块的记录数s=n/b

  • 查找方法与ASL

  • 顺序查找、折半查找

    ASL(1)=(b+1)/2

  • 在某一块中顺序查找

    ASL(2)=(s+1)/2

  • ASL=(b+1)/2+(s+1)/2=(b+s)/2+1=1/2(n/s+s)+1

  • 最加分块:s=根号n

ASLmin=根号n+1=O(根号n)

二、动态查找表

1、二叉排序树(二叉查找树)

定义:二叉树中的任一结点大于其非空左子树的所有结点,而小于其非空右子树的所有结点,则称这颗二叉树为二叉排序树。

对于一颗二叉排序树进行中序遍历,所得的结点序列一定是递增有序的。

二叉排序树的存储结构
struct node{
struct {
int key; //关键字 }data; struct node *lchild,*rchild; //左右子树的指针}*root,*t;
插入一个元素到二叉排序树的算法

(递归实现插入元素)

struct node *intree(struct node *t,ElemType x){
if(t==NULL){
//如果为空,那么新开一个结点 t=(struct node *)malloc(sizeof(struct node)) t->data=x; //生成并插入结点x t->lchild=t->rchild=NULL; //为叶子结点 } else if(x.key
data.key) t->lchild=intree(t->lchild,x); //插入到左子树 else t->rchild=intree(t->rchild,x); //插入到右子树 return t;}
二叉排序树的查找算法:

(返回值 失败:NULL 成功:非NULL,结点指针)

  • 递归实现:
struct node *search_tr(struct node*t,keytype k){
if(t==NULL) return NULL; //查找失败 else if(k==k->data.key) return t; //查找成功 else if(k
data.key) return search_tr(t->lchild,k);//查左子树 else return search_tr(t->rchild,k); //查右子树}
  • 非递归实现:
struct node *search_tree(struct node*t,keytype k){
while(t!=NULL) if(k==t->data.key) return t; //查找成功 else if(k
data.key) t=t->lchild; //查左子树 else t=t->rchild; //查右子树 return t; //查找失败}
二叉排序树的删除算法

在二叉排序树中删除一个结点时,必须将因删除节点而断开的二叉链表重新连接起来,同时确保二叉排序树的性质不会失去。

  • 删除叶结点
  • 被删及结点缺左子树(或右子树)
  • 被删结点左右子树都存在

分析:

  • 最好情况(满二叉树)

    ASL=(n+1)/nlog2(n+1)-1=O(log2n)

  • 最坏情况(单枝树)

    ASL=(n+1)/2

  • 平均值

    ASL=O(log2n)

2、平衡二叉树(高度平衡二叉树)

结点的平衡因子:结点的左右子树的深度之差。

AVL树:任何结点的平衡因子的绝对值小于等于1的二叉树

AVL树的存储结构:

typedef int DataType;typedef struct node{
DataType data; int balance; struct node *leftChild,*rightChild;}AVLNode;typedef AVLNode * AVLTree;

平衡化旋转

如果在一棵平衡的二叉搜索树中插入一个新结点,造成了不平衡,此时必须调整树的结构,使之平衡化。

平衡化旋转的两类:

  • 单旋转(左旋和右旋)
  • 双旋转(左平衡和右平衡)

静态查找表和动态查找表查找方法的不足:

无法根据关键字的值,估计数据元素可能在的位置

三、哈希表和哈希法

存储数据元素时,利用一个Hash函数根据数据元素的关键字计算出该数据元素的存储位置,查找时,也是根据给定的数据元素的关键字计算出该数据元素可能存储位置,这样一来,存储和查找的效率相当高。

哈希表也称为散列表,其数据元素的存储一般是不连续的,通过Hash函数计算出的地址称为哈希地址或散列地址。

1、相关术语

Hash函数实现的是将一组关键字映像到一个有限的地址区间上,理想的情况是关键字得到不同的地址。

设K1和K2是关键字,若K1不等于K2是H(K1)=H(k2),则称K1和K2为同义词,他们发生了冲突。

要考虑的两个问题:

  • 选择一个好的哈希函数
  • 选择一种解决冲突的方法

2、构造哈希函数的方法

直接地址法:

取关键字过着关键字的某个线性函数值为哈希地址

除留余数法:

设哈希表的表长为m,哈希地址为key除以p所得的余数

p<=m,p为接近m的质数(素数)eg:m=130,p=127

或者不包含小于20的质因子的合数

解决冲突的方法:线性探测再散列(哈希)

平方取中法:

H(k)=取k2的中间某几位数字

eg:K=21 K2=0441 取中间两位,H(K)=44

折叠法:

将关键字分成位数相同的几部分,然后取这几部分的叠加和作为哈希地址

  1. 边界折叠法

    eg: k=056439725 H(k)=650+439+725=1814

  2. 位移折叠法

    k=056439527 056+439+527=1022 H(k)=022

数字分析法:

设哈希表中可能出现的关键字都是事先知道的,则可以取关键字的若干分布均匀的位组成哈希地址

eg:k=9020067 H(k)=206

随机数法:

H(k)=random(key)

random(key)为产生伪随机数的函数

灵活构造哈希函数

eg:H(k)=取k2的中间2位数*40/99

再用线性探测再散列法解决冲突

3、如何解决冲突

开放地址法(开式寻址法)
  • 线性探测再散列
  • 二次探测再散列
链地址法

将关键字为同义词的所有记录存入同一个链表中(表尾插入)。

eg:设H(k)=k的首字母再字母表中序号

建立公共溢出区

将发生冲突的所有记录都存入一个公共溢出区

eg:设H(k)=k的首字母再字母表中的序号

再哈希法

发生冲突时,再使用下一个哈希函数计算哈希地址

哈希表的平均查找长度依赖于哈希表的装填因子

你说的,乐观一点

给生活加点

转载地址:http://sdzwb.baihongyu.com/

你可能感兴趣的文章
VLAN与子网划分区别
查看>>
Cisco Packet Tracer教程
查看>>
02. 交换机的基本配置和管理
查看>>
03. 交换机的Telnet远程登陆配置
查看>>
微信小程序-调用-腾讯视频-解决方案
查看>>
phpStudy安装yaf扩展
查看>>
密码 加密 加盐 常用操作记录
查看>>
TP 分页后,调用指定页。
查看>>
Oracle数据库中的(+)连接
查看>>
java-oracle中几十个实用的PL/SQL
查看>>
PLSQL常用方法汇总
查看>>
几个基本的 Sql Plus 命令 和 例子
查看>>
PLSQL单行函数和组函数详解
查看>>
Oracle PL/SQL语言初级教程之异常处理
查看>>
Oracle PL/SQL语言初级教程之游标
查看>>
Oracle PL/SQL语言初级教程之操作和控制语言
查看>>
Oracle PL/SQL语言初级教程之过程和函数
查看>>
Oracle PL/SQL语言初级教程之表和视图
查看>>
Oracle PL/SQL语言初级教程之完整性约束
查看>>
PL/SQL学习笔记
查看>>