数据结构-查找

线性表的查找

顺序查找

定义被查找的顺序表类型定义如下:

#define MAXL <>
typedef struct
{	KeyType key;//KeyType为关键字的数据类型
	InfoType data;
}NodeType;
typedef NodeType SeqList[MAXL];
//静态查找表
int SeqSearch(SeqList R,int n,KeyType k)
{	int i=0;
	while(i<n&&R[i].key!=k)
		i++;
	if(i>=n) return 0;
	else return i+1;
}

平均查找长度ASL=1/n *n(n+1)/2=(n+1)/2
不成功时ASL=n
时间复杂度O(n)

折半查找

要求线性表中记录必须已按关键字值有序排列
算法如下:

int BinSearch(SqList R,int n,KeyType k)
{	int low=0,high=n-1,mid;
	while(low<=high)
	{	mid=(low+high)/2;
		if(R[mid].key==k)
			return mid+1;
		if(k<R[mid].key)
			high=mid-1;
		else
			low=mid+1;
	}
	return 0;
}

二分查找过程可用二叉树描述:
把当前查找区间的中间位置上的记录作为根
左子表和右子表中的记录分别作为根的左子树和右子树
这样的二叉树称为判定树或比较树。

索引存储结构和分块查找

索引存储结构

索引存储结构=数据表+索引表
索引表中每一项称为索引项,一般形式:
(关键字,地址)

分块查找

查找方法:
1、索引表(有序):可以顺序查找块,也可二分查找块
2、数据块(无序):只能顺序查找块中元素

二叉排序树

树表:以二叉树或树作为表的组织形式,称为树表,动态查找表。

二叉排序树概念

简称BST,又称二叉查找(搜索)树。满足性质:
若它的左子树非空,则左子树上所有节点值均小于根节点值
若它的右子树非空,则右子树上所有节点值均小于根节点值
注意:二叉排序树中没有相同关键字的节点

二叉排序树算法设计

二叉排序树节点类型:

typedef struct node
{	KeyType key;//关键字项
	InfoType data;
	struct node *lchild,*rchild;
}BSTNode;

递归查找算法如下:

BSTNode *SearchBST(BSTNode *bt,KeyType k)
{	if(bt==NULL||bt->key==k)
		return bt;
	if(k<bt->key)
		return SearchBST(bt->lchild,k);
	else return SearchBST(bt->rchild,k);
}

插入过程:

int InsertBST(BSTNode *&p,KeyType k)
{	if(p==NULL)//原树为空,新插入的记录为根节点
	{	p=(BSTNode *)malloc(sizeof(BSTNode));
		p->key=k;p->lchild=p->rchild=NULL;
		return 1;
	}
	else if(l==p->key)//存在相同关键字节点
		return 0;
	else if(k<p->key)
		return InsertBST(p->lchild,k);
	else return InsertBST(p->rchild,k);
}

建立二叉排序树:

BSTNode *CreateBST(KeyType A[],int n)//返回树根指针
{	BSTNode *bt=NULL;
	int i=0;
	while(i<n)
	{	InsertBST(bt,A[i]);
		i++;
	}
	return bt;//返回建立的二叉排序树的根指针
}

节点删除:
1、被删除的节点是叶子节点:直接删去该节点
2、被删除的节点只有左子树或只有右子树,用其左子树或右子树替换它
3、被删除的节点既有左子树,也有右子树:
以其中序前驱值替换之,然后再删除该前趋节点。前趋是左子树中最大节点。
也可以用后继替换之,然后再删除该后继节点,后继是右子树中最小节点。

查找被删节点

int deletek(BSTNode *&bt,KeyType k)
{	if(bt!=NULL)
	{	if(k==bt->key)
	{	deletep(bt);
		return 1;
	}
	else if(k<bt->key)
		deletek(bt->lchild,k);
		else deletek(bt->rchild,k);
	}
	else return 0;
}

void deletep(BSTNode *&p)
{	BSTNode *q;
	q=p;
	p=p->rchild;
	free(q);
}

在二叉排序树bt中删除节点算法:

int DeleteBST(BSTNode *&bt,KeyType k)
{	if(bt==NULL) return 0;
	else
	{	if(k<bt->key) return DeleteBST(bt->lchild,k);
		else if(k>bt->key) return DeleteBST(bt->rchild,k);
		else{
		Delete(bt);
		return 1;
		}
	}
} 

void Delete(BSTNode *&p)
{	BSTNode *q;
	if(p->rchild==NULL)//*p节点没有右子树的情况
	{	q=p;p=p->lchild;
		free(q);
	}
	else if(p->lchild==NULL)//*p节点没有左子树的情况
	{	q=p;p=p->rchild;
		free(q);
	}
	else Delete1(p,p->lchild);//*p节点既没有左子树又没有右子树的情况
}
void Delete1(BSTNode *p,BSTNode *&r)//p指向待删除的节点,r指向其左孩子节点
//当被删节点有左右子树时
{	BSTNode *q;
	if(r->rchild!=NULL)
		Delete1(p,r->rchild);
	else{
	p->key=r->key;p->data=r->data;
	q=r;r=r->rchild;
	free(q);
	}
}

平衡二叉树

若一棵二叉树中每个节点的左、右子树的高度至多相差1,则称此二叉树为平衡二叉树(AVL)
平衡因子:该节点左子树高度减去右子树高度

平衡二叉树插入调整

1、LL型调整

2、RR型调整

3、LR型调整

4、RL型调整

平衡二叉树的查找

含有n个节点的平衡二叉树的平均查找长度为O(log2n)

B-树和B+树

B-树

又称多路平衡查找树,是一种组织和维护外存文件系统非常有效的数据结构。
一棵m阶B-树或者是一棵空树,或者是满足要求的m叉树:
树中每个节点至多有m-1个关键字。
除根节点外,其他非叶子节子点至少有m/2]个孩子节点,最少关键字个数Min=[m/2]-1
外部节点就是失败节点,指向它的指针为空、一棵B-树中总有n个关键字,则外部节点个数为n+1

B-树节点类型定义:

#define MAXM 10//定义B-树的最大阶数
typedef int KEyType;//KeyType为关键字类型
typedef struct node
{	int keynum;//节点当前拥有的关键字个数
	KeyType key[MAXM];//存放关键字
	struct node *parent;//双亲节点指针
	struct node *ptr[MAXM];//孩子节点指针数组
}BTNode;

B-树的查找:
将k与根节点中的key[i]比较:
若k=key[i],则查找成功

若k<key[1],则沿着指针ptr[0]所指的子树继续查找

若key[i]<k<key[i+1],则沿着指针ptr[i]所指子树继续查找

若k>key[n],则沿着指针ptr[n]所指子树继续查找

当查找到某个叶节点,若相应指针为空,落入一个外部节点,表示查找失败

B-树的插入:
1、查找该关键字的插入节点(B-树的插入节点一定是叶子节点层的节点)

2、插入关键字

在某个叶子节点中插入关键字分两种情况:
1、插入节点有空位置,即关键字个数n<m-1:直接把关键字k有序插
入到该节点的合适位置上

2、插入节点没有空位置,即原关键字个数n=m-1=》分裂:

如果没有双亲节点,新建一个双亲节点,树的高度增加一层

如果有双亲节点,将ki插入到双亲节点中

3、删除关键字

分为两种情况:

1、在叶子节点层上删除关键字k

2、在非叶子节点层上删除关键字k

在B-树的叶子节点b上删除关键字共有以下3种情况:
1、假如b节点的关键字个数大于Min,直接删
2、等于Min,说明删除关键字后该节点将不满足B-树定义,可以从兄弟节点借,如果借不了就要合并

B+树

有n棵子树恰好有n个关键字
所有叶子节点包含全部关键字及指向相应记录的指针,叶子节点按关键字大小顺序连接,并将所有叶子节点链接起来

哈希表的查找

哈希冲突:对于两个关键字分别为ki和kj的记录,有ki≠kj,但h(ki)=h(kj),这种现象叫做哈希冲突。

哈希表设计:
哈希冲突主要与3个因素有关:
1、与装填因子有关。装填因子=存储的记录个数/哈希表的大小=n/m
装填因子越小,冲突可能性越小
2、与所采用的的哈希函数有关
3、与解决冲突方法有关

哈希函数构造方法

1、直接定址法
以关键字k本身或关键字加上某个数值常量c作为哈希地址。
h(k)=k+c
2、除留余数法
h(k)=k mod p p最好是质数
3、数字分析法
取关键字最后两位作为哈希地址

解决冲突办法:
1、线性探查法

2、拉链法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值