zoukankan      html  css  js  c++  java
  • 交换排序经典的快速排序算法总结

    时间复杂度,平均O(nlogn),最坏O(n);

    不稳定的算法

    1、算法思想

        快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。

    (1) 分治法的基本思想

        分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

    (2)快速排序的基本思想

        设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:

    ①分解:

    在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。

    注意:

        划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):

        R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys

                      其中low≤pivotpos≤high。

    ②求解:

    通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。

    ③组合:

    因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

    1、如无序数组[3 2 4 1 5 9]

    a),先把第一项[3]取出来,

    用[3]依次与其余项进行比较,

    如果比[3]小就放[3]前边,2 1 都比[3]小,所以全部放到[3]前边

    如果比[3]大就放[3]后边,4 5 9比[3]大,放到[3]后边

    一趟排完后变成下边这样:

    排序前 3 2 4 1 5 9

    排序后 2 1 3 4 5 9

    b),对前半拉[2 1]继续进行快速排序

    重复步骤a)【取第一项 2与其余项比较】后变成下边这样:

    排序前 2 1

    排序后 1 2

    前半拉排序完成。

    c),对后半拉[4 5 9]继续进行快速排序

    重复步骤a)【取第一项 4与其余项比较】后变成下边这样:

    排序前 4 5 9

    排序后 4 5 9

    d),对后半拉[5 9]继续进行快速排序

    重复步骤a)【取第一项 5与其余项比较】后变成下边这样:

    排序前 5 9

    排序后 5 9

    d在这个例子中可以忽略,但是当后面的数字较小时就得必不可少的循环继续下去。

    前半拉排序完成。

    总的排序也完成:

    排序前:[3 2 4 1 5 9]

    排序后:[1 2 3 4 5 9]

    2、快速排序算法QuickSort

      void QuickSort(SeqList R,int low,int high)

       { //对R[low..high]快速排序

         int pivotpos; //划分后的基准记录的位置

         if(low<high){//仅当区间长度大于1时才须排序

            pivotpos=Partition(R,low,high); //对R[low..high]做划分

            QuickSort(R,low,pivotpos-1); //对左区间递归排序

            QuickSort(R,pivotpos+1,high); //对右区间递归排序

          }

        } //QuickSort

      注意:

        为排序整个文件,只须调用QuickSort(R,1,n)即可完成对R[l..n]的排序。

    具体算法实现:

       1: int partition(int R[], int low, int high)
       2: {//对R[low..high]做划分
       3:     int pivot = R[low];
       4:     int tmp =0;
       5:  
       6: //    int i = low, j= high ;
       7: //    print(R+low,high-low+1);
       8:  
       9:     while(low < high)
      10:     {
      11:         while( low <high &&R[high] >= pivot)
      12:             --high ;
      13:         swap(R[low] ,R[high]);    
      14:  
      15:         while (low < high && R[low] <= pivot )
      16:             ++low;
      17:         swap(R[low] ,R[high]);        
      18:  
      19:         
      20:     }    
      21:  
      22:  
      23:     //print(R+i,j-i+1);
      24:     
      25:     return high;
      26: }
      27: void quick_sort_z(int R[] ,int low ,int high)
      28: { 
      29:     int pivot_pos; //划分后的基准记录的位置
      30:     if(low<high){  //仅当区间长度大于1时才须排序
      31:         pivot_pos = partition(R ,low, high); //对R[low..high]做划分
      32:     //    cout<<pivot_pos <<endl;
      33:         quick_sort_z(R, low, pivot_pos-1); //对左区间递归排序
      34:         quick_sort_z(R, pivot_pos+1, high);//对右区间递归排序
      35:     }
      36: }
      37:  
      38: void quick_sort(int R[], int low, int high)
      39: {
      40:     quick_sort_z(R,low,high);
      41: }

    另一种partion算法实现:以最后一个元素作为基准

       1: int partition_a(int data[],int lo,int hi) 
       2: {
       3:     int key=data[hi];  //以最后一个元素,data[hi]为主元
       4:     int i=lo-1;
       5:     for(int j=lo;j<hi;j++)   ///注,j从p指向的是r-1,不是r。
       6:     {
       7:         if(data[j]<=key)
       8:         {
       9:             i=i+1;
      10:             swap(data[i],data[j]);
      11:         }
      12:     }
      13:     swap(data[i+1],data[hi]);   
      14:     return i+1;
      15: }

    完整的源代码(VS2010编译):

       1: // code-summary.cpp : 定义控制台应用程序的入口点。
       2:  
       3: /**************************************************************************
       4:     * Copyright (c) 2013,  All rights reserved.
       5:     * 文件名称    : code-summary.cpp
       6:     * 文件标识    :
       7:     * 摘    要    : 快速排序算法
       8:     * 
       9:     * 当前版本    : Ver 1.0
      10:     * 作者    : 徐冬冬
      11:     * 完成日期    : 2013/05/10
      12:     *
      13:     * 取代版本    : 
      14:     * 原作者    :
      15:     * 完成日期    :  
      16:     * 开放版权  : GNU General Public License GPLv3
      17: *************************************************************************/
      18: #include "stdafx.h"
      19:  
      20: #include <iostream>
      21: #include <random>
      22: #include <stdlib.h>
      23: using namespace std;
      24:  
      25: //快速排序
      26:  
      27: void init(int a[], int len)
      28: {
      29:     int i =0;
      30:     for( i=0;  i<len ;i++)
      31:     {
      32:         a[i]= rand();
      33:     }
      34:     return ;    
      35: }
      36: void print(int *a, int len)
      37: {
      38:     int i =0;
      39:     for( i=0;  i<len; i++)
      40:     {
      41:         cout << a[i] <<'\t';
      42:     }
      43:     cout << endl;
      44:     return ;    
      45: }
      46: void swap(int &a, int &b)
      47: {
      48:     int tmp =a;
      49:     a = b;
      50:     b=tmp;
      51:     return ;
      52: }
      53: int partition(int R[], int low, int high)
      54: {//对R[low..high]做划分
      55:     int pivot = R[low];
      56:     int tmp =0;
      57:  
      58: //    int i = low, j= high ;
      59: //    print(R+low,high-low+1);
      60:  
      61:     while(low < high)
      62:     {
      63:         while( low <high &&R[high] >= pivot)
      64:             --high ;
      65:         swap(R[low] ,R[high]);    
      66:  
      67:         while (low < high && R[low] <= pivot )
      68:             ++low;
      69:         swap(R[low] ,R[high]);        
      70:  
      71:         
      72:     }    
      73:  
      74:  
      75:     //print(R+i,j-i+1);
      76:     
      77:     return high;
      78: }
      79:  
      80: int partition_a(int data[],int lo,int hi) 
      81: {
      82:     int key=data[hi];  //以最后一个元素,data[hi]为主元
      83:     int i=lo-1;
      84:     for(int j=lo;j<hi;j++)   ///注,j从p指向的是r-1,不是r。
      85:     {
      86:         if(data[j]<=key)
      87:         {
      88:             i=i+1;
      89:             swap(data[i],data[j]);
      90:         }
      91:     }
      92:     swap(data[i+1],data[hi]);   
      93:     return i+1;
      94: }
      95:  
      96: void quickSort(int R[] ,int low ,int high)
      97: { 
      98:     int pivot_pos; //划分后的基准记录的位置
      99:     if(low<high){  //仅当区间长度大于1时才须排序
     100:         pivot_pos = partition(R ,low, high); //对R[low..high]做划分
     101:     //    cout<<pivot_pos <<endl;
     102:         quickSort(R, low, pivot_pos-1); //对左区间递归排序
     103:         quickSort(R, pivot_pos+1, high);//对右区间递归排序
     104:     }
     105: }
     106:  
     107: void quickSort_a(int R[] ,int low ,int high)
     108: { 
     109:     int pivot_pos; //划分后的基准记录的位置
     110:     if(low<high){  //仅当区间长度大于1时才须排序
     111:         pivot_pos = partition_a(R ,low, high); //对R[low..high]做划分
     112:         //    cout<<pivot_pos <<endl;
     113:         quickSort_a(R, low, pivot_pos-1); //对左区间递归排序
     114:         quickSort_a(R, pivot_pos+1, high);//对右区间递归排序
     115:     }
     116: }
     117: void quick_sort(int R[], int low, int high)
     118: {
     119:     quickSort(R,low,high);
     120: }
     121:  
     122: void quick_sort_a(int R[], int low, int high)
     123: {
     124:     quickSort_a(R,low,high);
     125: }
     126:  
     127:  
     128: int _tmain(int argc, _TCHAR* argv[])
     129: {
     130:     int *arr = new int[10];
     131:     init(arr, 10);
     132:     print(arr, 10);
     133:     quick_sort(arr,0,9);
     134:     print(arr, 10 );
     135:  
     136:     init(arr, 10);
     137:     print(arr, 10);
     138:     quick_sort_a(arr,0,9);
     139:     print(arr, 10 );
     140:  
     141:     system("pause");
     142:     return 0;
     143: }
     144:  

    参考资料:

    http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.3.2.1.htm

    http://www.cnblogs.com/kkun/archive/2011/11/23/2260270.html

    http://blog.csdn.net/v_july_v/article/details/6262915

  • 相关阅读:
    http协议详解
    001http协议
    django整合版
    数据库整合版
    并发编程整合版
    网络编程整合版
    面向对象编程
    LeetCode OJ:Binary Tree Postorder Traversal(后序遍历二叉树)
    LeetCode OJ:Populating Next Right Pointers in Each Node II(指出每一个节点的下一个右侧节点II)
    LeetCode OJ:Populating Next Right Pointers in Each Node(指出每一个节点的下一个右侧节点)
  • 原文地址:https://www.cnblogs.com/xuddong/p/3072160.html
Copyright © 2011-2022 走看看