数据结构排序算法之归并排序(c语言实现)

博主身为大二萌新,第一次学习数据结构,自学到排序的时候,对于书上各种各样的排序算法顿觉眼花缭乱,便花了很长的时间尽力把每一个算法都看懂,但限于水平有限,可能还是理解较浅,于是便将它们逐个地整理实现出来,以便加深理解。

归并排序就是通过将一个具有n个key记录的线性表,看成是具有n个有序子序列的排序叠加来实现对原有序列的排序的一种算法。它的中间状态就是将所有的子序列长度变为1,再将它们两两进行归并,得到长度为2或1的次级子序列,之后再进行两两归并,如此反复,直到得到一个长度为n的有序序列。这个过程包含了很多次的切分与归并,可以通过递归的方式来实现。归并排序的改进形式没有使用耗时较大的递归,而是改用了迭代法,这里我们先来讨论比较基础的递归法。

一共分成两个函数,一个是切分归并函数,另一个则是实现归并的函数。

话不多说,先粘贴我根据算法实现出来的源代码。

运行环境:win10&vs2015&.cpp或.c后缀文件形式

#include "stdafx.h"
#include "stdio.h"
#include "malloc.h"
#include <string.h>
#include<cstdlib>

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

typedef int Status;

typedef struct {//一个简单的线性链表结构
	int *Data;//线性链表的初址
	int length;
}SqList;

/*线性链表初始化函数*/
Status InitSqList(SqList *S) {
	int n;
	printf("请输入需排序的数据个数:\n");
	scanf_s("%d", &n);
	getchar();//吸收换行符
	S->length = n;
	S->Data = (int*)malloc((n + 1)*sizeof(int));
	if (!S->Data)return ERROR;
	S->Data[0] = 0;//编写排序程序的小习惯(设立哨兵位,用于插入排序)
	for (int i = 1; i <= n; i++) {
		printf("第%d个数为:", i);
		scanf_s("%d", &S->Data[i]);
		getchar();//吸收换行符
	}
	return OK;
}

/*归并排序的归并函数*/
void Merge(int SR[], int TR[], int i, int middle, int rightend) {//实际上这里的i也就是要排序合并的数组段的左起始点
	int j, k, l;
	for (k = i, j = middle + 1; i <= middle&&j <= rightend; k++) {
		if (SR[i] < SR[j])/*将SR中的元素按小到大的顺序存入TR,只需比较中点两侧对应下标元素大小*/
			TR[k] = SR[i++];
		else
			TR[k] = SR[j++];
	}
	if (i <= middle) {/*若中点左边元素剩余,将剩余元素并入TR(注意这里并入只要按照顺序即可,因为SR已经排好序了)*/
		for (l = 0; l <= middle - i; l++)
			TR[k + l] = SR[i + l];
	}
	if (j <= rightend) {/*若中点右边元素剩余,将剩余元素并入TR*/
		for (l = 0; l <= rightend - j; l++)
			TR[k + l] = SR[j + l];
	}
}

/*归并排序递归函数*/
void MSort(int SR[], int TR1[], int s, int t) {
	int middle;
	int TR2[MAXSIZE + 1];
	if (s == t)
		TR1[s] = SR[s];
	else {
		middle = (s + t) / 2;/*将SR分成以middle为界的两部分*/
		MSort(SR, TR2, s, middle);/*递归将SR[s,middle]归并为有序的数组TR2*/
		MSort(SR, TR2, middle + 1, t);/*递归将SR[middle+1,t]归并为有序的数组TR2*/
		Merge(TR2, TR1, s, middle, t);/*将上面的两部分分别有序的TR2归并为总体有序的TR1*/
	}
}

/*总体调用排序函数*/
void MergeSort(SqList *S) {
	MSort(S->Data, S->Data, 1, S->length);
}

int main()
{
	SqList S;
	InitSqList(&S);
	MergeSort(&S);
	printf("\n");
	for (int i = 1; i <= S.length; i++){
		printf("第%d个数为\t%d\n", i, S.Data[i]);
	}
	system("pause");
    return 0;
}

运行结果:

《数据结构排序算法之归并排序(c语言实现)》
这里的递归过程我思考了很久才算是彻底想清楚,下面整理给大家,以供参考。

以严蔚敏老师的书上的数列为例:{49,38,65,97,76,13,27}

这些元素在前面代码中对应下标为{1,2,3,4,5,6,7}

《数据结构排序算法之归并排序(c语言实现)》

上图为鄙人对递归函数执行过程的一部分进行的整理。退出(1)与(2)的递归步骤以后,执行的就是Merge(TR2,TR1,1,2,4)的归并排序函数了,就是将TR2[1…2]与TR2[3…4]归并到TR1[1…4](即上图Msort(SR,TR2,1,4)中的形参TR2)。

由此可见,所谓的将TR2排序归并到TR1的merge函数,在退到最外层递归以前,都是指排序归并到merge函数的形参TR1即实参TR2中。在最外层递归函数,才是将middle两侧的排好序的部分有序的TR2归并到真正的TR1中,获得最后的整体有序的排序结果。

另外的半部分的递归执行过程同理,在此就不进行赘述了。

这么一个看上去很简单的归并排序我竟然搞了这么久才懂,也是菜的不行,但想到自己每天能比之前强上那么一点点,就开心的不行呢。

    原文作者:排序算法
    原文地址: https://blog.csdn.net/qq_33234826/article/details/68090208
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞