归并排序

  • 归并算法非递归实现
  • 归并算法应用
  • 抢气球问题


归并算法采用的是分治的思想,是不断将一个序列一分为二,最后合并进行排序的一个过程。
在下面的代码中,mergePass函数起的作用就是“分”,而merge_array函数的作用是“治”和“合”。
最后在主函数中通过循环的方法实现了非递归实现。
时间复杂度是O(nlogn),排序稳定

归并算法非递归实现

// An highlighted block
#include<iostream>
using namespace std;
int test1[100000];
int test2[100000];
void merge_array(int *c,int *d,int l,int m,int r);
void mergePass(int *c,int *d,int s,int length_t);
int main(void){
    int length_t;
    int s = 1;
    cin>>length_t;
    int i=0;
    for(;i<length_t;i++)
        cin>>test1[i];
    while(s<length_t){
        mergePass(test1,test2,s,length_t);
        s+=s;
        mergePass(test2,test1,s,length_t);
        s+=s;
    }
    for(int k=0;k<length_t;k++)
        cout<<test1[k]<<" ";

}
void mergePass(int *c,int *d,int s,int length_t){//将c数组分别排序并合并到d数组
    int i=0;
    while(i<=(length_t-2*s)){
        merge_array(c,d,i,i+s-1,i+2*s-1);
        i=i+2*s;
    }
    if(i+s<length_t){//剩下部分大于s
        merge_array(c,d,i,i+s-1,length_t-1);
    }//剩下的部分小于2s,分为大于s或者小于等于s
    else{
        for(int j=i;j<length_t;j++)
            d[j]=c[j];
    }//小于等于s
}
void merge_array(int *c,int *d,int l,int m,int r){//将数组c合并到d数组中,可以合并了,然后接下来就是分割战场
    int i=l;
    int j=m+1;
    int k=l;
    while(i<=m&&j<=r){
        if(c[i]<=c[j])
            d[k++]=c[i++];
        else
            d[k++]=c[j++];
    }
    if(i>m){
        while(j<=r)
            d[k++]=c[j++];
    }
    else{
        while(i<=m)
            d[k++]=c[i++];
    }
}

归并算法应用

如题:进行两次排序

// An highlighted block
#include<iostream>
using namespace std;
int test1[10000];
int test2[10000];
int test3[10000];
void merge_array1(int *c,int *d,int l,int m,int r);
void mergePass1(int *c,int *d,int s,int l,int r);
void merge_array2(int *c,int *d,int l,int m,int r);
void mergePass2(int *c,int *d,int s,int l,int r);
int main(void){
    int length_t;
    int s = 1;
    cin>>length_t;
    int l1,r1,l2,r2;
    cin>>l1>>r1>>l2>>r2;
    int i=0;
    for(;i<length_t;i++){
        cin>>test1[i];
    }
    while(s<r1-l1+1){
        mergePass1(test1,test2,s,l1-1,r1-1);
        s+=s;
        mergePass1(test2,test1,s,l1-1,r1-1);
        s+=s;
    }
    s=1;
    while(s<r2-l2+1){
        mergePass2(test1,test3,s,l2-1,r2-1);
        s+=s;
        mergePass2(test3,test1,s,l2-1,r2-1);
        s+=s;
    }

	for(int k=0;k<length_t;k++)
        cout<<test1[k]<<" ";
}
void mergePass1(int *c,int *d,int s,int l,int r){//修改一下,这里不写长度,这里写数组下标
    int i=l;//i为起始的下标
    while(i<=(r+1-2*s)){//长度和r下标的区别
        merge_array1(c,d,i,i+s-1,i+2*s-1);
        i=i+2*s;
    }
    if(i+s<r+1){//剩下部分大于s
        merge_array1(c,d,i,i+s-1,r);
    }//剩下的部分小于2s,分为大于s或者小于等于s
    else{
        for(int j=i;j<r+1;j++)
            d[j]=c[j];
    }//小于等于s
}
void merge_array1(int *c,int *d,int l,int m,int r){//将数组c合并到d数组中,可以合并了,然后接下来就是分割战场
    int i=l;
    int j=m+1;
    int k=l;
    while(i<=m&&j<=r){
        if(c[i]<=c[j])
            d[k++]=c[i++];
        else
            d[k++]=c[j++];
    }
    if(i>m){
        while(j<=r)
            d[k++]=c[j++];
    }
    else{
        while(i<=m)
            d[k++]=c[i++];
    }
}
void mergePass2(int *c,int *d,int s,int l,int r){//修改一下,这里不写长度,这里写数组下标
    int i=l;//i为起始的下标
    while(i<=(r+1-2*s)){//长度和r下标的区别
        merge_array2(c,d,i,i+s-1,i+2*s-1);
        i=i+2*s;
    }
    if(i+s<r+1){//剩下部分大于s
        merge_array2(c,d,i,i+s-1,r);
    }//剩下的部分小于2s,分为大于s或者小于等于s
    else{
        for(int j=i;j<r+1;j++)
            d[j]=c[j];
    }//小于等于s
}
void merge_array2(int *c,int *d,int l,int m,int r){//将数组c合并到d数组中,可以合并了,然后接下来就是分割战场
    int i=l;
    int j=m+1;
    int k=l;
    while(i<=m&&j<=r){
        if(c[i]>c[j])
            d[k++]=c[i++];
        else
            d[k++]=c[j++];
    }
    if(i>m){
        while(j<=r)
            d[k++]=c[j++];
    }
    else{
        while(i<=m)
            d[k++]=c[i++];
    }
}

抢气球问题

#include<iostream>
using namespace std;
long airball[100000];//气球高度
long a[100000];
int getRank[100000];//相应的小朋友排名映射。初始标号到排名的映射
long height[100000];//小朋友跳的高度
long origin[100000];
void mergePass(long *c,long *d,int length,int s);
void merge_array(long *c,long *d,int l,int m,int r);
int main(void){
    int n,m;
    cin>>n>>m;//n是小朋友的数量,m是气球的数量
    int i=0;
    for(;i<n;i++){
        cin>>height[i];
    }
    for(i=0;i<m;i++)
        cin>>airball[i];//气球高度就直接归并排序吧
    int s=1;
    while(s<m){
        mergePass(airball,a,m,s);
        s+=s;
        mergePass(a,airball,m,s);
        s+=s;
    }//气球序列排好了
    //选择排序进行操作吧
    for(i=0;i<n;i++)
        getRank[i]=i;
    int minh=0;
    int k=0;
    int j=0;
    long temp1=0;
    int temp2=0;
    for(;k<n-1;++k){
        minh=k;
        for(j=k+1;j<n;j++){
            if(height[j]<height[minh]){
                minh=j;
            }
        }
        temp1=height[k];
        height[k]=height[minh];
        height[minh]=temp1;
        temp2=getRank[k];
        getRank[k]=getRank[minh];
        getRank[minh]=temp2;
    }
    //归并排序出了一点错
    //依次输出吧,temp1作为临时变量存储数据
    j=0;
    for(i=0;i<n;++i){
        temp1=0;
        if(j<m){
            for(;height[i]>=airball[j];j++)
                temp1++;
            origin[getRank[i]]=temp1;
        }
        else
            origin[getRank[i]]=0;
    }
    for(i=0;i<n-1;i++)
        cout<<origin[i]<<endl;
    cout<<origin[n-1];
}
//归并排序
void mergePass(long *c,long *d,int length_t,int s){//将c数组分别排序并合并到d数组
    int i=0;
    while(i<=(length_t-2*s)){
        merge_array(c,d,i,i+s-1,i+2*s-1);
        i=i+2*s;
    }
    if(i+s<length_t){//剩下部分大于s
        merge_array(c,d,i,i+s-1,length_t-1);
    }//剩下的部分小于2s,分为大于s或者小于等于s
    else{
        for(int j=i;j<length_t;j++)
            d[j]=c[j];
    }//小于等于s
}
void merge_array(long *c,long *d,int l,int m,int r){//将数组c合并到d数组中,可以合并了,然后接下来就是分割战场
    int i=l;
    int j=m+1;
    int k=l;
    while(i<=m&&j<=r){
        if(c[i]<=c[j])
            d[k++]=c[i++];
        else
            d[k++]=c[j++];
    }
    if(i>m){
        while(j<=r)
            d[k++]=c[j++];
    }
    else{
        while(i<=m)
            d[k++]=c[i++];
    }
}