归并排序

本文分享了作者在学习算法设计与分析课程过程中实现的归并排序代码,并提供了两种不同方案的对比测试结果。通过具体的数据展示算法效率。

这是我在优快云上面写的第一个博客,源于我写了一点点小程序。我想把它发到这里分享给大家,就像我一直在优快云上找别人的资源一样。这一系列分类叫算法设计与分析,是因为这是我的一门专业课的名字,而且我买到了一本好书《算法导论》。我把上面许多作者给出的伪代码和一些习题都用C++标准写出来,也希望我能坚持到把这本书做个50%(由于时间有限,课程非常紧,而且教学内容并不是一本书中的所有内容)。我习惯于不写注释,除非在比较难懂的结构中才会表明总体思路和个别变量的意义。虽然说,这一系列的程序中有一部分是对伪代码的翻译,另一部分是课后习题,不过每一份程序都是我完成的,所以也是由原创权利的,转载或使用请表明出处。

由于我是在VS2015编译器中写的,所以我也不能保证它在所有编译器上都可用,不过至少,我没有类似scanf_s等微软提供的“安全”函数,遇到这种函数,我都会想办法避开它们;我使用的主要是C++11标准,像DEV_C++可能不包含其中的一些头文件。

在吹过一阵牛逼之后,这次博客的主题归并排序的代码实现。其实归并排序没什么好说的,是一个比较好用的O(nlogn)的排序算法。我在测试数据的时候,发现对100个int型数据排序用了不到0ns的时间,对1000个int排序用了1000100ns的时间,对10000个int排序用了10000600ns的时间。从1000到10000是基本满足O(nlogn)规律的,但是100个int用时为0我也看不太懂。。。程序中有两个实现的方案,第一个是使用哨兵的归并,第二个没有用哨兵,然而两种方案的用时是几乎相同的。

需要直接的.h程序,可以下载下面的文件"Sort.h"(说明一下为什么只有.h没有.cpp,使用template泛型编程时声明和定义不能放在不同的文件中,不然编译会报错;同时引用.h和.cpp文件是更蠢的选择)。


#pragma once


#include <fstream>
#include <iostream>
#include <random>
#include <limits>
#include <chrono>
using namespace std;


namespace my
{
template <typename T>
void MergeSort(T* A, int p, int r)
{
if (p < r)
{
int q = (p + r) / 2;
MergeSort(A, p, q);
MergeSort(A, q + 1, r);
Merge(A, p, q, r);
}
}
template <typename T>
void MergeSort(T* A, int siz)
{
MergeSort<T>(A, 0, siz - 1);
}
template <typename T>
void Merge(T* A, int p, int q, int r)
{
int n1 = q - p + 1, n2 = r - q;
T *L = new T[n1 + 1], *R = new T[n2 + 1];
for (int i = 0; i < n1; i++) L[i] = A[p + i];
for (int i = 0; i < n2; i++) R[i] = A[q + i + 1];
L[n1] = numeric_limits<T>::max();
R[n2] = numeric_limits<T>::max();
int i = 0, j = 0;
for (int k = p; k <= r; k++) 
if (L[i] < R[j]) A[k] = L[i++];
else A[k] = R[j++];
delete[] L, R;
}


template <typename T>
void MergeSortWithoutSoilder(T* A, int p, int r)
{
if (p < r)
{
int q = (p + r) / 2;
MergeSortWithoutSoilder(A, p, q);
MergeSortWithoutSoilder(A, q + 1, r);
MergeWithoutSoilder(A, p, q, r);
}
}
template <typename T>
void MergeSortWithoutSoilder(T* A, int siz)
{
MergeSortWithoutSoilder<T>(A, 0, siz - 1);
}
template <typename T>
void MergeWithoutSoilder(T* A, int p, int q, int r)
{
int n1 = q - p + 1, n2 = r - q;
T *L = new T[n1], *R = new T[n2];
for (int i = 0; i < n1; i++) L[i] = A[p + i];
for (int i = 0; i < n2; i++) R[i] = A[q + i + 1];
int i = 0, j = 0, lnum = 0, rnum = 0;
for (int k = p; k <= r; k++)
{
if (i == n1 && j != n2)
{
while (j != n2) A[k++] = R[j++];
break;
}
if (i != n1 && j == n2)
{
while (i != n1) A[k++] = L[i++];
break;
}
if (L[i] < R[j]) A[k] = L[i++];
else A[k] = R[j++];
}
delete[] L, R;
}


void MergeSortTest(int num = 10000)
{
int *randomnum = new int[num];
random_device rd;
for (int i = 0; i < num; i++) randomnum[i] = rd() % (num*10);
ofstream fout("out_MergeSort.txt");
for (int i = 0; i < num; i++) fout << randomnum[i] << "\t";
auto start = chrono::system_clock::now();
MergeSort<int>(randomnum, 0, num-1);
auto diff = chrono::system_clock::now() - start;
fout << endl << "Time used by MergeSort for " << num << " elements (type int) is " 
<< chrono::duration_cast<chrono::nanoseconds>(diff).count() << " nanoseconds." << endl;
cout << "Time used by MergeSort for " << num << " elements (type int) is "
<< chrono::duration_cast<chrono::nanoseconds>(diff).count() << " nanoseconds." << endl;
for (int i = 0; i < num; i++) fout << randomnum[i] << "\t";
fout << endl;
fout.close();
delete[] randomnum;
getchar();
}
void MergeCompareTest(int num = 1000)
{
int *ran1 = new int[num], *ran2 = new int[num];
random_device rd;
for (int i = 0; i < num; i++)
{
ran1[i] = rd() % (num * 10);
ran2[i] = ran1[i];
}
ofstream fout("out_MergeCompare.txt");
for (int i = 0; i < num; i++) fout << ran1[i] << "\t";
fout << endl;
auto start = chrono::system_clock::now();
MergeSort<int>(ran1, 0, num - 1);
auto diff = chrono::system_clock::now() - start;
fout << "Time used by MergeSort with soilder for " << num << " elements (type int) is "
<< chrono::duration_cast<chrono::nanoseconds>(diff).count() << " nanoseconds." << endl;
for (int i = 0; i < num; i++) fout << ran1[i] << "\t";
fout << endl;
start = chrono::system_clock::now();
MergeSortWithoutSoilder(ran2, 0, num - 1);
diff = chrono::system_clock::now() - start;
fout << "Time used by MergeSort without soilder for " << num << " elements (type int) is "
<< chrono::duration_cast<chrono::nanoseconds>(diff).count() << " nanoseconds." << endl;
for (int i = 0; i < num; i++) fout << ran2[i] << "\t";
fout << endl;
fout.close();
delete[] ran1, ran2;
getchar();
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值