csdn_spider/blog/ds19991999/原创-- 第九章 查找.md

223 lines
5.2 KiB
Markdown
Raw Permalink Normal View History

2021-02-27 15:01:45 +00:00
# 原创
第九章 查找
# 第九章 查找
2024-07-03 09:49:47 +00:00
## 一、基础知识点
2021-02-27 15:01:45 +00:00
2024-07-03 09:49:47 +00:00
### 1.基本概念
2021-02-27 15:01:45 +00:00
>
2024-07-03 09:49:47 +00:00
### 2.顺序查找法
2021-02-27 15:01:45 +00:00
>
思路从表的一端开始顺序扫描线性表依次扫描到的关键字和给定值k比较
```
//数组a[]有n个元素没有次序数组从下标1开始存储写出查找元素k的算法
int Search(int a[],int n,int k)
{
int i;
for(i=1;i<=n;++i)
{
if(a[i]==k)return i;
}
return 0;
}
//查找成功----ASL分析ASL=(1/n)*n*(1+n)/2=(n+1)/2,时间复杂度O(n);
//查找失败----ASL分析ASL=n,时间复杂度O(n);
```
2024-07-03 09:49:47 +00:00
### 3.折半查找法
2021-02-27 15:01:45 +00:00
>
**思路:** <br/> 1.要求线性表**有序**设R[low, … ,high]是当前查找区间mid = ( low / high ) / 2 <br/> 2.将待查找k与R[mid]进行比较相等则查找成功返回mid失败则确定新查找区间 <br/> 3.R[mid] &gt; k则high = mid - 1若R[mid]
```
//数组从下标1开始存储
int HalfSearch(int R[],int low,int high,int k)
{
int mid;
while(low&lt;=high)
{
mid=(low+high)/2;
if(R[mid]==k)return mid;
else if(R[mid]&gt;k)high=mid-1;
else low=mid+1;
}
return 0;
}
```
>
2024-07-03 09:49:47 +00:00
### 4.分块查找
2021-02-27 15:01:45 +00:00
>
```
//索引表定义
typedef struct
{
int key;
int low,high; //记录块内第一个和最后一个元素位置
}indexElem;
indexElem index[maxSize]; //定义索引表
```
>
**算法描述:** <br/> 首先确定待查找元素的块,采用二分法查找;块内元素较少,直接用顺序查找; <br/> 平均查找长度 = 二分法查找平均长度 + 顺序查找平均查找长度;
2024-07-03 09:49:47 +00:00
## 二、二叉排序树与平衡二叉树
2021-02-27 15:01:45 +00:00
2024-07-03 09:49:47 +00:00
### 1.二叉排序树
2021-02-27 15:01:45 +00:00
>
**基本算法:**
```
//1.查找关键字算法
//与这折半查找的二叉树类比,很简单
BTNode *BSTSearch(BTNode *bt,int key)
{
if(bt==NULL)return NULL;
else
{
if(bt-&gt;key==key)return bt;
else if(bt-&gt;key&gt;key)return BSTSearch(bt-&gt;lchild,key);
else if(bt-&gt;key&lt;key)return BSTSearch(bt-&gt;rchild,key);
}
}
//2.插入关键字的算法
//注意BST是一个查找表对于一个不存在于二叉排序树中的关键字查找不成功的位置即为需要将关键字插入的位置
int BSTInsert(BTNode *&amp;bt,int key)//由于二叉树需要改变,所以用引用,绪论里说过
{
if(bt==NULL)//空指针即为找到关键字插入位置
{
bt=(BTNode*)malloc(sizeof(BTNode));
bt-&gt;lchild=bt-&gt;rchild=NULL;
bt-&gt;key=key;
return 1;
}
else
{
if(key==bt-&gt;key)return 0;//关键字存在二叉树中插入1失败
else if(key&lt;bt-&gt;key)return BSTInsert(bt-&gt;lchild,key);
else if(key&gt;bt-&gt;key)return BSTInsert(bt-&gt;rchild,key);
}
}
//3.二叉排序树的构造算法
//建立一棵空树,直接逐个插入即可
void CreatBST(BTNode *&amp;bt, int key[], int n)
{
int i;
bt=NULL;
for(i=0;i&lt;n;++i)BSTInsert(bt,key[i]);
}
//4.删除关键字操作
/*
1.p结点为叶子结点
2.p结点只有右子树或者只有左子树
3.p结点有左右子树为保证二叉排序树的成立条件输出的中序遍历有序
遍历p左子树的右指针直到到达最右边的结点r或者遍历p右子树的左指针直到到达最左边的结点
p的关键字用r的关键字(相当于删除p),然后处理多出来的r删除方式就按12情况处理。
*/
//具体算法严版书上有P230页
//5.判断一棵二叉树是否为二叉排序树(结点值为int型)
//思路利用二叉排序树BST的中序遍历为递增序列的性质对该二叉树进行中序遍历即可
int predt=INF;//INF为已知常量小于任何树中结点值predt始终记录当前结点的前驱结点的值
int judgeBST(BTNode *bt)
{
int b1,b2;
if(bt==NULL)return1;//空BST
else
{
b1=judgeBST(bt-&gt;lhild);
if(b1==0||predt &gt; bt-&gt;date)return 0;
predt=bt-&gt;date;
b2=judgeBST(bt-&gt;rchild);
return b2;
}
}
```
2024-07-03 09:49:47 +00:00
### 2.平衡二叉树
2021-02-27 15:01:45 +00:00
>
2024-07-03 09:49:47 +00:00
## 三、B-树和B+树
2021-02-27 15:01:45 +00:00
2024-07-03 09:49:47 +00:00
### 1.基本概念
2021-02-27 15:01:45 +00:00
>
<table><thead><th align="center">n</th><th align="center">k1</th><th align="center">k2</th><th align="center"></th><th align="center">kn</th>
</thead><tbody><td align="center">p0</td><td align="center">p1</td><td align="center">p2</td><td align="center"></td><td align="center">pn</td>
</tbody></table>
2024-07-03 09:49:47 +00:00
### 2.基本操作
2021-02-27 15:01:45 +00:00
2024-07-03 09:49:47 +00:00
### 3.B+树
2021-02-27 15:01:45 +00:00
>
2024-07-03 09:49:47 +00:00
## 四、散列表
2021-02-27 15:01:45 +00:00
2024-07-03 09:49:47 +00:00
### 1.基本概念
2021-02-27 15:01:45 +00:00
>
2024-07-03 09:49:47 +00:00
### 2.Hash表建立以及冲突解决
2021-02-27 15:01:45 +00:00
>
2024-07-03 09:49:47 +00:00
### 3.常用Hash函数构造方法
2021-02-27 15:01:45 +00:00
>
2024-07-03 09:49:47 +00:00
### 4.常用的Hash冲突处理方法
2021-02-27 15:01:45 +00:00
>
2024-07-03 09:49:47 +00:00
### 5.散列表的性能分析
2021-02-27 15:01:45 +00:00
>
<table><thead><th align="right">解决冲突的方法</th><th align="center">查找成功时</th><th align="left">查找不成功时</th>
</thead><tbody><td align="right">线性查找法</td><td align="center">`[1+1/(1-a)]/2`</td><td align="left">`[1+1/(1-a)^2]/2`</td>
<td align="right">平方探查法</td><td align="center">`-(1/a)ln(1-a)`</td><td align="left">`1/(1-a)`</td>
<td align="right">链地址法</td><td align="center">`1+a/2`</td><td align="left">`a+e^a≈a`</td>
</tbody></table>
**特别注意链地址法的ASL2求法**