Chapter 7 快速排序

快速排序---实际排序应用中最好的选择

期望时间复杂度为θ(nlgn)最坏情况复杂度为θ(n2)----由于隐含常数因子小及原址排序,故广泛用

7.1 快速排序描述

采用分治思想

分解:将数组A[p..r]划分为两个子数组A[p..q-1]和A[q+1,r],划分的依据是使A[p..q-1]的值全都小于或等于A[q],A[q+1..r]的每个值都大于等于A[q]

解决:通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]进行排序

合并:由于子数组都是原址排序,所以无需合并便已有序

核心思想:数组中找个"坑",将小于等于该坑的值扔坑的左边,大于等于该坑的值扔坑的右边,在每次递归采取同样措施(自然每次递归都要选坑)

数组的划分(1.其中的r也在数组内,因此在测试代码时为array.count-1  2.其中选择的坑为数组最末元素):

        static int Partition(List<int> array,int p,int r)
        {
            int x = array[r], temp;
            int i = p-1;         //类似于一个指示,在该指示左边的值均小于x
            for(int j=p;j<r;j++)
            {
                if(array[j]<=x)    //遇到比x小的,放到i的下一位去
                {
                    i++;
                    temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                }
            }
            array[r] = array[i + 1];
            array[i + 1] = x;
            return i + 1;
        }

快速排序:

        static void QuickSort(List<int> array,int p,int r)
        {
            int q;
            if(p<r)  //进行递归的条件
            {
                q = Partition(array, p, r);
                QuickSort(array, p, q - 1);
                QuickSort(array, q + 1, r);
            }
        }

7.2 性能分析

最坏情况(基本不可能出现):每次划分子问题时(包括递归中)产生子问题包含n-1和0个元素,则时间复杂度为θ(n2)

最好和平衡划分的情况(即任何一种常数比例的划分):产生的递归树深度为θ(lgn),每一层的时间代价都是O(n),从而可知算法的运行时间是θ(nlgn)

7.3 快速排序的随机化版本(即在选择"坑"时,随机选取)

        static int RandomPartition(List<int> array,int p,int r)
        {
            Random rnd = new Random();
            int position = rnd.Next(p, r + 1);  //随机产生一个p..r之间的数,代表选取"坑"的下标
            int temp = array[r];                //将选取的array[position]与array[r]交换
            array[r] = array[position];
            array[position] = temp;
            return Partition(array, p, r);
        }

--------练习--------

7.4-1 证明在递归式 T(n)=max0≤q≤n-1(T(q)+T(n-q-1))+θ(n) 中,  T(n)=Ω(n2)

思路,代入法    即证  cn2≤max0≤q≤n-1(T(q)+T(n-q-1))+θ(n)

由 max0≤q≤n-1(T(q)+T(n-q-1))+θ(n)≥max(q2+(n-q-1)2)+θ(n)≥(n-q-1)2+θ(n)

∴ T(n)≥(n-q-1)2+θ(n)≥cn2

--------------------

时间: 2024-11-02 04:46:43

Chapter 7 快速排序的相关文章

算法导论——lec 07 快速排序

一. 快速排序的描述 1. 快速排序是一种原地排序的算法,最坏情况下的时间复杂度为Θ(n^2),期望的运行时间为Θ(n logn),且其中隐含的常数因子较小. 2. 快速排序分三个步骤: 分解:数组A[p...r]被划分成两个数组A[p...q-1]和A[q+1...r],使得A[p...q-1]中的元素都小于等于A[q],A[q+1...r]中的元素都大于等于A[q].下标q在这个划分过程中计算. 解决:递归调用快速排序,对子数组A[p...q-1]和A[q+1...r]进行排序. 合并:两个

算法导论4:快速排序 2016.1.4

今天上最后一节史纲课,老师说不管什么学科,最重要的就是思想.我觉得很有道理. 好吧,不扯了.原谅我看书选择了速读策略,中间有很多感觉目前还很难看懂,以后有时间再细细学习.把略过去的在这里记一下. 一.矩阵乘法算法.复杂度从n^3优化到了n^2.81 (数字比较神奇).因为还没学线性代数,所以以后学了再看. 二.递归复杂度的计算和估计.这部分看起来有些复杂,好像需要比较高的数学水平,有空研究一下. 三.堆排序.这个以前已经写过了.http://www.cnblogs.com/itlqs/p/475

算法导论7.3快速排序的随机化版本

以下摘自网络 随机化快排:快速排序的最坏情况基于每次划分对主元的选择.基本的快速排序选取第一个元素作为主元.这样在数组已经有序的情况下,每次划分将得到最坏的结果.一种比较常见的优化方法是随机化算法,即随机选取一个元素作为主元.这种情况下虽然最坏情况仍然是O(n^2),但最坏情况不再依赖于输入数据,而是由于随机函数取值不佳.实际上,随机化快速排序得到理论最坏情况的可能性仅为1/(2^n).所以随机化快速排序可以对于绝大多数输入数据达到O(nlogn)的期望时间复杂度.一位前辈做出了一个精辟的总结:

【算法导论学习-015】数组中选择第i小元素(Selection in expected linear time)

1.算法思想 问题描述:从数组array中找出第i小的元素(要求array中没有重复元素的情况),这是个经典的"线性时间选择(Selection in expected linear time)"问题. 思路:算法导论215页9.2 Selection in expect linear time 2.java实现 思路:算法导论216页伪代码 /*期望为线性时间的选择算法,输入要求,array中没有重复的元素*/ public static int randomizedSelect(i

《算法导论》 — Chapter 7 快速排序

序 快速排序(QuickSort)也是一种排序算法,对包含n个数组的输入数组,最坏情况运行时间为O(n^2).虽然这个最坏情况运行时间比较差,但是快速排序通常是用于排序的最佳实用选择,这是因为其平均性能相当好,期望的运行时间为O(nlgn),且O(nlgn)中隐含的常数因子很小,另外它还能够进行就地排序在虚拟环境中也能很好的工作. 原理 快速排序也和合并排序一样,基于分治法,分为分解.解决.合并三个步骤: 分解:数组array[low-high]被分为两个(可能空)子数组array[low-te

算法导论第七章快速排序

一.快速排序概述 关于快速排序,我之前写过两篇文章,一篇是写VC库中的快排函数,另一篇是写了快排的三种实现方法.现在再一次看算法导论,发现对快速排序又有了些新的认识,总结如下: (1).快速排序最坏情况下的时间复杂度为O(n^2),虽然最坏情况下性能较差,但快排在实际应用中是最佳选择.原因在于:其平均性能较好,为O(nlgn),且O(nlgn)记号中的常数因子较小,而且是稳定排序. (2).快速排序的思想和合并排序一样,即分治.快排排序的分治思想体现在: a.首先从待排序的数中选择一个作为基数,

《算法导论》 — Chapter 7 高速排序

序 高速排序(QuickSort)也是一种排序算法,对包括n个数组的输入数组.最坏情况执行时间为O(n^2). 尽管这个最坏情况执行时间比較差.可是高速排序一般是用于排序的最佳有用选择.这是由于其平均性能相当好.期望的执行时间为O(nlgn).且O(nlgn)中隐含的常数因子非常小.另外它还能够进行就地排序在虚拟环境中也能非常好的工作. GitHub chapter 7 程序代码下载 原理 高速排序也和合并排序一样,基于分治法,分为分解.解决.合并三个步骤. 分解:数组array[low-hig

快速排序的算法导论划分形式和hoare划分

1. hoare划分 1 int hoare_partition(int a[], int begin, int end) 2 { 3 int pivot = a[begin]; 4 int ini = begin; 5 int ter = end; 6 while (ini < ter) 7 { 8 while (a[ini] <= pivot && ini <end) 9 ++ini; 10 while (a[ter] >= pivot && t

快速排序之算法导论实现

#include <iostream> using namespace std; int partition(int *a,int p,int r) { int x=a[r]; int i=p-1;//note i important which is used for //storage the number smaller than flag x=a[r] for (int j=p;j<r;j++) { if (a[j]<x)// if a[j] smaller than x=

快速排序实现代码 算法导论7.1 7.2 7.4

快速排序通常是实际排序中应用最好的选择,因为平均性能很好,且是原址排序,不稳定. 书上的大部分内容在分析其运行时间,感觉看一下就好了(还是蛮喜欢数学的,可是...) #include <iostream> #include <algorithm> #include <random> using namespace std; //实际应用比较多,原址排序 typedef int index; index Partition(int *a, index p, index r