快速排序(Quicksort)

mcomco 2018-12-18 原文

快速排序(Quicksort)

1.排序问题

  现有一个含有N个数字的数组S,如何通过程序把这个数组变成有序的数组?

  例如:

  排序前:S:5,3,7,5,9,4,1,100,50

  排序后:S:1,3,4,5,5,7,9,50,100

2.快速排序(Quicksort)

  简单介绍:  

  快速排序内含一道重要的工序:分区(Partition)。这里将先介绍分区,然后介绍排序方法。

分区:

  

  对于一个数组,将它的第一个元素设为V,令i=2,j为数组的最后一个元素的序号(index)。

  1.先从i开始比较,如果i项元素比V小,则i++;否则停止比较,此时的i项元素大于等于V。

  2.然后从j开始比较,如果j项元素比V大,则j–;否则停止比较,此时的i项元素小于等于V。

  3.如果i<j,说明i项元素和j项元素之间还有元素,将i项元素和j项元素互换,然后i++,j–,然后重复1,2,3步骤,直到i和j重合(即i=j)。

  4.将J项元素和V互换。这样就得到了一个分好区的数组:V的左端的元素都小于等于V;V的右端都大于等于V。

排序:

  1.将整个数组进行分区。

  2.对分区得到的两个部分数组分别进行分区,不停的分区下去,直到分区数组只有一个元素为止。

  3.排序完成。

3.快速排序的优缺点

优点:

不需要额外空间(归并排序需要一个额外数组),速度比归并排序快。

缺点:

1.如果数组是递增的有序数组,对它用快速排序需要N2/2次操作。

2.No Stable:如果数组已经按一种排序方式排成有序了,然后再按另一种排序方式用快速排序对此数组排序,则会打乱第一种排序。(例如手机通讯录先按地区排了一次序,再按名字排一次序。)PS:归并排序是Stable的。

 

4.快速排序具体代码实现:

.h:

UCLASS()
class ALGORITHM_API AQuicksort : public AActor
{
    GENERATED_BODY()
    
public:    
    // Sets default values for this actor's properties
    AQuicksort();
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    //生成数组
    void InitArray(int N);
    //把此部分数组分为两半,中间分界线为v,左半部分的数字都比v小,右半部分的数字都比v大
    int Partition(int lo, int hi);
    //更换数组里两个数字
    void ExChange(int i, int j);//开始排序
    //开始排序
    void Sort();
    void Sort( int lo, int hi);

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public:    
    

private:

    TArray<int> MyIntArray;
};

.cpp:

// Sets default values
AQuicksort::AQuicksort()
{
     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AQuicksort::BeginPlay()
{
    Super::BeginPlay();
    //测试
    //生成数组
    InitArray(10000);
    UKismetSystemLibrary::PrintString(this, "Before Sort: ");
    for (int i = 0; i < MyIntArray.Num(); i++)
    {
        UKismetSystemLibrary::PrintString(this, FString::FromInt(i) + " : " + FString::FromInt(MyIntArray[i]));
    }
    //开始排序
    Sort();
    UKismetSystemLibrary::PrintString(this, "After Sort: ");
    for (int i = 0; i < MyIntArray.Num(); i++)
    {
        UKismetSystemLibrary::PrintString(this, FString::FromInt(i) + " : " + FString::FromInt(MyIntArray[i]));
    }
    
}

// Called every frame
void AQuicksort::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}

void AQuicksort::InitArray(int N)
{
    FRandomStream Stream;
    Stream.GenerateNewSeed();
    for (int i = 0; i < N; i++)
    {
        MyIntArray.Add(Stream.RandRange(0, 100));
    }
}

int AQuicksort::Partition(int lo, int hi)
{
    int i(lo);
    //因为后面会--j,而我们需要从hi项开始比较,所以这里j=hi+1
    int j(hi + 1);
    //只要中途不break,循环一直进行下去
    while (true)
    {
        //lo项作为比较用的元素,从lo+1开始比较,直到找到大于等于lo项的元素,才停止(除非lo项是此部分数组中最大的,此时i=hi)
        //停止时,i项元素比lo项大
        //注意:MyIntArray[++i] < MyIntArray[lo]中,先进行++i,再进行比较
        while (MyIntArray[++i] < MyIntArray[lo])
        {
            if (i == hi) break;
        }
        //从hi项开始比较,直到找到小于等于lo项的元素,才停止(除非lo项是此部分数组中最小的,此时i=lo)
        //注意:MyIntArray[lo]<MyIntArray[--j]中,先进行--j,再进行比较
        while (MyIntArray[lo]<MyIntArray[--j])
        {
            if (j == lo) break;
        }

        //如果i >= j,说明i,j重合了,不需要继续循环。此时,i项左边的元素都比lo项小;右边的元素都比lo项大
        if (i >= j) break;
        //如果i和j之间还有元素,说明还没比较完,继续比较
        ExChange(i, j);
    }
    //lo项是分界线元素,把它放到分界线处
    ExChange(lo, j);
    //返回分界线元素的Index
    return j;
}

void AQuicksort::ExChange(int i, int j)
{
    //序号i,j应该在数组范围内
    if (i > MyIntArray.Num() - 1 || j > MyIntArray.Num() - 1) return;
    //互换
    int Tempint = MyIntArray[i];
    MyIntArray[i] = MyIntArray[j];
    MyIntArray[j] = Tempint;
}

void AQuicksort::Sort()
{
    Sort(0, MyIntArray.Num() - 1);
}

void AQuicksort::Sort(int lo, int hi)
{
    if (hi <= lo) return;
    //把此部分数组分为两部分
    int j = Partition(lo, hi);
    //然后这两部分数组作为新的部分数组继续分下去,直到hi <= lo
    Sort(lo, j - 1);
    Sort(j + 1, hi);
}

 

发表于 2018-12-18 15:46 MichaelCen 阅读() 评论() 编辑 收藏

 

版权声明:本文为mcomco原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/mcomco/p/10137601.html

快速排序(Quicksort)的更多相关文章

  1. 图表算法—最小生成树

    图表算法—最小生成树 1. 什么是最小生成树(Minimum Spanning Trees)   对于一个无向 […]...

  2. 红黑树的删除

    红黑树的删除 1.前文回顾   上一篇随笔写到了红黑树的实现及其各种功能的实现,本文将讲红黑树的删除。   上 […]...

  3. 排序算法杂谈(五) —— 关于快速排序的优化策略分析

    1. 前提 排序算法(六) —— 归并排序 排序算法(七) —— 快速排序 排序算法杂谈(四) —— 快速排序 […]...

  4. 二叉搜索树(BinarySearchTrees)

    二叉搜索树(BinarySearchTrees) 1.什么是二叉搜索树   如下图所示:15为树的根节点,10 […]...

  5. 机器学习实践之决策树算法学习

    关于本文说明,笔者原博客地址位于http://blog.csdn.net/qq_37608890,本文来自笔者 […]...

  6. 栈与队列(Stack and Queue)

    栈与队列(Stack and Queue) 1.定义      栈:后进先出(LIFO-last in fir […]...

  7. 【原创】KMP算法-讲解(不含代码)

    【原创】KMP算法-讲解(不含代码) Posted on 2018-03-14 17:01 菠萝有点甜 阅读( […]...

  8. 堆排序(Heapsort)

    堆排序(Heapsort) 1.排序问题   现有一个含有N个数字的数组S,如何通过程序把这个数组变成有序的数 […]...

随机推荐

  1. jQuery元素的筛选

    children(“这里可以添加筛选的元素”) Title<scrip...

  2. JS组件系列——表格组件神器:bootstrap table(三:终结篇,最后的干货福利)

    前言:前面介绍了两篇关于bootstrap table的基础用法,这章我们继续来看看它比较常用的一些功能,来个 […]...

  3. 微信小程序开发教程手册文档

    微信小程序开发教程手册文档 微信小程序开发教程文档 微信小程序是什么?微信小程序如何开发?微信小程序开发教程有 […]...

  4. MySQL笔记(五)之表的连接

    MySql数据库中表的连接一共有如下几种 INNER JOIN 内连接 语法: SELECT column_n […]...

  5. 如何成为一名成功的程序员

    编程是一个仅靠兴趣仍不足以抵达成功彼岸的领域。你必须充满激情,并且持之以恒地不断汲取更多有关编程的知识。只是对 […]...

  6. 买卖股票专题系列6—买卖股票的最佳时机含手续费

    题目:   给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee […]...

  7. Qt初学者的一些学习方法、参考资料

    1,简介 最近有一些朋友加我,询问Qt入门学习的方法、资料 我基本都一一作答,根据情况给出了一些参考意见 感觉 […]...

  8. 张高兴的 .NET Core IoT 入门指南:(六)串口通信入门

    在开始之前,首先要说明的是串口通信所用到的 SerialPort 类并不包含在 System.Device.G […]...

展开目录

目录导航