线性结构的查找
查找操作: ①查找一个数据是否在查找表中。
②查找一个数据的其他属性。
③对查找表进行插入与删除操作。(动态查找表)
查找算法的优劣: 平均查找长度ASL。
…
顺序查找法:
int search_seq(seq st, elemtype key)
{
st.elem[0]=key; //哨兵,目的可以不用判断是否越界,使代码简洁。
for(int i=n; st.elem[i]!=key; i--); //从后往前找
return i; //返回元素的位置
}
查找成功ASL: n-i+1的求和。ASL= (n+1)/2
查找失败ASL:n
缺点:时间效率较低,改善方法可以通过将使用频率大的关键字放在后面。可以提高效率。
优点:简单,适用于线性存储和链式存储。同时对序列的有序性无要求。
注:
有序表和无序表的顺序查找法;
当被查找元素在表中有且仅有一个。查找成功的比较次数相同
当被查找元素在表中有且仅有两个。查找时间不同,有序表相同元素都在一块,而无序表需遍历全表才能全部找到。
查找失败时,有序表的ASL=(1+2+ …+n+n)/(n+1)=n(n+2)/2(n+1),而无序表ASL为n。
折半查找法:
int binary_search(seqlist st; elemtype key)
{
int low=0;
int high=n-1;
int mid;
while(low<=high)
{
mid=(low+high)/2;
if(st.elem[mid]=key) //找到关键字为key的值
return mid; //返回该位置
else if(st.elem[mid]>key) //从左半序列找
high=mid-1;
else
low=mid+1; //从右半序列找
}
return -1; //未找到
}
查找成功ASL: ASL=1/n(1x1+2x2+…+h*2^h)≈log2(n+1)-1
缺点: 仅适用于有序线性表。
优点:大大减少比较次数。
分块查找:
**定义:**块内可以无序,块间有序。
分为: 索引表——>按顺序排列每块最大值,第一行写每块最大值,第二行写块内第一个关键字的位置
查找表
设索引表长度a,每块查找表长度b。
对索引表和查找表都采用顺序查找。
查找成功ASL: ASL= (s+b+2)/2
对索引表采用折半查找和查找表采用顺序查找。
查找成功ASL: ASL= log2(a+1)+ (b+1)/2
优点:插入删除比较容易,无需大量移动元素
缺点: 需要一个索引表的额外空间,并对索引表排序。
…
题型:①如何构造折半查找判定树。(算法定义)
②计算ASL
折半查找的递归算法
递归算法的四条原则:
①基准情形
总有某些基准情形,无序递归即可解出。
②不断推进
每一次递归都使求解状况朝接近基准情形的方向推进
③设计法则
所有的递归调用都能进行
④合成效益法则
不要在不同的递归过程中做重复性的工作。
int binaryselect(sqlist st,elemtype k,int low,int high)
{
if(low>high)
return -1;
mid=(low+high)/2;
if(key>st.elem[mid])
binaryselect(st,k,mid+1,high);
else if(key<st.elem[mid])
binaryselect(st,k,low,mid-1);
else
return mid;
}
线性表中各结点的检索概率不等, 则可用如下策略提高顺序检索的效率: 若找到指定的结点, 将该结点和其前驱结点(若存在)交换,使得经常被检索的结点尽量位于表的前端。 试设计在顺序结构和链式结构的线性表上实现上述策咯的顺序检索算法
void sqselect(sqlist st, elemtype k,int n)
{
for(int i=n;st.elem[i]!=k&&i>=1;i--);
if(st.elem[0]==k)
return 0;
else if(i<=0)
return -1;
else
{
swap(st.elem[i],st.elem[i-1]);
return i-1;
}
}