关于C++各类排序算法与std::sort性能的比较

原创 2015年11月21日 14:26:59

talk is cheap.直接放代码(C++)。
先定义一个计时的类。
class Time_count//时间计时类,需要#include< ctime>
{
private:
clock_t start_,end_;
double duration;//记录时间
public:
Time_count()
{
start_=clock();
}
void show_time()
{
end_=clock();
duration = (double)(end_-start_)/CLOCKS_PER_SEC;
cout< < “spend time “< < duration< < ” seconds”< < endl< < endl;
}
};
然后,计时的时候,实例化一个Time_count类,再通过show_time()成员函数获得时间。这里不细讲。

define LENGTH 10000//排序长度为10000的数组

注意 如果想改变数组长度,只需改变LENGTH大小即可。
开头就这么定义:
int a[LENGTH+10];
srand(time(NULL));
for(int i=0;i< LENGTH;i++)
{
a[i]=rand()%10000+1;//随机生成1-10000之间的数字填充进数组
}
然后是驱动函数部分:
/*1.以下为插入排序/
Time_count t1;
insertion_sort(a);
cout< < “1.after insertion sort:”< < endl;
t1.show_time();
//print(a);
/*2.以下为冒泡排序/
Time_count t2;
bubble_sort(a);
cout< < “2.after bubble sort:”< < endl;
t2.show_time();
//print(a);
/*3.以下为选择排序/
Time_count t3;
selection_sort(a);
cout< < “3.after selection sort:”< < endl;
t3.show_time();
//print(a);
/*4.以下为归并排序/
Time_count t4;
merge_sort(a,0,LENGTH-1);
cout< < “4.after merge sort:”< < endl;
t4.show_time();
//print(a);
/*5.以下为快速排序/
Time_count t5;
quick_sort(a,0,LENGTH-1);
cout< < “5.after quick sort:”< < endl;
t5.show_time();
//print(a);
/*6.以下为STLsort排序/
Time_count t6;
STLsort(a);
cout< < “6.after STLsort:”< < endl;
t6.show_time();
//print(a);
system(“pause”);
注意:我这个程序一共要比较5种不同的排序算法,以及标准库sort(定义在头文件algorithm里)的算法之间的效率。
冒泡,选择不罗嗦。重点是插入,归并,快排。
插入排序(insertion sort):算法导论2.1(P17)有详细的说明,而在6(P84),7(P95),8(P107)章中重点对堆排序,快排做了说明。
这些具体的算法抽出时间我再去整理一下。这里就直接贴代码。
//插入排序
void insertion_sort(int *a)
{
int key;
int i,j;
for(j=1;j< LENGTH;j++)
{
key=a[j];
i=j-1;
while(i>0&&a[i]>key)
{
a[i+1]=a[i];
i–;
}
a[i+1]=key;
}
}
//归并排序(注意!last应为a数组长度-1)
void merge_sort(int *a,int first,int last)
{
if (first< last)
{
int mid = (first + last) / 2;
merge_sort(a, first, mid); //左边有序
merge_sort(a, mid + 1, last); //右边有序
//再将二个有序数列合并
int i = first, j = mid + 1;
int m = mid, n = last;
int k = 0;
int *temp;
if((temp=(int*)malloc(LENGTH*sizeof(int)))==0)
{
cout< < “fuck you”< < endl;
exit(1);
}
while (i < = m && j < = n)
{
if (a[i] < = a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while (i < = m)
{
temp[k++] = a[i++];
}
while (j < = n)
{
temp[k++] = a[j++];
}
for (i = 0; i < k; i++)
{
a[first + i] = temp[i];
}
}
}

//快速排序
void quick_sort(int *a, int l, int r)
{
if (l < r)
{//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
int i = l, j = r, x = a[l];
while (i < j)
{
while(i < j && a[j] >= x) // 从右向左找第一个小于x的数
{
j–;
}
if(i < j)
a[i++] = a[j];
while(i < j && a[i] < x) // 从左向右找第一个大于等于x的数
{
i++;
}
if(i < j)
a[j–] = a[i];
}
a[i] = x;
quick_sort(a, l, i - 1); // 递归调用
quick_sort(a, i + 1, r);
}
}

最后,打印结果:
这里写图片描述
惊讶的发现,快排没那么快(其实原因是快排还有很多改进版本,如随机选择基准数,区间内数据较少时直接用另的方法排序以减小递归深度,而本程序使用的快排却并不是最好的。这里不做过多的讨论)。本地图片,请重新上传而STL的sort函数却相当的快。
那么,如果加大LENGTH的长度呢?比如,#define LENGTH 50000 会怎么样呢?
试试看
这里写图片描述
啊哈,调用merge_sort的时候 因为要开过多的空间,导致栈溢出了。
因为quick_sort也是通过空间换时间的算法,所以递归调用时同样会导致栈溢出。
那么,把merge和quick注释掉,看看结果:
这里写图片描述
STL的sort函数还是傲视群雄。根本没用多少时间。
为什么标准库的排序函数会这么快?
我们进algorithm标准库看看吧

我们可以看到很多乱七八糟的C++代码。从这个STL函数来看,重载了两个版本的sort函数,第一个接收三个参数,第二个接收两个。因为定义的是模板,因此参数无论传入指针,还是迭代器都是没问题的。第三个参数可以使用一个比较函数,bool cmp(T &a,T &b);之类的,也可以用funtional标准库中的equal_to< Type>、not_equal_to< Type>、greater< Type>、greater_equal< Type>、less< Type>、less_equal< Type>等等进行大小比较,甚至还可以利用C++11的feature自己写个lambda表达式。当然这里不赘述。主要看sort函数的实现原理。
继续f12,跳。

template< class _RanIt,
class _Diff,
class _Pr> inline
void _Sort(_RanIt _First, _RanIt _Last, _Diff _Ideal, _Pr _Pred)
{ // order [_First, _Last), using _Pred
_Diff _Count;
for (; _ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal; )
{ // divide and conquer by quicksort
pair< _RanIt, _RanIt> _Mid =
_Unguarded_partition(_First, _Last, _Pred);
_Ideal /= 2, _Ideal += _Ideal / 2; // allow 1.5 log2(N) divisions

    if (_Mid.first - _First <  _Last - _Mid.second)
        {   // loop on second half
        _Sort(_First, _Mid.first, _Ideal, _Pred);
        _First = _Mid.second;
        }
    else
        {   // loop on first half
        _Sort(_Mid.second, _Last, _Ideal, _Pred);
        _Last = _Mid.first;
        }
    }

if (_ISORT_MAX <  _Count)
    {   // heap sort if too many divisions
    _STD make_heap(_First, _Last, _Pred);
    _STD sort_heap(_First, _Last, _Pred);
    }
else if (2 < = _Count)
    _Insertion_sort(_First, _Last, _Pred);  // small
}

template< class _RanIt,
class _Pr> inline
void sort(_RanIt _First, _RanIt _Last, _Pr _Pred)
{ // order [_First, _Last), using _Pred
_DEBUG_RANGE(_First, _Last);
_DEBUG_POINTER_IF(2 < = _Last - _First, _Pred);
_Sort(_Unchecked(_First), _Unchecked(_Last), _Last - _First, _Pred);
}

    // TEMPLATE FUNCTION sort

template< class _RanIt> inline
void sort(_RanIt _First, _RanIt _Last)
{ // order [_First, _Last), using operator<
_STD sort(_First, _Last, less< >());
}

其实STL的sort函数在数据量大时采用快排,分段递归排序,一旦分段后的数据小于某个值,就改用插入排序。如果递归层次过深,还会改用堆排序。这样就结合了各类算法的所有优点。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

[C/C++标准库]_[初级]_[使用std::sort排序各种类型数据]

场景: 1. 在使用sort排序时,有时候需要对对象的某个值进行排序,比如对类对象的某个id的int类型值或者bool类型值,其实bool类型值排序研究了半天。。

牛顿迭代法(Newton's Method)

牛顿迭代法(简称牛顿法)由英国著名的数学家牛顿爵士最早提出。但是,这一方法在牛顿生前并未公开发表。 牛顿法的作用是使用迭代的方法来求解函数方程的根。简单地说,牛顿法就是不断求取切线的过程。 对于形...

Leetcode全回文问题

目录: 1、编号5 5_Longest Palindromic Substring 2、编号9 Palindrome Number 3、编号126 Valid Palindrome 4、编号132 P...

Leetcode全树类问题

Leetcode全树类问题。算法总的来说就是递归(Stack, DFS)和广度优先(Queue, BFS)两种。下面有关二叉树类linked list的题目,若不加特别说明...

C++11 sort, vector, lambda——vector 自定义排序

vector自定义sort( ):std::sort大法好!std::vector大法好!lambda大法好!

c++中sort等算法中比较操作的规则

sort函数在重写比较函数cmp的时候,提示错误invalid comparator

C++sort函数的用法

C++sort()函数的用法 近来看了c++标准库这本书,学到了很多,就把这其中的一点C++sort()函数的用法写下来和大家分享吧! (一)为什么要用c++标准库里的排序函数 Sort()函数...

C++ 排序函数 sort(),qsort()的用法

想起来自己天天排序排序,冒泡啊,二分查找啊,结果在STL中就自带了排序函数sort,qsort,总算把自己解脱了~ 所以自己总结了一下,首先看sort函数见下表:     函数名 功能描述 ...

C/C++的八种排序算法及实现

几个基本常见的排序,插入排序 (包括 直接插入,希尔插入,折半插入等),交换排序(包括 冒泡排序,快速排序) ,选择排序(简单选择,堆排序,树形排序等),归并排序,基数排序(多关键字,链式基数)。
  • zcyzsy
  • zcyzsy
  • 2016-10-08 22:43
  • 1301

各类排序算法比较(C++)

1、简单选择排序 基本思想:在序列A[0]~A[n-1]中,第i趟(i=0;i>n;i++)选择从A[i-1]~A[n-1]中最小的数和A[i-1]交换,直至i=n-1,结束排序。 时间复杂度:最...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)