第一章至第四章

第一章复习

二分搜索

问题来源

假定元素满足,线序集合;A[1…n]中有x吗?从头到尾的扫描,依次比较:顺序搜索(适合无序的集合)如果存在等于x的,返回其下标;否则返回0;

算法解决:

j = 1;								//设定初始值
while (j <= n) {
   					//while (循环条件){
   
    if(A[j] == x)					//	比较和更新;
    {
   								//}
        return j;					// return 0;
    }								
    j= j + 1;						
}									
return 0;							

最小查找时间? 最好情况,A[1]=X

平均查找时间?P(i)=1/n,T(n)=n/2;

最大查找时间?最坏情况,x不在A[1…n]或者x=A[n],复杂度为n;

二分搜索:

有序(非降序)的集合(Binary Search);

int low = 1, high = n;						//设定初始值
while (low <= high) {
   						//while(循环条件){
   
    mid = [ (low + high) / 2];				//	比较和更新;
    if (A[mid] == x)						//}
    {
   										//return 0;
        return mid;							
    }
    if(A[mid] > x) 
    {
   
        high = mid - 1;
    }
    else {
   
        low = mid + 1;
    }
}
return 0;

二分搜索的比较次数分析

  • 最少比较一次;

  • 最多呢?

在while循环中,第一次循环之后A[mid+1,…,n]剩余的元素个数最多为:n/2 或者 (n-1)/2

若n为偶数,令n=2*k,则最多剩余k个;

若n为奇数,令n=2*k+1,则最多剩余k个;

最多剩余的个数总是:⌊n/2⌋

接着在第二次循环之后剩余的元素个数为:⌊⌊n/2⌋/2⌋=⌊n/4⌋。(证明方法来源于教材的定理2.1)

快速证明:

1.在10进制的情况下:

​ 123除以10等于12.3;3568除以10等于356.8;相当于小数点向左移一位;

2.同理在2进制的情况下:

​ 小数点也是向左移一位,并且舍去小数位;

​ 所以除以4就相当于小数点连续左移两位,并且舍去小数位;

那么,在第j-1次循环之后,剩余的元素个数为:⌊n/2(j-1)⌋(2的j-1次方)

所以,j=⌊㏒n⌋+1(以2为底取对数)。

最多循环次数,最多比较次数都是j=⌊㏒n⌋+1

合并两个已排序的表

问题来源

​ 两个数组A[p…q],A[q+1…r]已经是有序排列了(不妨设为非降序)

​ 例如:

​ 输入:3,7,9,12;1,2,4,13,14作为两个数组

​ 输出:1,2,3,4,7,9,12,13,14;

【方法一】:使用辅助数组

基本思想:

  • 三个数组

  • A[p…q],A[q+1…r],B[p…r]

  • 3个指针:s,t,k

    s初始化时各自指向A[p] -》 t初始化时各自指向A[q+1] -》 k初始化时各自指向B[p],暂存器 -》

    比较A[s],A[t],小的值存入B[k] -》 小的指针+1,形成新比较对,存入k+1 -》 某组已到尾部,将另一组尚未比较的复制到B -》 B回写到A

s=p,t=q+1,k=p;												//设定初始值
while (s <= q && t <= r){
   									//while (循环条件){
   
    if (A[s]<A[t]){
   											//	当A[s]小于A[t]时,将A[s]给B[k]
        B[k]=A[s];											//	s+1形成新的比较对
        s++;													
    }
    else{
   													//	同上,道理相同
        B[k]=A[t];														
        t++;
    }
    k++;													//	k+1,将新比较对结果,放入B[k+1]
}															//}
if(s>q){
   													//当一个数组全部处理完时,将另外一个数组尚未比较的数字复制到B
    B[k....r]=A[t....r];
}
else {
   														
    B[k...r]=A[s...q];
}
A[p....r]=B[p....r];										//B回写到A;
return 0;													//return 0;

观察结论:

  • 辅助数组算法(Merge)将n1=q-p+1和n2=r-q大小的两个数组合并成一个n=n1+n2的数组,(n1≤n2)元素的比较次数为n1到n-1之间。

    特例:如果两个数组的大小为**⌊n/2⌋⌈n/2⌉**,需要比较的次数在⌊n/2⌋到n-1之间。

【方法二】:改进后的Merge算法

优化思路:

可以省去一部分由A写到B再由B回写A的重复步骤;

if(s>q){
   																	
    B[k....r]=A[t....r];				//可以直接省去这一步,直接将A[t...r]不动即可
}
else{
   
    B[k.....r]=A[s....q];				//可以将A[s....q]直接赋值给A[k....r]
}
A[p....r]=B[p....r
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值