排序算法之——二路归并排序
二路归并排序的思想:
一次排序过程,将已经各自有序的两个段的数据合并一个段,并且合并后依旧有序
开始,我们认为单个数据是有序的,一个数据就是一个段,一次排序之后,两个数据就是一个有序数据段,这样下一次每个数据段就是两个数据。最后将其合并成一个完成有序段,则整个数据就已经排序好了
时间复杂度:
O(nlog(n))
空间复杂度:
O(n)
稳定性:
稳定
代码实现:
void Meger(int* arr, int len, int width, int *brr)
{
int low1 = 0;
int high1 = low1 + width - 1; //high1为第一个段的结束位置下标
int low2 = high1 + 1;
int high2 = low2 + width > len ? len - 1 : low2 + width - 1;
int index = 0;
//处理有两个归并段
while(low2 < len)
{
//有两个归并段都有未归并数据
while (low1 <= high1 && low2 <= high2)
{
if (arr[low1] < arr[low2])
{
brr[index++] = arr[low1++];
}
else brr[index++] = arr[low2++];
}
//只剩下一个归并段
while (low1 <= high1) brr[index++] = arr[low1++];
while (low2 <= high2) brr[index++] = arr[low2++];
low1 = high2 + 1;
high1 = low1 + width - 1;
low2 = high1 + 1;
high2 = low2 + width > len ? len - 1 : low2 + width - 1;
}
//处理只剩下一个归并段的情况
while (low1 < len)
{
brr[index++] = arr[low1++];
}
//将brr中的数据全部复制到arr中
for (int i = 0; i < len;i++)
{
arr[i] = brr[i];
}
}
void MegerSort(int* arr, int len)
{
int* brr = (int*)malloc(sizeof(int) * len);
assert(brr != NULL);
//i是每个段当前的数据个数
for (int i = 1; i < len; i *= 2)
{
Meger(arr, len, i,brr);
}
free(brr);
}
C++递归版
#include<iostream>
#include<vector>
using namespace std;
void merge(vector<int>& arr, int left, int mid, int right)
{
vector<int> help(right - left + 1);
int i = 0;
int p1 = left;
int p2 = mid + 1;
//将数组分成两端后,取两端中小的放入新数组
while (p1 <= mid && p2 <= right)
{
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= mid)
{
help[i++] = arr[p1++];
}
while (p2 <= right)
{
help[i++] = arr[p2++];
}
for (i = 0; i < help.size(); i++)
{
arr[left + i] = help[i];
}
}
void mergeSort(vector<int>& arr, int left, int right)
{
if (left == right)
{
return;
}
int mid = left + ((right - left) >> 1);
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
void mergeSort(vector<int>& arr)
{
if (arr.empty() || arr.size() < 2) return;
mergeSort(arr, 0, arr.size() - 1);
}
int main()
{
vector<int> arr = { 16,123,89,23,56,34,10,56,45,78,56 };
mergeSort(arr);
for (auto x : arr)
{
cout << x << " ";
}
cout << endl;
return 0;
}