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