1. 程式人生 > >歸併排序——將兩個有序表直接歸併為一個有序表

歸併排序——將兩個有序表直接歸併為一個有序表

歸併排序是多次將兩個或兩個以上的有序表合併成一個新的有序表。最簡單的歸併是直接將兩個有序的子表合併成一個有序的表,即二路歸併

二路歸併的排序基本思想是:

       將a[0……n-1]看成是n個長度為1的有序序列,然後進行兩兩歸併,得到n/2(向上取整)個長度為2(最後一個有序序列的長度可能為1)的有序序列,再進行兩兩歸併,得到n/4(向上取整)個長度為4(最後一個有序序列的長度可能小於4)的有序序列……直到得到一個長度為n的有序序列

歸併排序每趟產生的有序區只是區域性有序的,也就是說在最後一趟排序結束前,所有元素並不一定歸位了

每次從兩個段中取出一個元素進行關鍵字的比較,將較小者放入c[ ]中,最後將各段餘下的部分直接複製到c[ ]中

#include<stdio.h>
#include<iostream>
using namespace std;
//a[]、b[]為需要合併的兩個陣列,c為合併後的新陣列,n為a[]的長度,m為b[]的長度
void merge(int a[],int b[],int c[],int n,int m){
	int i=0,j=0,k=0;//i為a[]的下標,j為b[]的下標,k為c[]的下標	
	//在a[]和b[]均未掃描完時迴圈
	while(i<n && j<m){
		if(a[i]<=b[j])
		   c[k++]=a[i++];
		else
		   c[k++]=b[j++];
	}
	//如果a[]還有剩餘,則將餘下部分賦值過去
	while(i<n){
	   c[k++]=a[i++];
	}
	//如果b[]還有剩餘,則將餘下部分賦值過去
	while(j<m){
	   c[k++]=b[j++];
	}
}
int main(){
  int n,m;//n為a[]的長度,m為b[]的長度
   //初始化
  //陣列a[]
  cout<<"n:";
  cin>>n;
  int *a=new int[n];
  cout<<"輸入"<<n<<"個數的第一個有序列表:";
  for(int i=0;i<n;i++){
     cin>>a[i];
  }
  //陣列b[]
  cout<<"m:";
  cin>>m;
  int *b=new int(m);
  cout<<"輸入"<<m<<"個數的第二個有序列表:";
  for(int i=0;i<m;i++){
     cin>>b[i];
  }
  int *c=new int(n+m);//c為合併後的陣列
 //歸併兩個有序列表
  merge(a,b,c,n,m);
  //輸出
  cout<<"合併後為:"; 
  for(int i=0;i<n+m;i++){
    cout<<c[i]<<" ";
  }
  cout<<endl;
}