排序算法性能比较练习——《数据结构、算法与应用》

参考书籍:《数据结构、算法与应用 C++语言描述》

一:排序算法复杂度
排序算法
最坏情况性能
平均性能
冒泡排序
n2
n2
计数排序
n2
n2
插入排序
n2
n2
选择排序
n2
n2
排序
nlog(n)
nlog(n)
归并排序
nlog(n)
nlog(n)
快速排序
n2
nlog(n)

二、三值取中快排
       由于快排对有序的输入序列比对无序输入序列要慢,为了解决这个问题,提高快排的平均性能,提出三值取中规则选择支点元素。方法是对序列的最左头元素、中间元素、最右头元素取三者的中值元素作为支点元素。比如三元素分别为5、9、7,则取7为支点元素;
      使用三值取中规则对输入有序的表进行快速排序,用时为O(nlog(n))。并且不会出现一个数据段为空的情况(当快排左右两块大小差不多时性能最好),使用三值取中就可以保证左右两个数据段长度均衡

三、结合两种性能好的排序算法
        实验发现当排序的数量小于某值时,插入排序性能最好,大于某值,快速排序性能最好;所以可以设置某值c结合着这两种算法.

四、C++中的排序方法
      sort:使用改进的快排,当子序列(已经经过了分治)的数量超过对数的某个常数倍时,使用堆排序,数据段不大时,使用过插入排序;
      stable_sort:是归并排序,当数据段不大时,使用插入排序。
 
五、性能最优排序算法(18章课后题28)
发现:1,在1000以上,快排的效果就显示出来了,几百的时候插入排序就很快;2,随着总数的上升nbreak不能太小,在总数0.1倍的时候效果还可以,再小就越来越差。
(注:生成数据随机,带/的后面是STL的sort方法的运行时间,没有的表示sort运行时间为0,每组试验数据多次取平均):
总数
1000
5000
50000
nbreak=100
0.001
太慢

nbreak=500
0有时比sort好
0.017

nbreak=1000
0~0.001
0.012

nbreak=2000

0.008/0.001

nbreak=2500

0.010 /0.001
45.513/0.005
nbreak=5000

0.017
1.111/0.006
nbreak=10000


0.636/0.004
nbreak=20000


0.646/0.004
nbreak=25000


0.956/0.006
nbreak=50000


1.373/0.01
//书chp18 题28
#include <iostream>
#include <algorithm>
#include <iterator>
#include <array>
#include <time.h>
using namespace std;
//void insertsort(int b[], int leftEnd, int rightEnd);
void MySort(int b[], int leftEnd, int rightEnd);
int main()
{
 const int count = 50000;
 int sortnumber[count];
 srand(unsigned(time(0)));//为了防止后面rand生成的随机数不同
 for (size_t i = 0; i < count; i++)
  sortnumber[i] = rand() % 30000;
 //排序算法,从小到大
 clock_t start, finish;
 double totaltime;
 start = clock();
 //int leftEnd = 0;
 //int rightEnd = sortnumber.size() - 1;
 MySort(sortnumber, 0, count - 1);
 finish = clock();
 totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
 cout << "my sort:" << totaltime<<endl ;
 //for (int i = 0; i<count; i++)//输出排列好以后的数组元素
  //cout << ' ' << sortnumber[i];
 cout << endl;
 array<int, count> sortnumber1;
 srand(unsigned(time(0)));//为了防止后面rand生成的随机数不同
 for (size_t i = 0; i < count; i++)
  sortnumber1[i] = rand() % 1000;
 start = clock();
 sort(sortnumber1.begin(), sortnumber1.end());  //C++ STL函数的sort方法
 finish = clock();
 totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
 cout << "C++ sort:" << totaltime << endl;
 return 0;
}
void MySort(int b[], int leftEnd, int rightEnd)
{
 int Snum = rightEnd - leftEnd + 1;
 int nBreak = 50000;
 int a[] = { b[leftEnd], b[(leftEnd + rightEnd) / 2], b[rightEnd] };
 if (Snum>nBreak)  //使用快排
 {
  //‘三值取中’
  if (a[0] > a[1])
  {
   swap(b[leftEnd], b[(leftEnd + rightEnd) / 2]);
  }
  if (a[1] > a[2])
  {
   swap(b[rightEnd], b[(leftEnd + rightEnd) / 2]);
   if (a[0] > a[1])
   {
    swap(b[leftEnd], b[(leftEnd + rightEnd) / 2]);
   }
  }
  //取中间元素作为支点
  int mid = b[(leftEnd + rightEnd) / 2];
  MySort(b, 0, (leftEnd + rightEnd) / 2 - 1);
  MySort(b, (leftEnd + rightEnd) / 2 + 1, rightEnd);
 }
 else              //使用插入排序
 {
  //insertsort(b, leftEnd, rightEnd);
  for (int i = leftEnd + 1; i <= rightEnd; i++)
  {
   int t = b[i];
   int j;
   for (j = i - 1; j >= 0 && t < b[j]; j--)
    b[j + 1] = b[j];
   b[j + 1] = t;   //注意此处是j+1是因为for循环执行完j会多减一次。
  }
 }
}
等看了二叉树后,补上堆排序。

猜你喜欢

转载自blog.csdn.net/whatwho_518/article/details/51280406
今日推荐