子数组合并

问题描述:


设子数组a[0:k-1]和a[k:n-1]已排好序(0<=k<=n-1)。试设计一个合并这两个子数组为排好序的数组a[0:n-1]的算法。要求算法在最坏情况下所用的计算时间为O(n),且只用到O(1)的辅助空间。

 

思路:

首先用二分搜索算法在数组段a[k:n-1]中搜索a[0]的插入位置,即找到位置p使得a[p]<a[0]<=a[p+1]。数组段a[0:p]向左循环移位p-k+1个位置。此时,数组元素a[p]及其左边的所用元素均已排好序。对剩余的数组元素重复上述过程,直至剩下一个数组段,此时整个数组已排好序。

例int a[7]= {7,9 ,11,13,6,8,10}

k=4,a[0]在a[k:6]的插入位置为p=4; 将数组段a[0:p]循环左移p-k+1=4-4+1=1个位置得到

a[7]={6,7,9,11,13,8,10}

此时k=p+1=5.下一个要考察的元素为a[2]

然后查看a[2]在数组a[5:n-1]的插入位置p=5 数组段a[2:5]向左循环移位p-k+1=1个位置,此时数组变为

a[7]={6,7,8,9,11,13,10}

 此时k=6,下一个要考察的元素为a[4]=11

然后查看a[4]在数组a[6:6]的插入位置为p=6,数组段a[4:6]向左循环移位6-6+1=1个位置,此时数组为

a[7]={6,7,8,9,10,11,13}

此时k=7>n-1,循环结束

 

 代码如下:

#include <iostream>
using namespace std;
int binarysearch(int a[],int x,int left,int right)//二分搜索
{
 int middle;
 while(left<=right)
 {
  middle=(left+right)/2;
 if(x==a[middle])
  return middle;
 if(x>a[middle])
  left=middle+1;
 else
  right=middle-1;
 }
 if(x>a[middle])
  return middle;
 else
  return middle-1;
}
void shiftleft(int a[],int s,int t,int k)   //a[s,t]中元素循环左移k个位置
{
 int i,j,temp;
 for(i=0;i<k;i++)
 {
  temp=a[t];
 for(j=t;j>s;j--)
  a[j]=a[j-1];
 a[s]=temp;
 }
}
void mergefor(int a[],int k,int n)
{
 int i=0,j=k;
 int p;
 while(i<j&&j<n)
 {
  p=binarysearch(a,a[i],j,n-1);
   shiftleft(a,i,p,p-j+1);
  
   i+=p-j+2;
   j=p+1;
  
 }
}
int main()
{
 int a[10]={1,5,6,7,2,3,4,8,9,10};
 int x,temp;
    int i;
 //temp=5;
   //x=binarysearch(a,temp,0,3);
 //shiftright(a,0,3,2);
 mergefor(a,4,10);
 
 for(i=0;i<10;i++)
  cout<<a[i]<<' ';
 
 //cout<<x;

 
 return 0;
}


  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值