归并排序

来源:互联网 发布:公交大数据 编辑:程序博客网 时间:2024/06/05 17:07

归并排序是一种效率非常高的并且稳定的排序算法,借助临时数组,其平均时间复杂度为O(nlogn)。

类似于快速排序,归并排序也是使用分治法将数组逐步分割成更小的数组进行排序。但快速排序是采用枢纽元将数组的元素分成左右两部分,这是导致不稳定的原因所在。而归并排序则是逐步将两个有序数组合并成一个新的有序数组,对于值相等的元素,它们的相对位置是不会改变的,因此算法是稳定的。

下面通过一个例子来说明归并排序:

原数组:4 6 5 8 7 2 1 3

(1)将原数组分割成两个子数组,分别为4 6 5 8和7 2 1 3

(2)将子数组4 6 5 8进行分割,变成4 6和5 8

(3)将子数组4 6进行分割,变成4和6,将子数组5 8进行分割,变成5和8

(4)将4和6合并成有序数组,即4 6,将5和8合并成有序数组,即5 8

(5)将4 6和5 8合并成有序数组,从两个子数组的数组头开始:4和5较小的数是4,取出4放到临时数组中,然后将第一个子数组的指针往右移一位;6和5较小的数是5,取出5放到临时数组中,然后将第二个子数组的指针往右移一位;6和8较小的数是6,取出6放到临时数组中,然后将第一个子数组的指针往右移一位。此时第一个数组已经到结尾,因此把第二个数组接到临时数组当前指针的后面。最后把临时数组复制回原数组。即4 5 6 8

(6)等同于(2)~(5),将7 2 1 3进行排序,变成1 2 3 7

(7)对两个有序的子数组4 5 6 8和1 2 3 7按第(5)步的方式进行合并,得到最终的有序数组1 2 3 4 5 6 7 8

#include <iostream>#include <cstdio>using namespace std;const int N = 100005;//数组大小int num[N];int temp[N];int n;//归并成有序数组void merge(int low, int mid, int high){int i = low;//左半部分当前位置int j = mid + 1;//右半部分当前位置int k = low;//结果数组当前位置while (i <= mid && j <= high)// 归并,每次找两边数组当前元素的较小者加入结果数组中{if (num[i] <= num[j]) temp[k++] = num[i++];else temp[k++] = num[j++];}while (i <= mid) temp[k++] = num[i++];//把左半部分数组剩余部分加入结果数组while (j <= high) temp[k++] = num[j++];//把右半部分数组剩余部分加入结果数组for (i = low; i <= high; ++i) num[i] = temp[i];//从结果数组中把元素复制回原数组}//递归地进行归并排序void mergeSort(int beg, int end){if (beg < end)//两个端点不重合{int mid = (beg + end) / 2;//获取中点mergeSort(beg, mid);//对左半部分进行排序mergeSort(mid + 1, end);//对右半部分进行排序merge(beg, mid, end);//合并左右两部分}}int main(){scanf("%d", &n);for (int i = 0; i < n; ++i){scanf("%d", num + i);}mergeSort(0, n - 1);for (int i = 0; i < n; ++i){printf("%d ", num[i]);}printf("\n");return 0;}


原创粉丝点击