排序算法练习-归并排序

介绍

归并排序是一种时间复杂度为O(n log n)级别的排序算法,并且是一种稳定的排序算法。因为它划分出的每一部分在空间上都是大小相同的。下面用C++实现了一个基本的归并排序算法,并对其进行优化改进。

具体思路

  • 将需要排序的数组arr[l…r]一分为二,并设定一个中间位置索引mid,直到每组元素只有一个元素。
  • 开辟一个临时数组temp[0…r-l],复制当前需要排序的数组arr[l…r]。
  • 分别对temp[0…mid-l]和temp[mid-l+1…r-l]的首元素比较,符合排序要求覆盖到arr,直到所有temp中的元素都重新覆盖原来到arr数组。

代码实现

#include<bits/stdc++.h>
using namespace std;

template<class T>
void _merge(T arr[], int l, int mid, int r) {
    //开辟一个临时数组用于存放归并后的元素
    T* temp = new T[r-l+1];
    for(int i = l; i <= r; i++) {
        temp[i-l] = arr[i];
    }
    int i = l;
    int j = mid+1;
    for(int k = l; k <= r; k++) {
        //当左边元素都已排好
        if(i > mid) {
            arr[k] = temp[j-l];
            j++;
        }
        //当右边元素都排好
        else if(j > r) {
            arr[k] = temp[i-l];
            i++;
        }
        //左边元素较小时
        else if(temp[i-l] < temp[j-l]) {
            arr[k] = temp[i-l];
            i++;
        }
        else {
            arr[k] = temp[j-l];
            j++;
        }
    }
    return;
}

//对arr[l...r]排序
template<class T>
void _mergeSort(T arr[], int l, int r) {

    //退出条件
    if(l >= r) {
        return;
    }
    //将数组元素一分为二
    int mid = l + (r-l)/2;

    //分别对左右部分归类
    _mergeSort(arr, l, mid);
    _mergeSort(arr, mid+1, r);
    
    //之后合并
    //如果右边第一个元素比左边最后一个元素大就不需要归并了
    if(arr[mid] > arr[mid+1])
    	_merge(arr, l, mid, r);
}

template<class T>
void mergeSort(T arr[], int n) {
    //对数组arr[0...n-1]排序
    _mergeSort(arr, 0, n-1);
}

int main(int argc, char const *argv[])
{
    //测试
    int arr[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    mergeSort(arr, 10);
    for(int i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

自底向上的归并排序

#include<bits/stdc++.h>
using namespace std;

template<class T>
void _merge(T arr[], int l, int mid, int r) {
    //开辟一个临时数组用于存放归并后的元素
    T* temp = new T[r-l+1];
    for(int i = l; i <= r; i++) {
        temp[i-l] = arr[i];
    }
    int i = l;
    int j = mid+1;
    for(int k = l; k <= r; k++) {
        //当左边元素都已排好
        if(i > mid) {
            arr[k] = temp[j-l];
            j++;
        }
        //当右边元素都排好
        else if(j > r) {
            arr[k] = temp[i-l];
            i++;
        }
        //左边元素较小时
        else if(temp[i-l] < temp[j-l]) {
            arr[k] = temp[i-l];
            i++;
        }
        else {
            arr[k] = temp[j-l];
            j++;
        }
    }
    return;
}

//自底向上的归并排序
template<class T>
void mergeSortBtoU(T arr[], int n) {
	//l = i, mid = sz - 1, r = i + sz + sz - 1
	for(int sz = 1; sz < n; sz += sz) {
	    for(int i = 0; i + sz < n; i += sz + sz) {
	        if(arr[i+sz-1] > arr[i+sz]) {
	            _merge(arr, i, i+sz-1, min(i+sz+sz-1, n-1));
	        }
	    }
	}
}

int main(int argc, char const *argv[])
{
    // 测试
    int arr[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    mergeSortBtoU(arr, 10);
    for(int i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

最后

  • 由于博主水平有限,难免有疏漏之处,欢迎读者批评指正!
发布了5 篇原创文章 · 获赞 4 · 访问量 152

猜你喜欢

转载自blog.csdn.net/weixin_43587255/article/details/105485916