归并排序
算法复杂度:
最好情况:O(nlogn)
最坏情况:O(nlogn)
平均情况:O(nlogn)
空间复杂度:O(n)
缺点:需要另开一个等大数组,消耗空间
思路
3 1 5 4 2
拆分成3 1 5 和 4 2 两部分
再分为3 1 和 5 以及 4 和 2
继而比较前半部分为1 3 5,后半部分为2 4
定义两个指针指向这两部分,p1和p2,往后移动,比较当前所指元素大小。
C++代码:
#include <iostream>
using namespace std;
int a[1000], b[1000];
void Merge(int *a, int *b, int begin, int mid, int end) {
int pb = 0;
int p1 = begin, p2 = mid + 1;
while (p1 <= mid && p2 <= end) {
if (a[p1] <= a[p2])
b[pb++] = a[p1++];
else
b[pb++] = a[p2++];
}
while (p1 <= mid)
b[pb++] = a[p1++];
while (p2 <= end)
b[pb++] = a[p2++];
for (int i = 0; i < end - begin + 1; ++i) {
a[begin + i] = b[i];
}
}
void Merge_Sort(int *a, int *b, int begin, int end) {
if (begin < end) {
int mid = begin + (end - begin) / 2;
Merge_Sort(a, b, begin, mid);
Merge_Sort(a, b, mid + 1, end);
Merge(a, b, begin, mid, end);
}
}
int main() {
ios::sync_with_stdio(false);
int n, k = 0;
cout<<"输入你要排序的数字:";
while (cin >> n) {
a[k++] = n;
if (cin.get() == '\n') //cin输入吃到了回车就不继续读入了
break;
}
cout << k << "位" << endl;
Merge_Sort(a, b, 0, k - 1);
for (int i = 0; i < k; ++i) {
cout << a[i]<<" ";
}
return 0;
}
Java代码
public static void MergeSort(int[] nums, int left, int right, int[] temp) {
if (left == right)
return;
int mid = (left + right) / 2;
MergeSort(nums, left, mid, temp);
MergeSort(nums, mid + 1, right, temp);
Merge(nums, left, mid, right, temp);
}
public static void Merge(int[] nums, int left, int mid, int right, int[] temp) {
int l = left; // 左边序列的第一个元素
int r = mid + 1; // 右边序列的第一个元素
int t = 0; // temp数组的下标
while (l <= mid && r <= right) {
if (nums[l] <= nums[r]) {
temp[t++] = nums[l++];
} else {
temp[t++] = nums[r++];
}
}
// 排完一轮,发现还有没加进去的,就顺序加入
while (l <= mid) {
temp[t++] = nums[l++];
}
while (r <= right) {
temp[t++] = nums[r++];
}
// 现在是temp是顺序的,覆盖写入nums数组
int tempLeft = left;
t = 0; // 重置下标
while (tempLeft <= right) {
nums[tempLeft++] = temp[t++];
}
}