现在的位置: 首页 > 综合 > 正文

算法导论——第四章——快速排序

2012年12月24日 ⁄ 综合 ⁄ 共 1665字 ⁄ 字号 评论关闭

 1.快速排序的基本思想
     设当前待排序的无序区为R[p,r],利用分治法可将快速排序的基本思想描述为:
①分解: 
   
  在R[p,r]中任选一个记录作为基准q,以此基准将当前无序区划分为左、右两个较小的子区间R[p,q-1)和R[q+1,r],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为q),右边的子区间中所有记录的关键字均大于等于q,而基准记录q则位于正确的位置(pivotpos)上,它无须参加后续的排序。
 
②求解: 
    
 通过递归调用快速排序对左、右子区间R[p,q-1]和R[q+1,r]快速排序。
③组合: 
   
  因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

代码如下
// 快速排序.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
 
int num=10;
 
void swap(int &a, int &b)            //交换数组元素
{
    int temp = a;
    a = b;
    b = temp;
}
 
void PrintArray(int *arr)            //输出数组
{
    for(int i=0; i<num; ++i)
        cout << arr[i] << " ";
    cout << endl;
}
 
int Partition2(int *arr, int beg, int end)     //划分数组
{
    int sentinel = arr[end];               ////用区间的最后数个记录作为基准
    int i = beg-1;
    for(int j=beg; j<=end-1; j++)   //从左向右扫描,查找第1个关键字小于sentinel的记录arr[j]
    {
        if(arr[j] <= sentinel)
        {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i+1], arr[end]);
    cout << "排序过程:";
    PrintArray(arr);
    return i+1;
}
 
void QuickSort(int *arr, int beg, int end)            //实现快速排序
{
    if(beg < end)
    {
        int pivot = Partition2(arr, beg, end);
        QuickSort(arr, beg, pivot-1);
        QuickSort(arr, pivot+1, end);
    }
}
 
int main()
{
   int arr[]={2,6,7,5,8,1,9,10,3,4};
    QuickSort(arr, 0, 9);
    cout << "最后结果:";
    PrintArray(arr);
   
	char x;
	cin >> x;
	 return 0;
}

 

算法分析
     快速排序的时间主要耗费在划分操作上,对长度为k的区间进行划分,共需k-1次关键字的比较。

(1)最坏时间复杂度
     最坏情况是每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准右边的子区间为空,而划分所得的另一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减少一个。
     因此,快速排序必须做n-1次划分,第i次划分开始时区间长度为n-i+1,所需的比较次数为n-i(1≤i≤n-1),故总的比较次数达到最大值:
               Cmax = n(n-1)/2=O(n2)
(2) 最好时间复杂度
     在最好情况下,每次划分所取的基准都是当前无序区的"中值"记录,划分的结果是基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数:
        0(nlgn)
注意:
     用递归树来分析最好情况下的比较次数更简单。因为每次划分后左、右子区间长度大致相等,故递归树的高度为O(lgn),而递归树每一层上各结点所对应的划分过程中所需要的关键字比较次数总和不超过n,故整个排序过程所需要的关键字比较总次数C(n)=O(nlgn)。
     因为快速排序的记录移动次数不大于比较的次数,所以快速排序的最坏时间复杂度应为0(n2),最好时间复杂度为O(nlgn)。

抱歉!评论已关闭.