# 原创 : 第九章 查找 # 第九章 查找 # 一、基础知识点 ## 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.基本概念 >
nk1k2kn
p0p1p2pn
## 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求法**