C:八种排序算法——归并排序(5)

归并排序

原理:

归并排序采用的是分治法,并且依托于归并操作,其思想是分而治之
归并操作是将两个有序的数列合并到一个有序的序列,那么对于一个无序的长序列,可以把它分解为若干个有序的子序列,然后依次进行归并。如果我们说每一个数字都是单独有序的序列,那么只要把原始长序列依次分解,直到每个子序列都只有一个元素的时候,再依次把所有的序列进行归并,直到序列数为1为止。

思路:

  1. 分解:将列表越分越小,直至分成一个元素。
  2. 终止条件:一个元素是有序的。
  3. 合并:将两个有序列表归并,列表越来越大。

图解归并排序

在这里插入图片描述
算法解析:

  1. 每一层的时间复杂度是O(n),层数是logn。因此总的时间复杂度是O(nlogn)。
  2. 归并排序需要一个与原数组相同长度的数组做辅助来排序由于merge函数创建了一个aux的临时空间,到最大的时候长度是n,空间复杂度是O(n)。
  3. 稳定性:归并排序是稳定的排序算法
  4. 该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列,归并排序的比较次数小于快速排序的比较次数,移动次数一般多于快速排序的移动次数

C代码如下:

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

//归并排序——治
void merge(int a[], int l, int r, int mid)
{
	int aux[8] = { 0 };
	int i, j, k;

	for (k = l; k <= r; k++){//在治的过程中,对数组做拷贝
		aux[k - l] = a[k];
	}

	i = l;
	j = mid + 1;
	for (k = l; k <= r; k++)
	{
		if (i>mid)//左数组的值已经全部排列完毕
		{
			a[k] = aux[j - l];
			j++;
		}
		else if (j>r)//右数组的值已经全部排列完毕
		{
			a[k] = aux[i - l];
			i++;
		}

		//左右两个数组最左端进行对比
		else if (aux[i - l]>aux[j - l])
		{
			a[k] = aux[j - l];
			j++;
		}
		//保证当左右两部分的值相等的时候,先复制左边的值,这样可以保证值相等的时候两个元素的相对位置不变。
		else
		{
			a[k] = aux[i - l];
			i++;
		}
	}
}

//归并排序————分
void MergeSort(int a[], int l, int r)
{
	if (l >= r)
		return;

	int mid = l + (r - l) / 2;

	MergeSort(a, l, mid);
	MergeSort(a, mid + 1, r);
	merge(a, l, r, mid);
}

int main(){
	int i;
	int arr[] = { 8, 4, 5, 7, 1, 3, 6, 2 };
	int len = sizeof(arr) / sizeof(arr[0]);

	MergeSort(arr, 0, len-1);

	for (i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	system("pause");
	return 0;
}

代码生成图
在这里插入图片描述


如有不同见解,欢迎留言讨论!

发布了92 篇原创文章 · 获赞 32 · 访问量 4657

猜你喜欢

转载自blog.csdn.net/AngelDg/article/details/104232750