排序算法 --- 归并排序

        归并排序是典型的分治思想(所谓分治即分而治之)的实现。具体实现就是将乱序的序列划分为两个子序列,再将子序列又分别向下划分,直到划分成最小单位(这一过程可以通过递归实现)。在不能划分时,将相邻的两个子序列进行比较,按序排列,将排好的序列向上返回,逐层地比较 - - - > 排序 - - - > 归并,直到最终序列有序。

演示:

  • 我们随机生成一个乱序序列:

  • 每次可以较为均匀的将序列划分为两个子序列:

                         

  •  两个子序列执行过程一样,以左序列为例,向下演示:

                       

  • 其中9 2序列再向下划分就为单个元素,即上述所说最小单位:           

                        

  • 此时比较两个相邻元素,我们以升序排列,所以9与2交换变成有序序列,再向上返回:

                        

  • 最初两个子序列都只是单个元素很好处理,当返回到子序列元素较多时,可以解释下具体的归并算法: 

             

在比较两序列首先考虑越界问题:

        1. i > mid 时,即左边的有序子序列已经遍历完了,若此时有边数组还有值,则一定大于左边序列中任意元素,直接就可以更改原arr数组;

        2. j > r 时,与上述同理。

比较aux[i] 与 aux[j]:将相应小的值赋给arr数组,较小元素下标在更新到下一位置。

                 

  • 最终归并两子序列:

                     

代码展示:

#include <iostream>
#include <algorithm>
#include <string.h>
#include "SortTestHelper.h"

using namespace std;

// 将arr[l~mid] 和 arr[mid+1~r]两部分进行归并
template<typename T>
void __merge(T arr[], int l, int mid, int r){
	
	T *aux = new T[r-l+1];
	for (int i = l; i <= r; i++){
		aux[i-l] = arr[i];
	}

	
	int i = l, j = mid + 1;
	for (int k = l; k <= r; k++){
		// 判断索引是否越界
		if (i > mid){
			arr[k] = aux[j-l];
			j++;
		}
		else if(j > r){
			arr[k] = aux[i-l];
			i++;
		}
		// 分别判断子序列的元素大小
		else if (aux[i-l] < aux[j-l]){
			arr[k] = aux[i-l];
			i++;
		}
		else{
			arr[k] = aux[j-l];
			j++;
		}
	}

	delete[] aux;
}

// 递归实现归并排序
template<typename T>
void __mergeSort(T arr[], int l, int r){

	// 子序列中只有一个元素时,直接返回
	if (l >= r){
		return;
	}
	int mid = (l + r) / 2;
	__mergeSort(arr, l, mid);
	__mergeSort(arr, mid + 1, r);
	__merge(arr, l, mid, r);

}

template<typename T>
void mergeSort(T arr[], int n){

	__mergeSort(arr, 0, n - 1);
}

int main(){
	int n = 10;
	int *arr = SortTestHelper::generateRandomArray2(n);

	SortTestHelper::printArray(arr, n);

	mergeSort(arr, n);
	SortTestHelper::printArray(arr, n);

	delete[] arr;

	return 0;
}

运行结果:  

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值