C语言归并排序算法的实现

归并排序是将两个或两个以上有序表合并成一个有序表的过程,其算法稳定,可以用于链式存储结构,且不需要附加储存空间,但递归时由于必须开辟相应的递归工作栈,故这个算法对内存要求较高。归并排序的时间复杂度为O(nlog2n),空间复杂度为O(n)。

下面是实现代码:

预定义和类型定义:

#define OK 1
#define ERROR 0
#define MAXSIZE 100

typedef int Status;
typedef int RedType;
typedef int ElemType;

typedef struct{
	ElemType *data;
	int length;
}SqList;

顺序表的建立:

Status InitSqList(SqList *L)
{
	L->data = (int *)malloc(sizeof(int)*MAXSIZE);
	L->length = 0;
	return OK;
}

Status EnSqList(SqList *L, ElemType e)
{
	if (L->length >= MAXSIZE)
		return ERROR;
	L->data[L->length + 1] = e;
	L->length++;
	return OK;
}

相邻两个有序子序的归并:

void Merge(RedType R[], RedType *T, int low, int mid, int high)
{
	int i, j, k;
	i = low;
	j = mid + 1;
	k = low;
	while (i <= mid&&j <= high)
	{
		if (R[i] <= R[j])
			T[k++] = R[i++];
		else
			T[k++] = R[j++];
	}
	while (i <= mid)
		T[k++] = R[i++];
	while (j <= high)
		T[k++] = R[j++];
}

初始化i、k指向R[],T[]最开始的位置,j指向R[]的中间加1的位置(mid+1),将R[]分为两个数组。当i小于或等于mid,并且当j小于或等于high的时候,表明未比较完毕,则执行循环:如果将i指向元素和j指向元素进行比较,将比较小的元素记录进数组T[],并让该“指针”(i或j)还有k后移一位。退出循环后将其中一个数组(R[]的一半数据)在比较中未保存在T[]的元素(此时可以确定这一部分比写入的任何一个元素都大,且为有序序列)全部写入T[]。

归并排序:

void MSort(RedType R[], RedType *T, int low, int high)
{
	int mid;
	RedType S[MAXSIZE];
	if (low == high)
		T[low] = R[low];
	else
	{
		mid = (low + high) / 2;
		MSort(R, S, low, mid);
		MSort(R, S, mid + 1, high);
		Merge(S, T, low, mid, high);
	}
}

void MergeSort(SqList *L)
{
	MSort(L->data, L->data, 1, L->length);
}

MSort():如果low和high相等,则说明只有一个元素,不必进行排序,直接将其写入T[]中;若不相等,则确定其中点,将其左右分为两个数组,递归调用MSort(),对左右两部分进行排序,如此类推,直到每个数组只有一个元素,则对相邻的两个数组进行排序,然后返回上一递归层......直到mid左右序列有序,然后再调用Merge()对左右两个数组进行归并排序。

MergeSort():调用Msort()函数。

加入main():

int main(void)
{
	int n, i;
	SqList L;
	ElemType e;
	InitSqList(&L);
	printf("输入元素个数:");
	scanf("%d", &n);
	srand((int)time(0));
	for (i = 0; i < n; i++)
	{
		e = rand();
		EnSqList(&L, e);
	}
	printf("排序前:");
	for (i = 1; i <= L.length; i++)
		printf("%d ", L.data[i]);
	printf("\n");
	MergeSort(&L);
	printf("排序后:");
	for (i = 1; i <= L.length; i++)
		printf("%d ", L.data[i]);
	printf("\n");
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值