快速排序算法分析及实现(C++)

快速排序算法分析及实现(C++)

目录

[TOC]

算法思想

​ 把n个元素划分为三段:左端Left,中间段middle和右端right。中段仅有一个元素。左端的元素都不大于中间段的元素,右端的元素都不小于中间段的元素。因此可以对lefe和right对立排序,所以,快速排序是一种分治思想,把大问题分为了若干个小问题。middle的元素称为支点或分割元素。

​ 举例。考察元素【4,8,3,7,1,5,6,2】。假设选择元素6作为支点。因此6属于middle;4,3,1,5,2属于left,8和7属于right。left排序结果为1,2,3,4,5;right排序为7,8。把右端的元素放在支点之后,左端left元素放在支点之前,即可得到有序序列。这个例子仅仅是对快速排序的一个简单的描述,实际操作要比这复杂。

快速排序步骤

  • 指定一个支点

    注意,是“指定”,并没有明确的约束条件,也就是说这个支点是任意一个元素,一般我们选择两种支点:当前序列首元,或者随机选取

    ​ 两种方式各有优劣,前者胜在简单,但可能影响算法效率

    ​ 快排中,支点的最终位置越靠近中间位置效率越高,读起来可能有点怪怪的,注意支点是一个值(具体元素),而不是字面意思的位置,当支点在最终序列中的位置靠前或者靠后时算法效率都不高(类似于“最坏情况”)。

    ​ 因此,后者在一定程度上减少了最坏情况的发生次数,但随机选取需要耗费额外的时间

    所以在具体应用中一般采用第一种方式来指定“支点”,也就是直接把当前序列的首元作为“支点”。

  • 进行一趟快排

    ​ 快排中,一趟操作的最终目的是把“支点”放到它应该去的地方,同时,支点左边的元素都小于支点,右边的元素都大于支点,举个例子,已知序列{7, -1, 5, 23, 100, 101},那么第一趟快排的结果是{_, _, 7, _, _, _}

    ​ 可以看到,首元(支点)已经去了它该去的地方(在最终的结果序列中,7就在中间位置,没错吧)。

  • 对子序列进行快排。

    第二步我们已经成功用支点将序列分成了3个部分,left,middle right,这三个部分总体是有序的,但是每个元素内部确实无序的,因此我们需要让这3个部分的内部也有序,对left和right继续使用快速排序就好(递归思想)。

优点分析

​ 在最坏情况下,例如,数据段left总是空的,这快速排序用时O(n^2)。在最好情况下,即数据段的left和right规模大致相同,这时快速排序用时为O(nlogn)。而快速排序的平均复杂度也是O(nlogn),这是令人惊奇的速度,amazing!

​ 快排的前身是归并,而正是因为归并存在不可忽视的缺点,才产生了快排。归并的最大问题是需要额外的存储空间,并且由于合并过程不确定,致使每个元素在序列中的最终位置上不可预知的。针对这一点,快速排序提出了新的思路:把更多的时间用在“分”上,而把较少的时间用在“治”上。从而解决了额外存储空间的问题,并提升了算法效率。

​ 快排之所以被称为“快”排,是因为它在平均时间上说最快的,主要原因是硬件方面的,每趟快排需要指定一个“支点”(也就是作为分界点的值),一趟中涉及的所有比较都是与这个“支点”来进行比较的,那么我们可以把这个“支点”放在寄存器里,如此这般,效率自然大大提高。除此之外,快排的高效率与分治思想也是分不开的。

C++语言实现

首先把数组a的最大元素移动到数组的最右端(这样可以避免支点为最大的元素),然后调用函数执行排序。


#include <iostream>
using namespace std;
template <class T>
int indexOfMax(T* a, int n);
template <class T>
void quickSort(T * a, int n);
template <class T>
void quickSort(T* a, int leftEnd, int rightEnd);
int main()
{
    
    int* a =new int[5];
    a[0] = 4, a[1] = 3, a[2] = 1, a[3] = 5, a[4] = 2;
    quickSort(a, 5);
    for (int i = 0; i < 5; i++) {
        cout<<a[i]<<"\t";
    }
    delete[] a;
    return 0;
}
/*
    快速排序的驱动程序
*/
template <class T>
void quickSort(T *a, int n) {
    if (n <= 1) { return; }
    int max = indexOfMax(a, n);
    swap(a[max], a[n - 1]);
    quickSort(a, 0, n - 2);
}
/*
快速排序函数
*/
template <class T>
void quickSort(T * a, int leftEnd, int rightEnd) {
    if (leftEnd >= rightEnd) { return; }
    //这里我们把支点选择为序列的第一个元素
    T privot = a[leftEnd];
    int leftCursor= leftEnd;//从左到右移动的索引
    int rightCursor = rightEnd + 1;//从右到左移动的索引、
    //将位于左侧不小于支点的元素和位于右侧不大于支点的元素进行交换
    while (true) {
        do
        {//寻找左侧不小于支点的元素
            leftCursor++;
        } while (a[leftCursor]<privot);
        do
        {//寻找右侧不大于支点的元素
            rightCursor--;
        } while (a[rightCursor]>privot);
        if (leftCursor >= rightCursor) { break; }
        swap(a[leftCursor], a[rightCursor]);
    }
    a[leftEnd] = a[rightCursor];
    a[rightCursor] = privot;
    quickSort(a, leftEnd, rightCursor - 1);//对左侧的数段进行快速排序
    quickSort(a, rightCursor + 1, rightEnd);//对右侧的数段进行快速排序
}
/*
找到最大值
*/
template< class T>
int indexOfMax(T* a, int n) {
    int index = 0;
    for (int i = 0; i < n; i++) {
        if (a[index] < a[i]) {
            index = i;
        }
    }
    return index;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容

  • 参考:十大经典排序算法 0、排序算法说明 0.1排序的定义 对一序列对象根据某个关键字进行排序。 0.2 术语说明...
    谁在烽烟彼岸阅读 1,011评论 0 12
  • 排序算法说明 (1)排序的定义:对一序列对象根据某个关键字进行排序; 输入:n个数:a1,a2,a3,…,an 输...
    code武阅读 656评论 0 0
  • 写一个材料,涉及到人的关系问题,以往会习惯性地写成“朋友”,但这次有点难落笔。 朋友这个词大家经常用,但朋友的真正...
    潘燕生阅读 258评论 0 4
  • 问题一: 1、为什么人要吃早餐?(现象) 为什么吃了早餐有力气做事了?(结论) 2、为什么雪是白的?(现象)为什么...
    HUAN_运营控开刀营2期阅读 434评论 0 0
  • (1) 前几天多年不见的大学同学发来了几条长长的短信,诉说着大学四年里求而不得的艰辛劳累,第一次窥见,大男子主义之...
    SofiyaJ阅读 823评论 2 4