歸併排序方法

任意給出一行隨機數,對這些隨機數從小到大,進行歸併排序。

這裏只是簡單的沒有用到遞歸,後續的改進算法思想:1、不回寫(減少這裏copy()函數),2、不逆序,(組合片段時,選擇那些已經是順序的片段,例如(3,5,6),(4),(2),(7,8)),3、與插入結合(因爲可以證明,當每個片段的長度<=16時,插入排序較好,所以可以選擇片度小於16的進行插入排序,然後進行歸併)。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define LEN 37

void merge(int i, int j, int d);
void print(int a[]);
void copy();

int a[LEN];
int b[LEN];

void main(void)
{
	int i,j,d;

	srand((unsigned int)time(NULL));
	for(i=0; i<LEN; i++)
	{
		a[i]=rand()%LEN+1;
	}
	printf("排序之前的序列:\n");
	print(a);
	printf("\n");
	//歸併的基本思想:把一個長序列,先一個數佔一個片段,然後兩兩按序合併,合併的有序的片段再與其它
	//合併的有序片段進行合併,直到整個序列都是有序的,
	//用i表示第一個片段的起始位置,用j表示第二個片段的起始位置,
	//d表示兩個片段之間的跨度,進行兩兩合併
	
	d=1;
	
	while(d<LEN)
	{
		i=0;
		j=i+d;

		while(j<LEN+1)
		{
			
			merge(i,j,d);
			
			//定位下一對片段位置
			i=i+2*d;    
			j=j+2*d;
		}
		d=2*d;  //新的跨度
		copy();
		//printf("\n***a[0]=%d***\n",a[0]);
	}
	printf("排序之後的序列:\n");
	print(b);
	printf("\n");

}

//把兩個有序序列合併到一個序列中
void merge(int i, int j, int d)
{
	int k=i;
	int leni=i+d;
	int lenj;
	if(j+d>LEN)
	{
		lenj=LEN;
	}
	else
	{
		lenj=j+d;
	}
	while(i<leni && j<lenj)
	{
		if(a[i]>a[j])
		{
			b[k]=a[j];
			k++;
			j++;
		}
		else
		{
			b[k]=a[i];
			k++;
			i++;
		}
	}
	while(i<leni)
	{
		b[k]=a[i];
		i++;
		k++;
	}
	while(j<lenj)
	{
		b[k]=a[j];
		j++;
		k++;
	}
}

void print(int a[])
{
	int i;
	for(i=0; i<LEN; i++)
	{
		printf("%3d\t",a[i]);
	}
}

void copy()
{
	int i;
	for(i=0; i<LEN; i++)
	{
		a[i]=b[i];
	}
}


發佈了21 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章