一 前言
不想写前言,归并排序,我好像搞了一下午,我的妈,我在干啥,我,要命啊。不搞了,不来了,简单做下记录。
只记录两种代码。
- 递归
- 迭代
二 代码
2.0 例子
用归并排序排它。
2.1 迭代
数据元素下标从1开始。下标为0的数据不用。
需要改进成从0开始,等我想了再改吧
A 主调函数
#include <iostream>
#include <stdio.h>
using namespace std;
// 函数声明
void merge_sort(int a[], int n); // 迭代
void merge(int a[], int s1_left, int s1_right, int s2_left, int s2_right); // 合并两段有序序列
void mergePass(int a[], int s, int n); // 合并中间过程,一次调用就是一轮合并
// 归并排序——迭代方法
int main()
{
int a[] = {-1, 50, 10, 100, 30, 70, 40, 80, 60, 20};
int n = 10;
int i;
cout << "Before: " << endl;
for (i=1; i<n; i++)
cout << a[i] << " ";
cout << endl;
// 迭代归并排序
merge_sort(a, n-1);
cout << "After: " << endl;
for (i=1; i<n; i++)
cout << a[i] << " ";
cout << endl;
system("pause");
return 0;
}
B 归并函数
void merge_sort(int a[], int n)
{
int k = 1;
while (k < n)
{
mergePass(a, k, n); // 从1->2->4 ... ->2k逐项合并
k = 2 * k;
}
}
C 两两逐项合并函数
void mergePass(int a[], int s, int n)
{
int i = 1;
while (i <= n-2*s+1) //两两合并
{
merge(a, i, i+s-1, i+s, i+2*s-1); // 从小到大合并两个有序序列
i = i + 2*s;
}
if (i < n-s+1) //合并最后两个序列
merge(a, i, i+s-1, i+s, n);
}
// 将两个有序序列s1 s2合并
// s1_left: s1序列的左边界 s1_right: s1序列的右边界
// s2_left: s1序列的左边界 s2_right: s1序列的右边界
void merge(int a[], int s1_left, int s1_right, int s2_left, int s2_right)
{
int i, j, k; // 三指针
int b[9] = {0}; //合并场地, 初始化下。9为待排数据总长度
// 指针赋初值
i = s1_left; j = s2_left; k = s1_left;
// 当两个序列s1 s2均不满的时候
while ( (i<=s1_right) && (j<=s2_right) )
{
if ( a[i] < a[j])
b[k++] = a[i++];
else
b[k++] = a[j++];
}
// s1未结束
while ( i <= s1_right )
b[k++] = a[i++];
// s2未结束
while ( j <= s2_right )
b[k++] = a[j++];
// 将合并后的有序段移动回源数组a
for (i=s1_left; i<=s2_right; i++)
a[i] = b[i];
}
2.2 递归
递归过程就是这样子,管你看不看的懂,记就完了。
这个下标是从0开始的,没错的。当然你也可以改成从1开始。
A 主调函数
#include <iostream>
#include <stdio.h>
using namespace std;
// 函数声明
void merge(int a[], int s1_left, int s1_right, int s2_left, int s2_right); // 合并两段有序序列
void merge_sort2(int a[], int i, int j); //递归
// 归并排序——递归
int main()
{
int a[] = {50, 10, 90, 30, 70, 40, 80, 60, 20};
int n = 9;
int i;
cout << "Before: " << endl;
for (i=0; i<n; i++)
cout << a[i] << " ";
cout << endl;
merge_sort2(a, 0, n-1);
cout << "After: " << endl;
for (i=0; i<n; i++)
cout << a[i] << " ";
cout << endl;
system("pause");
return 0;
}
B 归并函数
// 递归
// 从0到n-1进行调用: merge_sort2(a, 0, n-1)
void merge_sort2(int a[], int i, int j)
{
int k;
if (i < j) // 每段元素个数大于1; 先拆分递归、再归并退出递归
{
k = (i + j) / 2;
merge_sort2(a, i, k); // 对左段进行排序,s1
merge_sort2(a, k+1, j); // 对右段进行排序,s2
merge(a, i, k, k+1, j); // 合并 s1 s2
}
}
C 两两合并函数
// 将两个有序序列s1 s2合并
// s1_left: s1序列的左边界 s1_right: s1序列的右边界
// s2_left: s1序列的左边界 s2_right: s1序列的右边界
void merge(int a[], int s1_left, int s1_right, int s2_left, int s2_right)
{
int i, j, k; // 三指针
int b[9] = {0}; //合并场地, 初始化下。9为待排数据总长度
// 指针赋初值
i = s1_left; j = s2_left; k = s1_left;
// 当两个序列s1 s2均不满的时候
while ( (i<=s1_right) && (j<=s2_right) )
{
if ( a[i] < a[j])
b[k++] = a[i++];
else
b[k++] = a[j++];
}
// s1未结束
while ( i <= s1_right )
b[k++] = a[i++];
// s2未结束
while ( j <= s2_right )
b[k++] = a[j++];
// 将合并后的有序段移动回源数组a
for (i=s1_left; i<=s2_right; i++)
a[i] = b[i];
}
参考资料
[1] 数据结构 – 中国人民解放军陆军工程大学 –陈卫卫、李清等 – 公开课 – 中国大学MOOC
https://www.icourse163.org/course/PAEU-1001660013#/info
[2] 程杰著.大话数据结构[M].北京:清华大学出版社.2011.