基础算法(2):快速排序(随机划分+三数取中划分+ 随机三数取中划分+尾递归)

来源:互联网 发布:数据挖掘从应用心得 编辑:程序博客网 时间:2024/05/16 14:12

快速排序:

简介:快速排序是一种排序算法,包含n个数的输入数组,最坏情况为O(n^2),但是平均性能非常好: 期望运行时间为O(n*lg(n))。

基本思想:通过 一次划分得到一个主元在集合中的位置。

影响因素:划分算法决定着一个快速排序的效率。           

划分算法分类

1.以集合尾元素(或首元素)为主元,以下代码以尾元素为主元。                         

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int partion(vector<int> &num, int beg, int end)  
  2. {  
  3.     /*把最后集合最后一个元素作为主元*/  
  4.     int x = num[end];  
  5.     int i = beg - 1;  
  6.     for (int j = beg; j != end; ++j)  
  7.     {  
  8.         if (num[j] <= x)  
  9.         {  
  10.             ++i;  
  11.             swap(num[i], num[j]);  
  12.         }  
  13.     }  
  14.     swap(num[i + 1], num[end]);  
  15.     return i + 1;  
  16. }  

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void quickSort(vector<int> &num, int beg, int end)  
  2. {  
  3.     if (beg < end)  
  4.     {  
  5.         int q = partion(num, beg, end);  
  6.         quickSort(num, beg, q - 1);  
  7.         quickSort(num, q + 1, end);  
  8.     }  

2. 随机数划分:随机选取数组中的一个元素为主元。随机数划分需要获得随机数,代码如下:

     1)   头文件

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <ctime>  
  2. #include <cstdlib>  

           2)在main() 函数调用random()前设置随机种子:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. srand(unsigned(time(0)));// srand函数要在main函数开始的时候设置  

           3)  写随机函数

[cpp] view plaincopy
  1. int random(int start, int end)// 返回[start, end]之间的随机数  
  2. {  
  3.     return start + (end - start + 1)*rand() / (RAND_MAX + 1);//[start, end]  
  4.     //return start + (end - start)*rand() / (RAND_MAX + 1);//[start, end)  
  5.     //return start + 1 + (end - start)*rand() / (RAND_MAX + 1);//(start, end]  
  6. }  

3.三数取中划分:取集合中的首元素,中元素,尾元素,以其中位数为主元。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int findMedian(const int &a, const int &b, const int &c)//取三个数的中位数  
  2. {  
  3.     if (a <= b && a <= c)  
  4.     {  
  5.         if (b <= c)  
  6.             return b;  
  7.         else  
  8.             return c;  
  9.     }  
  10.     else if (b < a && b <= c)  
  11.     {  
  12.         if (a <= c)  
  13.             return a;  
  14.         else  
  15.             return c;  
  16.     }  
  17.     else  
  18.     {  
  19.         if (a <= b)  
  20.             return a;  
  21.         else  
  22.             return b;  
  23.     }  
  24. }  
 4.随机三个数取中位数。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /*3种划分算法*/  
  2. int rand_Partion(vector<int> &num, int beg, int end)  
  3. {  
  4.     //int temp = random(beg, end);  
  5.     //swap(num[temp], num[end]);  
  6.     /*以上随机返回[beg, end]数组中的一个数作为主元(pivot element); 
  7.      *并把数组尾元素与这个随机数交换,因为partion()以最后一个数做主元 
  8.      */  
  9.   
  10.     //int a = random(beg, end);  
  11.     //int b = random(beg, end);  
  12.     //int c = random(beg, end);  
  13.     //int temp = findMedian(a, b, c);  
  14.     //swap(num[temp], num[end]);  
  15.     /*以上随机返回[beg, end]数组中的三个数,取三个数的中位数作为 
  16.      *主元(pivot element);并把数组尾元素与这个中位数交换 
  17.      */  
  18.     int a = num[beg];  
  19.     int b = num[beg + (end - beg) / 2];  
  20.     int c = num[end];  
  21.     int temp = findMedian(a, b, c);  
  22.     /*以上取[beg, end]的首、尾、中间三个数,把三个数的中位数作为 
  23.      *主元(pivot element);并把数组尾元素与这个中位数交换 
  24.      */  
  25.     return partion(num, beg, end);//调用分割函数  
  26. }  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void rand_quickSort(vector<int> &num, int beg, int end)  
  2. {  
  3.     if (beg < end)  
  4.     {  
  5.         int q = rand_Partion(num, beg, end);  
  6.         rand_quickSort(num, beg, q - 1);  
  7.         rand_quickSort(num, q + 1, end);  
  8.     }  
  9. }  

快速排序的尾递归: 

quickSort()中的第二次递归调用并不是必须的,可以用迭代控制结构替代它。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void quickSort_2(vector<int> &num, int beg, int end)//尾递归形式  
  2. {  
  3.     while (beg < end)  
  4.     {  
  5.         int q = partion(num, beg, end);  
  6.         quickSort_2(num, beg, q - 1);//一次循环把主元左边的排序好  
  7.         beg = q + 1;  
  8.     }  
  9. }  

0 0