1. 程式人生 > >歸併排序(遞迴和非遞迴方法實現)

歸併排序(遞迴和非遞迴方法實現)

/*
歸併排序
VS2010
*/

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

#define OK 1
#define ERROR 0
#define MAXSIZE 50

typedef struct
{
	int value;
}RedType; 

typedef struct
{
	RedType red[MAXSIZE+1];
	int length;
}SqList;

SqList *CreateSqList()
{
	int i = 0;
	int j = 0;
	char buf[4*MAXSIZE] = "";
	char *ptr = NULL;
	SqList *sqlist = (SqList *)malloc(sizeof(SqList));
	memset(sqlist, 0, sizeof(SqList));

	printf("請輸入待排序資料,以逗號分隔,以分號結束\n"
		"例:23,12,65,36,35;\n"
		"input:");
	scanf("%s", buf);

	ptr = buf;
	sqlist->red[i].value = 0;	//red[0]不存值用作哨兵單元
	i = 1;
	while(*ptr != ';')
	{
		sqlist->red[i].value = atoi(ptr);
		i++;

		ptr = strstr(ptr, ",");
		if(!ptr)
		{
			break;
		}
		ptr++;
	}
	sqlist->length = (i - 1);

	return sqlist;
}

//將有序的src[start...mid]和src[mid+1...end]歸併為有序的TR[start...end]
int Merging(RedType src[MAXSIZE+1], RedType *des, int start, int mid, int end)
{
	int i = 0;	//作為src[start...mid]的遊標
	int j = 0;	//作為src[mid+1...end]的遊標
	int k = 0;	//作為des[start...end]的遊標

	i = start;
	j = mid + 1;
	k = start;

	for( ; (i <= mid && j <= end); k++)	//將src中記錄由小到大地併入des
	{
		if(src[i].value <= src[j].value)
		{
			des[k] = src[i];
			i++;
		}
		else
		{
			des[k] = src[j];
			j++;
		}
	}

	if(i <= mid)
	{
		for( ; i <= mid; i++, k++)
		{
			des[k] = src[i];
		}
	}
	if(j <= end)
	{
		for( ; j <= end; j++, k++)
		{
			des[k] = src[j];
		}
	}

	return OK;
}

//將src[start...end]歸併排序為des[start...end]
int MSort(RedType src[], RedType des[], int start, int end)
{
	int mid = 0;
	RedType tmp[MAXSIZE+1];

	if(start == end)
	{
		des[start] = src[start];
	}
	else
	{
		mid = (start + end) / 2;	//將src[start..end]平分為SR[start...mid]和SR[mid+1..end]
		MSort(src, tmp, start, mid);
		MSort(src, tmp, (mid + 1), end);
		Merging(tmp, des, start, mid, end);
	}

	return OK;
}

//對順序表sqlist作歸併排序,採用遞迴的方法
int MergingSort(SqList *sqlist)
{
	MSort(sqlist->red, sqlist->red, 1, sqlist->length);
	return OK;
}

//將src[]中相鄰長度為s的子序列兩兩歸併到des[]
void MergePass(RedType src[], RedType des[], int s, int length)
{
	int i = 1;
	int j = 0;
	while(i <= length - 2 * s + 1) 
	{ 
		Merging(src, des, i, i + s - 1, i + 2 * s - 1);		//兩兩歸併
		i = i + 2 * s;
	}
	if(i < length - s + 1)		//歸併最後兩個序列
	{
		Merging(src, des, i, i + s - 1, length);
	}
	else			//若最後只剩下單個子序列
	{
		for(j = i; j <= length; j++)
			des[j] = src[j];
	}
}

//對順序表sqlist作歸併非遞迴排序
void MergingSort2(SqList *sqlist)
{
	int k = 1;
	int* tmp = (RedType *)malloc(sqlist->length * sizeof(RedType));	//申請額外空間
	while(k < sqlist->length)
	{
		MergePass(sqlist->red, tmp, k, sqlist->length);
		k = 2 * k;			//子序列長度加倍
		MergePass(tmp, sqlist->red, k, sqlist->length);
		k = 2 * k;			//子序列長度加倍
	}
}

//打印表中資料
int PrintSqList(SqList sqlist)
{
	int i = 0;
	for(i = 1; i <= sqlist.length; i++)
	{
		printf("%d,", sqlist.red[i].value);
	}
	printf("\b;\n");
	return OK;
}

int main()
{
	SqList *sqlist = NULL;
	SqList *testSqList = NULL;
	sqlist = CreateSqList();
	testSqList = (SqList *)malloc(sizeof(SqList));

	printf("\n遞迴實現歸併排序:\n");
	memcpy(testSqList, sqlist, sizeof(SqList));
	PrintSqList(*testSqList);
	MergingSort(testSqList);
	PrintSqList(*testSqList);

	printf("\n非遞迴實現歸併排序:\n");
	memcpy(testSqList, sqlist, sizeof(SqList));
	PrintSqList(*testSqList);
	MergingSort2(testSqList);
	PrintSqList(*testSqList);

	free(testSqList);
	free(sqlist);
	system("pause");

	return 0;
}