1.快速排序缺陷

  快速排序面对重复的元素时的处理方法是,把它放在了左部分数组或右部分数组,下次进行分区时,还需检测它。如果需要排序的数组含有大量重复元素,则这个问题会造成性能浪费。

  解决方法:新增一个相同区域,并把重复元素放进去,下次进行分区时,不对相同区域进行分区。

2. 3区快速排序(3-way quicksort)

  从例子入手:

  

  现有数组A[]如上图。

  令int lt=0; int i =1; int gt=5;

  首先从A[0](53)开始  

  A[lt]与A[i]进行对比,结果:A[0]<A[1], 交换A[i]与A[gt], gt减一:

  

  A[lt]与A[i]进行对比,结果:A[0]>A[1], 交换A[i]与A[lt], lt加一,i加一:

  

  A[lt]与A[i]进行对比,结果:A[1]>A[2],交换A[i]与A[lt], lt加一,i加一:

  

  A[lt]与A[i]进行对比,结果:A[2]=A[3],i加一:

  

  A[lt]与A[i]进行对比,结果:A[1]>A[2],交换A[i]与A[lt], lt加一,i加一:

  

  i>gt,第一次排序结束。

  此时,整个数组分为3个区:

  第一个区里的所有数字都比53小,它含有a[0]~a[2];

  第二个区里的所有数字都等于53,它含有a[3]~a[4];

  第三个的所有数字都比53大,它含有a[5];

  我们还需要对第一个区和第三个区进行3区快速排序(因为这两个区里的数字可能还是乱的,虽然在本例中顺序是对的)

  从第一个区的第一个数字20开始:

  令int lt=0; int i =1; int gt=2;

  

  A[lt]与A[i]进行对比,结果:A[2]=A[3],i加一:

  

  A[lt]与A[i]进行对比,结果:A[0]<A[2], 交换A[i]与A[gt], gt减一:(这里i=gt,所以等于没交换)

  

  i>gt,第二次排序结束。

  此时,整个区分为3个区:

  第一个区里的所有数字都比20小,它没有元素;

  第二个区里的所有数字都等于20,它含有a[0]~a[1];

  第三个的所有数字都比20大,它含有a[2];

  对第一个区和第三个区进行3区快速排序,但第一个区没元素,不用排;第三个区只有一个元素,不用排。

  

  对下一个区进行3区快速排序,但此区只有A[5]一个元素,不用排;

  没有下一个区了,排序结束。

  总结一下:

  对于一个数组A[],令lt=0;i=1,gt为数组的最后一个元素的序号(index)。

  1.从A[lt]开始,如果A[lt]>A[i],交换lt项元素和i项元素,lt++,i++;如果A[lt]=A[i], i++;如果A[lt]<A[i],交换gt项元素和i项元素,gt--。

  2.当i>gt时,数组已经分好3个区域了。

  3.对大于A[lt]的元素区域和小于A[lt]的元素区域分别进行3区快速排序,直到分区数组只有一个元素为止。

3.实现代码

.h:

UCLASS()
class ALGORITHM_API AThreeWayQuicksort : public AActor
{
GENERATED_BODY() public:
// Sets default values for this actor's properties
AThreeWayQuicksort();
// Called every frame
virtual void Tick(float DeltaTime) override; //生成数组
void InitArray(int N);
//更换数组里两个数字
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
AThreeWayQuicksort::AThreeWayQuicksort()
{
// 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 AThreeWayQuicksort::BeginPlay()
{
Super::BeginPlay();
//测试
//生成数组
InitArray();
UKismetSystemLibrary::PrintString(this, "Before Sort: ");
for (int i = ; i < MyIntArray.Num(); i++)
{
UKismetSystemLibrary::PrintString(this, FString::FromInt(i) + " : " + FString::FromInt(MyIntArray[i]));
}
//开始排序
Sort();
UKismetSystemLibrary::PrintString(this, "After Sort: ");
for (int i = ; i < MyIntArray.Num(); i++)
{
UKismetSystemLibrary::PrintString(this, FString::FromInt(i) + " : " + FString::FromInt(MyIntArray[i]));
}
} // Called every frame
void AThreeWayQuicksort::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
} void AThreeWayQuicksort::InitArray(int N)
{
FRandomStream Stream;
Stream.GenerateNewSeed();
for (int i = ; i < N; i++)
{
MyIntArray.Add(Stream.RandRange(, ));
}
} void AThreeWayQuicksort::ExChange(int i, int j)
{
//序号i,j应该在数组范围内
if (i > MyIntArray.Num() - || j > MyIntArray.Num() - ) return;
//互换
int Tempint = MyIntArray[i];
MyIntArray[i] = MyIntArray[j];
MyIntArray[j] = Tempint;
} void AThreeWayQuicksort::Sort()
{
Sort(, MyIntArray.Num() - );
} void AThreeWayQuicksort::Sort(int lo, int hi)
{
if (hi <= lo) return;
//left是小于V和等于V的分界线
int Left(lo);
//Right是大于V和等于V的分界线
int Right(hi);
int V(MyIntArray[lo]);
//i是等于V和未排序元素的分界线
int i(lo);
while (i <= Right)
{
//如果小于V,放在Left的左边(小于V的元素区间)
if (MyIntArray[i] < V) ExChange(Left++, i++);
//如果大于V,放在Right的右边(大于V的元素区间)
else if (MyIntArray[i] > V) ExChange(i, Right--);
//如果等于V,i++,相当于放在Left和i之间(等于V的元素区间)
else i++;
}
//然后这两部分数组作为新的部分数组继续分下去,直到hi <= lo
Sort(lo, Left - );
Sort(Right + , hi);
}

快速排序改进——3区快速排序(3-way quicksort)的更多相关文章

  1. 分治思想的应用:C++实现快速排序和随机化的快速排序

    分治思想的应用:C++实现快速排序和随机化的快速排序 原创 2014年09月08日 14:04:49 标签: 快速排序 / 随机化快速排序 / 排序算法 / 数据结构 947 1. 快速排序时冒泡排序 ...

  2. 快速排序 Java实现的快速排序

    快速排序  Java实现的快速排序: package xc; import java.util.Arrays; import java.util.Random; /** * * @author dax ...

  3. c++之快速排序改进(随机值)

    数量少(5~25),插入排序很高效 一个影响快排效率的因素就是: 基准值的选择 本文将演示一种随之法的快排 改进前 void quick_sort5(int arr[], int low, int h ...

  4. 排序算法练习--JAVA(插入、直接选择、冒泡、快速排序、非递归快速排序)

    排序算法是数据结构中的经典算法知识点,也是笔试面试中经常考察的问题,平常学的不扎实笔试时候容易出洋相,回来恶补,尤其是碰到递归很可能被问到怎么用非递归实现... package sort; impor ...

  5. java算法面试题:设计一个快速排序。双路快速排序,简单易于理解。

    package com.swift; import java.util.ArrayList; import java.util.Collections; import java.util.Compar ...

  6. 从一组数找第K大元素

    最近做面试题,经常与到一个问题,如何高效的从一组数中找到第K大的元素. 其实我们最容易想到的肯定是蛮力法. 1. 我们可以对这个乱序数组按照从大到小先行排序,然后取出前k大,总的时间复杂度为O(n*l ...

  7. 快速排序QuickSort

    前几天实现了直接插入排序.冒泡排序和直接选择排序这三个基础排序.今天看了一下冒泡排序的改进算法,快速排序.单独记录一下,后面还有归并和基数排序等 快速排序 1.选择一个支点默认为数组第一个元素及arr ...

  8. 快速排序(QuickSort)

    1.算法思想    快速排序是一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod). (1) 分治法的基本思想    分治法的基本思想是:将原 ...

  9. Html5 快速排序演示

    快速排序(Quicksort)是对冒泡排序的一种改进.快速排序由C. A. R. Hoare在1962年提出. 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另 ...

随机推荐

  1. 微信小程序web-view使用测试总结

    1.后台配置业务域名. 2.在开发者工具的web-view组件中绑定业务域名. 3.点击开发者工具的详情按钮,选择调试基础库高版本,如果不设置,有可能绑定的业务域名内容不显示. 4.如果是公众号上的内 ...

  2. Win10系列:VC++数据绑定

    数据绑定是一种将后台数据绑定到前台控件的机制,通常用于动态地将对象或集合中所保存的数据显示到前台界面中.本节通过一个具体的示例来说明在Windows应用商店应用中如何通过数据绑定将保存在集合中的数据显 ...

  3. 网卡驱动-BD详解(缓存描述符 Buffer Description)

    DMA介绍(BD的引入) 网络设备的核心处理模块是一个被称作 DMA(Direct Memory Access)的控制器,DMA 模块能够协助处理器处理数据收发.对于数据发送来说,它能够将组织好的数据 ...

  4. js评分

    js评分    原理:给ele挂载一个自定义属性保存选中的星星数,鼠标经过时,显示所在星数的评价内容,以及给他星星亮起来,鼠标移开时显示的星星数时选择的星星数,没选的话是默认星星数,点击时,将选中的星 ...

  5. JAVA支付宝和微信(APP支付,提现,退款)

    公共参数图表:       接口 需要参数 通知方式 支付宝APP支付 应用公钥,应用私钥 异步 支付宝APP提现 应用公钥,应用私钥,支付宝公钥 同步 支付宝APP退款 应用公钥,应用私钥,支付宝公 ...

  6. Python Django 之 基于JQUERY的AJAX 登录页面

    一.基于Jquery的Ajax的实现 1.url 2.vews 3.templates

  7. .net core 之Hangfire任务调度

    Hangfire可用作任务调度,类似延迟任务.队列任务.批量任务和定时任务等. 一.nuget Hangfire包 找到Hangfire.AspNetCore和Hangfire.SqlServer包, ...

  8. [Linux]Linux下修改snmp协议的默认161端口

    一.Linux SNMP的配置 SNMP的简介和Linux下IPV4,IPV6地址的snmp协议开启可以参考上一个随笔:[Linux]CentOS6.9开启snmp支持IPV4和IPV6 二.修改默认 ...

  9. jdk8--stream并行流

    stream的并行流要理解一个框架如下: 单线程,多线程和并行流对比 package com.atguigu.java8; import java.util.concurrent.ForkJoinPo ...

  10. DevExpress WPF v18.2新版亮点(五)

    买 DevExpress Universal Subscription  免费赠 万元汉化资源包1套! 限量15套!先到先得,送完即止!立即抢购>> 行业领先的.NET界面控件2018年第 ...