欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

归并排序原理及C++源码实现

程序员文章站 2022-03-24 13:53:40
...

一、原理

建立在归并操作上的一种有效、稳定的算法,采用分治法,先使每个子序列有序,然后将以有序的子序列合并,得到完全有序的序列。若将两个有序表合成一个有序表,成为二路归并。

排序思想,一分为二,二分为四,四分为八,直到划分到最细;然后逐渐合并回去。分的时候采用递归的方式进行。


二、思路

先把原始序列进行分组,划分为多个子序列,对每个子序列进行排序,然后子序列之间再两两合并排序得到新的有序序列作为下一次合并的子序,然后再把新子序列合并….如此循环最后得到一个有序的序列。
归并排序原理及C++源码实现

实例:
对数据[1, 4, 2, 6, 7, 3, 5, 10, 9]进行归并排序。

初始状态:1, 4, 2, 6, 7, 3, 5, 10, 9

  1. 第一次分组:{1,4},{2,6},{7,3},{5,10},{9},归并后得到{1,4},{2,6},{3,7},{5,10},{9}
  2. 第二次分组:{1,4,2,6},{3,7,5,10},{9},归并后得到{1,2,4,6},{3, 5,7,10},{9}
  3. 第三次分组:{1,2,4,6,3, 5,7,10},{9},归并后得到{1,2,3,4,5,6,7,10},{9}
  4. 第四次分组:{1,2,3,4,5,6,7,10,9},归并后得到[1,2,3,4,5,6,7,9,10]

三、归并排序特点

  • 稳定的排序,相等元素的顺序不会改变。比如输入记录1(a) 3(b) 2(c )2(d) 5(e) (括号中是记录的关键字)时输出的 1(a) 2(c )2(d) 3(b) 5(e) 中的2 和 2 是按输入的顺序.这对要排序数据包含多个信息而要按其中的某一个信息排序,要求其它信息尽量按输入的顺序排列时很重要。

  • 归并排序的比较次数小于快速排序的比较次数,移动次数一般多于快速排序的移动次数。


四、C++源码实现

拆分完成后,需要对拆分的数据进行排序,这时候归并函数一共有5个参数
sort(int *data, int *temp, int start, int middle, int end); 这里的临时变量temp是用于在两个排序好的集合中作为中间变量合成一个集合。


void merge(int arr[], int *temp, int start, int middle, int end)
{
	int i=start, j=middle+1,k=start;
	
	while(i<=middle && j<=end)
	{
		if(arr[j] < arr[i])
		{
			temp[k++]=arr[j++];
		}
		else
		{
			temp[k++]=arr[i++]
		}
	}
/*
这里表示的是几集合2的数值已经先排序完成,集合1剩下有数据剩余,
这个时候直接把集合1剩余的数据直接插入到合集的后面,比如两个集合,
集合1:1 3 8 9,  集合2:2 4 6 7,集合1和集合2的合集到1 2 3 4 6 7,
此时集合2内的数据已经合并完毕,集合1还有8 9 数据,这个时候直接追加到合集中即可
*/
	while(i <= middle)
	{
		temp[k++]=arr[i++];
	}
	//与上while类似,只是这里剩余的是集合2的数据
	while(j<=end)
	{
		temp[k++]=arr[j++];
	}
	
	//把临时变量中的数值拷贝到数组中
	for(i=start; i <=end; i++)
	{
		arr[i]=temp[i];
	}
}

//start,end参数均为数值的下标值
void mergeSort(int arr[], int *temp, int start, int end)
{
	int middle=0;
	if(start< end)
	{
		middle=start+(end-start)/2;
		mergeSort(arr, temp, start, middle);
		mergeSort(arr, temp, middle+1, end);
		merge(arr, temp, start, middle, end);
	}
}

//调用函数
int main()
{
	int arr[9]={1,4,2,6,7,3,5,10,9};
	int temp[9]={0};
	int len=9;
	
	mergeSort(arr, temp, 0, len-1);
}