归并排序

来源:互联网 发布:linux vi 全选复制 编辑:程序博客网 时间:2024/06/11 02:09

概述

归并排序是典型的分而治之策略的应用。主要是把一个数组分成若干个子数组进行从小到大的归并直至有序。下面所说的归并排序默认为2路归并排序。


递归算法思想

1)将数组平分为2等份,对这两个子数组进行从小大到有序归并。
2)递归对左半部分进行2路归并
3)递归对右半部分进行2路归并

//一趟归并 void Merge(int* data,int* tmp,int left,int right,int rightend){    int leftend = right-1;    int size = rightend-left+1;    int cnt = left;    while(left <= leftend && right <= rightend){        if(data[left] < data[right]){            tmp[cnt++] = data[left++];        }else{            tmp[cnt++] = data[right++];        }    }    while(left <= leftend){        tmp[cnt++] = data[left++];    }    while(right <= rightend){        tmp[cnt++] = data[right++];    }    for(int i = 0 ; i < size ; i++,rightend--){        data[rightend] = tmp[rightend];     }}//归并排序  void Msort(int* data,int* tmp,int left,int rightend){    if(left < rightend){        int mid = (left+rightend)/2;        Msort(data,tmp,left,mid);        Msort(data,tmp,mid+1,rightend);        Merge(data,tmp,left,mid+1,rightend);    }}//归并排序(递归版本)void Merge_Sort(int* data,int size){    int* tmp = new int[size];    if(tmp != NULL){        Msort(data,tmp,0,size-1);    }}

非递归算法思想

1)首先构造一个与原数组大小一样的临时数组
2)设置归并长度length = 1,从头开始堆两个length长度的数组进行归并到tmp直至倒数第二组。由于原数组长度与length布置时候能整除,如果能整除,那么把最后一组归并到数组了,若不能,那么就直接导入tmp数组。
3)更新length,使之翻倍,重复上述2)操作,只不过是把tmp的数组归并到原数组。
4)重复上述2)与3)操作,直至length大于数组长度。

//一趟归并 void Merge(int* data,int* tmp,int left,int right,int rightend){    int leftend = right-1;    int size = rightend-left+1;    int cnt = left;    while(left <= leftend && right <= rightend){        if(data[left] < data[right]){            tmp[cnt++] = data[left++];        }else{            tmp[cnt++] = data[right++];        }    }    while(left <= leftend){        tmp[cnt++] = data[left++];    }    while(right <= rightend){        tmp[cnt++] = data[right++];    }    for(int i = 0 ; i < size ; i++,rightend--){        data[rightend] = tmp[rightend];     }}//一趟归并排序void Merge_Pass(int* data,int* tmp,int size,int length){    int i;    for(i = 0 ; i <= size-2*length ; i += 2*length){        Merge(data,tmp,i,i+length,i+2*length-1);    }    if(i+length < size){//归并最后两个子序列         Merge(data,tmp,i,i+length,size-1);    }else{//归并最后一个子序列         for(int j = i ; j < size ; j++){            tmp[j] = data[j];        }    }}//归并排序(非递归排序)void Merge_Sort1(int* data,int size){    int* tmp = new int[size];    int length = 1;    if(tmp != NULL){        while(length < size){            Merge_Pass(data,tmp,size,length);            length*=2;            Merge_Pass(tmp,data,size,length);            length*=2;        }        delete tmp;    }}

全部代码

#include <iostream>#include <cstdlib>#include <ctime>using namespace std;//初始化数组 void SetArray(int* data,int size){    //srand(time(0));    cout<<"随机初始化"<<size<<"个数"<<endl;    for(int i = 0 ; i < size ; i++){        data[i] =rand()%100+1;    }}//打印函数 void Print(int* data ,int size){    for(int i = 0 ; i < size ; i++){        cout<<data[i]<<" ";     }    cout<<endl;}       //一趟归并 void Merge(int* data,int* tmp,int left,int right,int rightend){    int leftend = right-1;    int size = rightend-left+1;    int cnt = left;    while(left <= leftend && right <= rightend){        if(data[left] < data[right]){            tmp[cnt++] = data[left++];        }else{            tmp[cnt++] = data[right++];        }    }    while(left <= leftend){        tmp[cnt++] = data[left++];    }    while(right <= rightend){        tmp[cnt++] = data[right++];    }    for(int i = 0 ; i < size ; i++,rightend--){        data[rightend] = tmp[rightend];     }}//归并排序  void Msort(int* data,int* tmp,int left,int rightend){    if(left < rightend){        int mid = (left+rightend)/2;        Msort(data,tmp,left,mid);//递归归并排序左半部分         Msort(data,tmp,mid+1,rightend);//递归归并排序右半部分         Merge(data,tmp,left,mid+1,rightend);//对左右部分进行有序归并     }}//归并排序(递归版本)void Merge_Sort(int* data,int size){    int* tmp = new int[size];    if(tmp != NULL){        Msort(data,tmp,0,size-1);    }}//一趟归并排序void Merge_Pass(int* data,int* tmp,int size,int length){    int i;    for(i = 0 ; i <= size-2*length ; i += 2*length){        Merge(data,tmp,i,i+length,i+2*length-1);    }    if(i+length < size){//归并最后两个子序列         Merge(data,tmp,i,i+length,size-1);    }else{//归并最后一个子序列         for(int j = i ; j < size ; j++){            tmp[j] = data[j];        }    }}//归并排序(非递归排序)void Merge_Sort1(int* data,int size){    int* tmp = new int[size];    int length = 1;    if(tmp != NULL){        while(length < size){            Merge_Pass(data,tmp,size,length);            length*=2;            Merge_Pass(tmp,data,size,length);            length*=2;        }        delete tmp;    }}int main(){    cout<<"请输入数组长度:"<<endl;    int size,*data;    cin>>size;    data = new int[size];    SetArray(data,size);    cout<<"归并排序(递归版本)前:"<<endl;    Print(data,size);    cout<<"归并排序(递归版本)后:"<<endl;    Merge_Sort(data,size);    Print(data,size);     SetArray(data,size);    cout<<"归并排序(非递归版本)前:"<<endl;    Print(data,size);    cout<<"归并排序(非递归版本)后:"<<endl;    Merge_Sort1(data,size);    Print(data,size);    return 0; }  

截图:
这里写图片描述

原创粉丝点击