本次介绍与快速排序有着同样同样时间复杂度NlgN的合并排序
(我会慢慢介绍更多的,另外本程序在dev, vc等编译器下均可运行成功 !)
合并排序(归并排序):采用分治的思想,将数组(Array)划分为两个子数组(left和right),然后递归(MergeSort)的将每个子数组再进行划分,直到数组中只剩一下一个元素,然后开始排序合并(Merge),直到将所有的子数组合并完成,整个数据就是有序的了。
时间复杂度:将数组分成的子数组 用二叉树表示,假设共有n层,第k层共有2的K次方个子数组,每个子数组的长度是2的n-k次方 所以每一层的比较次数是2的n次方,n层就是n*2的n次方次比较,n=logN 所以 时间复杂度就是NlgN
空间复杂度:因为有3个临时数组:left, right, Array, 故为N
注:相信编程的同学应该都清楚,语言表述和实际编程还是有很大的出入的,故本文章重在能让人理解程序。
主函数:主函数中只要有输入的个数和输入要排序的值和最后排序后的值即可,没什么可说的,如何完成排序交给其他函数。
int main(int argc, char** argv){
//数据的初始化
int n;
cin>>n;
int Array[n];
//输入数据
for(int i = 0; i < n; i++)
cin>>Array[i];
MergeSort(Array, 0, n); //数组排序
//输出排序后的结果
for(int i = 0; i < n; i++)
cout<
MergeSort函数:将所输入的值分成2部分,每部分再次划分,最后划分至只剩单个元素,再进行排序合并(程序角度:分成begin和middle和end,分成2部分进行迭代,直至单个元素,再到merge里面进行排序)
//将数组元素分成单个元素进行处理
void MergeSort(int Array[], int begin, int end){
//这里和两链表的合并很像,也复习了数据结构链表这一节
if(begin + 1 < end){ //保证只有一个值的时候退出,防止多余计算,
int middle = (end + begin) / 2; //这里可以想想int关于奇数和偶数的除法运算,但是仔细想想都不影响结果
MergeSort(Array, begin, middle);
MergeSort(Array, middle, end);
Merge(Array, begin, middle, end); //如何排序交给Merge函数即可
}
}
Merge函数:对元素排序(程序角度,每单个元素可看成是排好序的,最后一起比较赋值即可)
void Merge(int Array[], int begin, int middle, int end){
int n1 = middle - begin;
int n2 = end - middle;
//动态申请内存空间大小,使其能存储正好足够的数据
int *left = new int[n1];
int *right = new int[n2];
/*注意:left,right 在不断迭代过程中已经排好序了,在后面只需要比较,赋值给Array就可以了,最后总体赋值,因为单个元素满足不了begin==end*/
//数组两边的数赋值到动态数组内
for(int i = 0; i < n1; i++)
left[i] = Array[begin + i]; //从begin开始赋值,因为
for(int i = 0; i < n2; i++)
right[i] = Array[middle + i]; //从middle开始赋值
//最初的数组赋值进行归并排序
int i = 0, j = 0, key;
for(key = begin; key < end; key++){
if(i < n1 && left[i] <= right[j])
Array[key] = left[i++];
else if(j < n2 && left[i] >= right[j])
Array[key] = right[j++];
else if(i == n1 && j < n2){ //万一left赋值完了,right还有很多呢?此语句即可解决这个问题
Array[key] = right[j++];
}
else if(j == n2 && i < n1){ //同上
Array[key] = left[i++];
}
}
}
个人感觉难点: 1>对于迭代的理解:是将数组分成多个元素,最后就是排好序的,再不断赋值给left,right就可以了,最后比较排序即可
2>对于比较的理解:这里涉及一些数据结构链表合并的知识,个人建议多想,多敲就好,实在不行,记下了,毕竟是个排序工具
最后附上所有代码,因为在dev上面写的,注释乱码了,希望别介意,这也是希望大家多看分解函数,新手上路,希望见谅,大吉大利,今晚吃鸡!
#include
using namespace std;
void Merge(int Array[], int begin, int middle, int end){
int n1 = middle - begin;
int n2 = end - middle;
int *left = new int[n1];
int *right = new int[n2];
for(int i = 0; i < n1; i++)
left[i] = Array[begin + i];
for(int i = 0; i < n2; i++)
right[i] = Array[middle + i];
int i = 0, j = 0, key;
for(key = begin; key < end; key++){
if(i < n1 && left[i] <= right[j])
Array[key] = left[i++];
else if(j < n2 && left[i] >= right[j])
Array[key] = right[j++];
else if(i == n1 && j < n2){
Array[key] = right[j++];
}
else if(j == n2 && i < n1){
Array[key] = left[i++];
}
}
}
void MergeSort(int Array[], int begin, int end){
if(begin + 1 < end){
int middle = (end + begin) / 2;
MergeSort(Array, begin, middle);
MergeSort(Array, middle, end);
Merge(Array, begin, middle, end);
}
}
int main(int argc, char** argv){
int n;
cin>>n;
int Array[n];
for(int i = 0; i < n; i++)
cin>>Array[i];
MergeSort(Array, 0, n);
for(int i = 0; i < n; i++)
cout<