一、查找
1、 关键字 —— 标识一个数据元素
2、 查找
3、平均查找长度(ASL)—— 与“给定值”比较的“关键字”个数的期望
【课堂练习】在顺序查找一维数组A[n]时,其排列有序或无序的ASL:
(1)若查找概率相等,ASL相同
(2)若查找概率不等,ASL1(有序表)小于ASL2(无序表)
二、线性表的查找(静态查找)
(一) 顺序查找 方向:从后往前
1、 一般方法
1 int SqSearch(int r[], int n, int x) // r为顺序表,x为给定值 2 { 3 for(int i=n; i>0; i--) // [1:n] 4 if(r[i]==x) //r[i]和x比较 5 return i; //找到,返回下标 6 return 0; //没找到,返回0 7 }
2、哨兵方法 优化:免去循环检测 i>0
1 int SqSearch2(int r2[], int n, int x) 2 { 3 int i; 4 r2[0]=x; //待查找元素放入r[0],作为监视哨 5 for(i=n;r2[i]!=x;i--); //不需要判断i是否超过范围 6 return i; 7 }
时间复杂度 |
空间复杂度 |
||
最好 |
最坏 |
平均 |
|
1次查找成功 |
n次查找成功 |
ASL=(n+1)/2 |
O(1) |
(二) 折半查找 前提:线性表必须采用顺序存储结构,关键字有序排列
1、 非递归算法
1 int BinarySearch(int s[],int n,int x) 2 { 3 int low=1,high=n; //初始化 4 while(low<=high) 5 { 6 int middle=(low+high)/2; //middle为查找范围的中间值 7 if(x==s[middle]) //x等于查找范围的中间值,算法结束 8 return middle; 9 else if(x>s[middle]) //x大于查找范围的中间元素,则从左半部分查找 10 low=middle+1; 11 else //x小于查找范围的中间元素,则从右半部分查找 12 high=middle-1; 13 } 14 return 0; //表中不存在待查元素 15 }
2、递归算法
1 int recursionBS (int s[],int x,int low,int high) 2 { 3 if(low>high) //递归结束条件 4 return 0; 5 int middle=(low+high)/2; //计算middle值(查找范围的中间值) 6 if(x==s[middle]) //x等于s[middle],查找成功,算法结束 7 return middle; 8 else if(x//x小于s[middle],则从前半部分查找 9 return recursionBS (s,x,low,middle-1); 10 else //x大于s[middle],则从后半部分查找 11 return recursionBS (s,x,middle+1,high); 12 }
- 初始化时,low指向数组的第一个元素,high指向数组的最后一个元素;
- 查找时,如果x==S[middle],则查找成功;如果x>S[middle],则令low=middle+1;否则令high=middle−1;
- 如果找不到x,则有(1)low>high且low=high+1;(2)a[low]>key>a[high]
时间复杂度 |
空间复杂度 |
|
非递归算法 |
递归算法 |
|
O(logn) |
O(1) |
O(logn) |
三、树表的查找(动态查找)
(一)二叉排列树(二叉查找树,BST)
1、特性:左子树<根<右子树
2、分析:高度越小,效率越高
— |
最好 |
最坏 |
平均 |
树的形态 |
形似折半查找判定树 |
单支树 |
— |
时间复杂度 |
O(logn) |
O(n) |
O(logn) |
平均查找长度 |
log2n |
(n+1)/2 |
— |
(二) 平衡二叉树(AVL树)
1、特性:左右子树高度差(平衡因子)绝对值不大于1,且左右子树也为平衡二叉树
2、调整:
(1)对象:最小不平衡子树(从新插入节点向上,找最近不平衡节点,以该节点为根的子树称为最小不平衡子树)
(2)原则:有序+平衡
(3)分类:LL,RR,LR,RL(如果最近不平衡节点到新节点的路径前两个都是左子树L,即为LL型)
四、散列表(哈希表)的查找
1、散列函数:hash(key)=Addr
(1)直接定址法:hash(key)=a*key+b(a,b是常数)
(2)除留余数法:hash(key)=key % p 注:%是取余运算,p为不大于表长的最大素数
2、 冲突处理
(1)开放地址法:hash′(key) = (hash(key) + di) %m
其中,hash(key)为原散列函数,hash′(key)为探测函数,di为增量序列,m为表长
A. 线性探测法:di=c*i (当c=1时有,di=1, …, m−1)
B. 二次探测法:di=12, −12, 22, −22, …, k2, −k2(k≤m/2)
C. 随机探测法:di是一组伪随机数列
(2)链地址法(拉链法)
3、“查找成功的ASL1”与“查找失败的ASL2”辨析
(1)ASL1:所有关键字查找成功的比较次数ci乘以查找概率pi之和(已记录的每个键值找到可存储空间的平均比较次数)
(2)ASL2:所有关键字查找失败的比较次数ci乘以查找概率pi之和(再插入一个新的键值平均需要比较的次数)
notice:ASL1分母是记录的数据元素个数,ASL2分母是模的值
4、装填因子α = 哈希表记录数 / 哈希表长度;ASL取决于α