数据结构算法学习总结-慕课网(六)归并排序(从小到大)
1.回顾
上一节讲到冒泡排序,对它有了基本的认识
这一节会讲性能比较好的归并排序
2.思路
如图
首先会创建一个与原{2,3,6,8}一模一样的数组tempArray,比较i和j所在的元素,可以知道2比6小,那么2就是我们要找的第一个元素,随后i角标移动到下一个位置,即3所在的位置,然后把2赋给k所在的数组的第一个元素,k角标往后移动一位,现在第一个元素排序完毕;i移动到角标为1的位置3,现在比较3和6,发现3比6小,那么3就是我们要找的元素,把3赋值给k的第二个位置,即3所在的位置,随后i角标加1;这时候的i=1,和mid=1相等啦,则对j所在的部分进行排序,往后类似。
3.实战
MergeSort.cpp
#include <iostream>
#include "SortTestHelper.h"
using namespace std;
/**
* 将[l...mid]和[mid+1...r]两部分进行归并
*/
template<typename T>
void __merge(T arr[],int l,int mid,int r){
//临时空间,存贮arr的数组
T aux[r-l+1];
for(int i = l;i<=r;i++)
aux[i-l]=arr[i];
int i = l,j=mid+1;
for(int k = l;k<=r;k++){
//i>mid表示i所在数组已经归并完,j所在的数组没有归并完,还需要归并一次
if(i > mid){
arr[k] = aux[j-l];
j++;
}else if(j > r){//j>r表示j所在数组已经归并完,i所在的数组没有归并完,还需要归并一次
arr[k] = aux[i-l];
i++;
}else if(aux[i-l]<aux[j-l]){
arr[k] = aux[i-l];
i++;
}else{
arr[k] = aux[j-l];
j++;
}
}
}
/**
* 递归使用归并排序,对arr[l...r]的范围排序
*/
template<typename T>
void __mergeSort(T arr[],int l,int r){
if(l >= r)
return;
int mid = (l+r)/2;
__mergeSort(arr,l,mid);
__mergeSort(arr,mid+1,r);
__merge(arr,l,mid,r);
}
template<typename T>
void mergeSort(T arr[],int n){
__mergeSort(arr,0,n-1);
}
int main(){
int n = 100000;
int* arr = SortTestHelper::generateRandomArray(n,0,100);
SortTestHelper::testSort("Merge Sort:",mergeSort,arr,n);
delete[] arr;
return 0;
}
SortTestHelper.h
#ifndef SORTTESTHELPER_H_
#define SORTTESTHELPER_H_
#include <iostream>
#include <ctime>
#include <cassert>
using namespace std;
namespace SortTestHelper{
//生成n个元素的随机数组,每个元素的随机范围为[rangeL,rangeR]
int* generateRandomArray(int n,int rangeL,int rangeR){
assert(rangeL <= rangeR); //为了程序稳定性,如果rangeL>rangeR,那么程序不会往下执行
int *arr = new int[n];
srand(time(NULL));//随机种子,需要导入ctime库
for(int i = 0;i<n;i++){
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL; //自己可以动笔算一下
}
return arr;
}
/**
* 检验排序的正确性
*/
template<typename T>
bool isSorted(T arr[],int n){
for(int i = 0;i<n;i++){
//注意,如果i=n-2时,实际上会比较arr[n-2]和arr[n-1]的值,此时数组已经比较完毕
if(i<n-1 && arr[i]>arr[i+1]){
return false;
}
}
return true;
}
/**
* 测试排序所需要的时间
*/
template<typename T>
void testSort(string sortName,void(*sort)(T arr[],int n),T arr[],int n){
clock_t startTime = clock();
sort(arr,n);
clock_t endTime = clock();
assert(isSorted(arr,n));
cout <<sortName<<" : "<< double(endTime - startTime) /CLOCKS_PER_SEC <<"s" << endl;
return;
}
template<typename T>
void printArray(T arr[],int n){
for(int i = 0;i<n;i++)
cout << arr[i] << ","; //循环打印数组中的元素
cout << endl;
}
int* copyArray(int arr[],int n){
int* b = new int[n];
//拷贝数组参数:指针开始的位置;指针结束的位置;目标数组
copy(arr,arr+n,b);
return b;
}
/**
*生成一个近乎有序的数组
*/
int* generateNearlyOrderedArray(int n,int swapTimes){
int* arr = new int[n];
for(int i = 0;i<n;i++)
arr[i] = i;
srand(time(NULL));
for(int i = 0;i<swapTimes;i++){
int swapX = rand()%n;
int swapY = rand()%n;
swap(arr[swapX],arr[swapY]);
}
return arr;
}
}
#endif /* SORTTESTHELPER_H_ */
运行结果
Merge Sort: : 0.019s
总结
从运行的结果可以得知,即使是10w的测试数据量,归并排序所需要的时间依然很短,性能很高
意见与建议
如果博友有任何问题或者建议,欢迎留言讨论