返回顶部

归并排序

来说说归并排序是啥?归并排序就是排序呗。啥,啥排序?归并呗。

哔bibibi(瞎哔哔)

好吧,归并排序,是创建在归并操作上的一种有效的排序算法,效率为O(nlogn)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分

治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。速度仅次于快速排序,为稳定排序算法,一般用

于对总体无序,但是各子项相对有序的数列,归并排序的比较次数小于快速排序的比较次数,移动次数一般多于快速排序的移动次数。

算法思想

该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶

段则将分的阶段得到的各答案"修补"在一起,即分而治之)。既然归并排序采用的是分治法,并且依托于归并操作,那么其思想肯定是分

而治之。我们知道归并操作是将两个有序的数列合并到一个有序的序列,那么对于一个无序的长序列,可以把它分解为若干个有序的子

序列,然后依次进行归并。如果我们说每一个数字都是单独有序的序列,那么只要把原始长序列依次分解,直到每个子序列都只有一个

元素的时候,再依次把所有的序列进行归并,直到序列数为1

alt 单向链表

综上可知:

归并排序其实要做两件事:

(1)“分解”——将序列每次折半划分。
(2)“合并”——将划分后的序列段两两合并后排序。

算法步骤

(1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

(2)设定两个指针,最初位置分别为两个已经排序序列的起始位置;

(3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

(4)重复步骤 3 直到某一指针达到序列尾;

(5)将另一序列剩下的所有元素直接复制到合并序列尾。

话不多说,上代码

#include <iostream>
#include <cstring >
#include <cstdio>
#include <cmath>
using namespace std;
//归并过程
void merge(int arr[], int l, int mid, int r){
	int help[r-l+1];//辅助数组
	int i = 0;
	int lIndex = l;
	int rIndex = mid+1;
	while(lIndex <= mid && rIndex <= r){
		help[i++] = arr[lIndex] < arr[rIndex] ? arr[lIndex++]:arr[rIndex++];
	}
    //左边和右边肯定有一边到头了,不可能同时,因为每次只移动一边
	while(lIndex <= mid){
		help[i++] = arr[lIndex++];
	}
	while(rIndex <= r){
		help[i++] = arr[rIndex++];
	}
    //将排好序的辅助数组赋值给原始数组,不需要返回值
	for(i = 0; i < r-l+1; i++){
		arr[l+i] = help[i];
	}
}

//递归
static void msort(int arr[], int l, int r){
	if(l == r){
		return;
	}
	int mid = (l + r) / 2;
    //左半部分归并排序
	msort(arr, l, mid);
    //右半部分归并排序
	msort(arr, mid+1, r);
    //左右部分归并
	merge(arr, l, mid, r);
}

//归并排序整个数组
 void msort(int arr[], int n){
    //如果数组为空或只有一个元素,不需要排序
	if(arr == NULL || n < 2){
		return;
	}
	msort(arr,0,n-1);
}

int main(){
    int arry[100];
    int n;
    cin>>n;
    for(int i=0; i<n; i++)
        cin>>arry[i];
    msort(arry, n);
    for(int i=0; i<n; i++)
        cout<<arry[i]<<" ";
    return 0;
}

posted @ 2020-10-16 19:31  Shamero  阅读(89)  评论(0)    收藏  举报