为防止广告,目前nocow只有登录用户能够创建新页面。如要创建页面请先登录/注册(新用户需要等待1个小时才能正常使用该功能)。

归并排序

来自NOCOW
跳转到: 导航, 搜索

目录

[编辑] 介绍

归并排序的思想很简单,我们将一个无序的序列排成有序的很麻烦,但将两个有序的序列合并成一个序列却只需要O(n)的时间就能完成。所以归并排序的做法就是将一个序列分成等长或长度差一的两个序列,对两个序列再次进行归并排序,显然只有一个元素的有序序列就是其本身,所以边界条件也很明显。

  • 归并就是将多个有序的数列合成一个有序的数列。将两个有序序列合并为一个有序序列叫二路归并(merge).归并排序就是n长度为1的子序列,两两归并最后变为有序的序列。

[编辑] 分析

与同样是O(nlogn)的快排相比,归并排序最大的缺点就是每次合并两个序列时,都必须要一些辅助空间来完成。

[编辑] 算法实现

PASCAL:

program MergeSort;
const
 n=10;
var
 a:array[1..n] of integer;
 i:integer;
 
procedure init;
var
 i:integer;
begin
 for i:=1 to n do read(a[i]);
 readln;
end;
 
procedure merge(low,mid,high:integer);
var
 h,i,j,k:integer;
 b:array[1..n] of integer;
 
begin
 h:=low; i:=low; j:=mid+1;
 while (h<=mid) and (j<=high) do
 begin
  if (a[h]<=a[j]) then
   begin
    b[i]:=a[h]; h:=h+1;
   end
  else
   begin
    b[i]:=a[j]; j:=j+1;
   end;
  i:=i+1;
 end;
 if h>mid then
  for k:=j to high do
   begin
    b[i]:=a[k]; i:=i+1;
   end
 else
  for k:=h to mid do
   begin
    b[i]:=a[k]; i:=i+1;
   end;
  for k:=low to high do
  a[k]:=b[k];
 end;
 
procedure mergesort(low,high:integer);
var
mid:integer;
begin
 if low<high then
  begin
   mid:=(low+high) div 2;
   mergesort(low,mid); 
   mergesort(mid+1,high);
   merge(low,mid,high);
  end;
end;
 
begin
  init;
  merge(1,5,10);
  mergesort(1,10);
  for i:=1 to n do writeln(a[i]);
end.

C:

/* merges.c
 * zr95.vip@gmail.com */
 
#include <stdio.h>
#define MAX 10000
 
int D[MAX], T[MAX];
 
void merge(int *begin, int *end)
/* 归并排序左闭右开区间[begin, end) */
{
	if (end - begin > 1) {
		int *middle = begin + (end - begin) / 2;
		int *p = begin;
		int *q = middle;
		int c = 0;
		/* 分治 ——对左右半边分别进行归并排序 */
		merge(begin, middle);
		merge(middle, end);
		/* 将左右半边归并 */
		while (p < middle && q < end) {
			if (*p < *q)
			        T[c++] = *p++;
			else
			        T[c++] = *q++;
		}
		/* 当左右不等长时,不要遗漏 */
		while (p < middle)
		        T[c++] = *p++;
		while (q < end)
		        T[c++] = *q++;
		/* 复制回去 */
		while (c--)
			begin[c] = T[c];
	}
}
 
int main()
{
	int n;
	int i;
	scanf("%d", &n);
	for (i = 0; i < n; ++i)
	        scanf("%d", &D[i]);
	merge(D, D+n);
        for (i = 0; i < n; ++i)
	        printf("%d ", D[i]);
	return 0;
}

C++:

#include <iostream>
#include <cstring>
 
using namespace std;
 
int a[1000];
 
void gbsort(int i,int j) {
 
	if (i==j) return;
	int mid=(i+j)>>1,m=mid+1,n=i;
	int* c=new int[j-i+2];
	gbsort(i,mid);
	gbsort(mid+1,j);
	for (int k=1; k<=j-i+1; k++)
		if ((a[n]<a[m] && n<=mid)||m>j) c[k]=a[n++];
			else if ((a[m]<=a[n] && m<=j)||n>mid) c[k]=a[m++];
	n=i;
	for (int k=1; k<=j-i+1; k++) a[n++]=c[k];
}
 
int main() {
 
	int n;
	scanf("%d",&n);
	for (int i=1; i<=n; i++) scanf("%d",&a[i]);
	gbsort(1,n);
	for (int i=1; i<=n; i++) printf("%d ",a[i]);
	return 0;
 
}//by ymfoi

[编辑] 算法实例

[编辑] 二路归并

例:将有序表L1=(1,5,7),L2=(2,3,4,6,8,9,10)合并一个有序表 L. 程序:

program gb;
const m=3;n=7;
type arrl1=array[1..m] of integer;
     arrl2=array[1..n] of integer;
     arrl=array[1..m+n] of integer;
var a:arrl1;
    b:arrl2;
    c:arrl;
    i,j,k,r:integer;
begin
 write('Enter l1(sorted):');
 for i:=1 to m do read(a[i]);
 write('Enter l2(sorted):');
 for i:=1 to n do read(b[i]);
 i:=1;j:=1;k:=0;
 while (i<=m) and (j<=n) do
  begin
   k:=k+1;
   if a[i]<=b[j] then begin c[k]:=a[i];i:=i+1; end
               else begin c[k]:=b[j];j:=j+1;end;
  end; 
 if i<=m then for r:=i to m do c[m+r]:=a[r];
 if j<=n then  for r:=j to n do c[n+r]:=b[r];
 writeln('Output data:');
 for i:=1 to m+n do write(c[i]:5);
 writeln;
end.

[编辑] 归并排序

程序:

program gbpx;
const maxn=7;
type arr=array[1..maxn] of integer;
var a,b,c:arr;
    i:integer;
procedure merge(r:arr;l,m,n:integer;var r2:arr);
var i,j,k,p:integer;
begin
 i:=l;j:=m+1;k:=l-1;
 while (i<=m)and (j<=n) do
  begin
   k:=k+1;
   if r[i]<=r[j] then begin r2[k]:=r[i];i:=i+1 end
                 else begin r2[k]:=r[j];j:=j+1 end
  end;
 if i<=m then
  for p:=i to m do begin k:=k+1;r2[k]:=r[p] end;
 if j<=n then
  for p:=j to n do begin k:=k+1;r2[k]:=r[p] end;
end;
procedure mergesort( var r,r1:arr;s,t:integer);
var k:integer; c:arr;
begin
 if s=t then r1[s]:=r[s] else
   begin
    k:=(s+t) div 2;
    mergesort(r,c,s,k);
    mergesort(r,c,k+1,t);
    merge(c,s,k,t,r1)
   end;
end;
begin
 write('Enter data:');
 for i:= 1 to maxn do
  read(a[i]);
 mergesort(a,b,1,maxn);
 for i:=1 to maxn do
  write(b[i]:9);
 writeln;
end.
归并排序是一个小作品,欢迎帮助扩充这个条目。
个人工具