归并排序

归并排序

基本思想:将数组看到n个长度为1有序表,将相邻的k个有序子表成对归并,得到一个新的有序子表。反复操作,最后得到一个长度为n的有序表。
k=2时,就是二路归并排序。

分治法

1 自底向上的二路归并

策略:分解(原序列看成为n个长度为1的子序列)->求解子问题(相邻子序列合并)->合并(整个序列在数组a中,此处可以忽略)
其中,“相邻子序列合并”时,先将原序列a[]中的两个子表,进行逐个比较,较小者放到一个临时表tmp[],得到一个临时有序表,再将其复制到原序列a中。

#include<bits/stdc++.h>
using namespace std;

//输出数组中的所有元素
void disput(int a[], int n)
{
 for(int i=0; i<n; i++)
  cout<<a[i]<<" ";
 cout<<endl;
 } 

//合并两个相邻序列
void Merge(int a[], int low, int mid, int high)
{
 int *tmpa; //一个临时数组
 tmpa=(int*)malloc((high-low+1)*sizeof(int));
 int i=low, j=mid+1, k=0;
 while(i<=mid&&j<=high) //两个数组均为扫完
 {
  if(a[i]<=a[j])
  {
   tmpa[k]=a[i];
   i++;
   k++;
   } 
  else
  {
   tmpa[k]=a[j];
   j++;
   k++;
  }
 }
 while(i<=mid)
 {
  tmpa[k]=a[i];
  i++;
  k++;
 }
 while(j<=high)
 {
  tmpa[k]=a[j];
  j++;
  k++;
 }
 for(k=0, i=low; i<=high; k++, i++) //还原 
  a[i]=tmpa[k];
 free(tmpa);
 } 

// 一趟二路归并
void MergePass(int a[], int length, int n) 
{
 int i;
 for(i=0; i+2*length-1<n; i=i+2*length)
  Merge(a, i, i+length-1, i+2*length-1);
 if(i+length-1<n) //归并剩下的子表 
  Merge(a, i, i+length-1, n-1);
}

// 二路归并算法
void MergeSort(int a[], int n)
{
 int length;
 for(length=1; length<n; length=2*length)
  MergePass(a, length, n);
 } 

int main()
{
 int n=5;
 int a[n]={2, 33, 45, 16, 8};
 cout<<"原序列为:"<<endl;
 disput(a, n);
 MergeSort(a, n);
 cout<<"二路归并排序后:"<<endl;
 disput(a, n); 
 
 return 0;
 } 

时间复杂度:O(nlog(2)(n))

2 自顶向下的二路归并

策略:分解(原序列一分二)->求解子问题(两个子序列二路归并并排序,知道子序列长度为0/1)->合并(合并已排序的两个子序列)

#include<bits/stdc++.h>
using namespace std;

//输出数组中的所有元素
void disput(int a[], int n)
{
 for(int i=0; i<n; i++)
  cout<<a[i]<<" ";
 cout<<endl;
 } 
 
 //合并两个相邻序列
void Merge(int a[], int low, int mid, int high)
{
 int *tmpa; //一个临时数组
 tmpa=(int*)malloc((high-low+1)*sizeof(int));
 int i=low, j=mid+1, k=0;
 while(i<=mid&&j<=high) //两个数组均为扫完
 {
  if(a[i]<=a[j])
  {
   tmpa[k]=a[i];
   i++;
   k++;
   } 
  else
  {
   tmpa[k]=a[j];
   j++;
   k++;
  }
 }
 while(i<=mid)
 {
  tmpa[k]=a[i];
  i++;
  k++;
 }
 while(j<=high)
 {
  tmpa[k]=a[j];
  j++;
  k++;
 }
 for(k=0, i=low; i<=high; k++, i++) //还原 
  a[i]=tmpa[k];
 free(tmpa);
 } 
 
// 二路归并算法
void MergeSort(int a[], int low, int high)
{
 int mid;
 if(low<high)
 {
  mid=(low+high)/2;
  MergeSort(a, low, mid);
  MergeSort(a, mid+1, high);
  Merge(a, low, mid, high);
 }
 } 
 
int main()
{
 int n=5;
 int a[n]={2, 33, 45, 16, 8};
 cout<<"原序列为:"<<endl;
 disput(a, n);
 MergeSort(a, 0, n-1);
 cout<<"二路归并排序后:"<<endl;
 disput(a, n); 
 
 return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值