快速排序之“采取“尾递归”和“三数取中”技术的快速排序”

2023-11-13

快速排序之“采取“尾递归”和“三数取中”技术的快速排序”  
     下面针对快速排序进行一些优化。
      QUICKSORT算法包含两个对其自身的递归调用,即调用PARTITION后,左边的子数组和右边的子数组分别被递归排序。QUICKSORT中的第二次递归调用并不是必须的,可以用迭代控制结构来代替它,这种技术叫做“尾递归”,大多数的编译器也使用了这项技术。最坏的情况下,就是划分不好的时候,递归深度为O(n),能够二分的话递归深度为O(lgn),但是怎么才能得到好的划分呢?前面在快速排序中用了个随机化技术,“三数取中”能够让随机化更加理想。有这两项技术护体,快速排序不管在时间复杂度还是空间复杂度上都能得到优化。所谓“三数取中”是指,从子数组中随机选出三个元素,取其中间数作为主元,这算是前面随机化版本的升级版,即使是升级版,也只能影响快速排序时间复杂度O(nlgn)的常数因子。
     下面以一个程序代码实现来讲解。
     

#include <string.h>
#include <time.h>

#define BUFFER_SIZE 10

int Partition(int *a,int p,int r)
{
 int tmp=0;
 int i=0;
 int j=0;
 
 i=p-1;
 for(j=p;j<r;j++)
 {
  if(a[j]<=a[r])
  {
   i++;
   tmp=a[i];
   a[i]=a[j];
   a[j]=tmp;
  }
 }
 tmp=a[i+1];
 a[i+1]=a[r];
 a[r]=tmp;
 
 return i+1;
}

int RandomPartition(int *a,int p,int r)
{
 int min=0;
 int mid=0;
 int max=0;
 int i=0;
 int j=0;
 int k=0;
 int tmp=0;
 
 srand((unsigned)time(NULL));
 i=rand()%(r-p+1)+p;
 j=rand()%(r-p+1)+p;
 k=rand()%(r-p+1)+p;
 
 min=a[i];
 mid=a[j];
 max=a[k];
 
 min=(min<mid)?min:mid;
 mid=(mid<max)?mid:max;
 mid=(mid>min)?mid:min;
 
 if(a[i]==mid)
 {
  tmp=a[i];
  a[i]=a[r];
  a[r]=tmp;
 }
 else if(a[j]==mid)
 {
  tmp=a[j];
  a[j]=a[r];
  a[r]=tmp;
 }
 else if(a[k]==mid)
 {
  tmp=a[k];
  a[k]=a[r];
  a[r]=tmp;
 }
 
 return Partition(a,p,r);
}

void QuickSort(int *a,int p,int r)
{
 int q=0;
 while(p<r)//直到把右半边数组划分成最多只有一个元素为止,就排完了!不能用if哦,用if的话,右半边数组就只被划分一次。
 {
  q=RandomPartition(a,p,r);
  QuickSort(a,p,q-1);
  p=q+1;
 }
}

int main()
{
 int i=0;
 int j=0;
 int a[BUFFER_SIZE]; 
 //随机生成数组 
 srand((unsigned)time(NULL));
 for(j=0;j<BUFFER_SIZE;j++)
 {
  a[j]=rand()%100;
 } 
 printf("随机生成的数组:\n");
 for(i=0;i<BUFFER_SIZE;i++)
 {
  printf("%d ",a[i]);
 } 
 printf("\n");
 
 QuickSort(a,0,BUFFER_SIZE-1);
 printf("对数组进行快速排序:\n"); 
 for(i=0;i<BUFFER_SIZE;i++)
 {
  printf("%d ",a[i]);
 }
 
 system("pause");
 return 0;


优化的尾递归:
QUICKSORT (A, p, r )
    while p < r
        do Partition and sort the small subarray ?rst
        q ← PARTITION(A, p, r )
        if q ? p < r ? q
            then QUICKSORT (A, p, q ? 1)
                    p ← q + 1
        else QUICKSORT (A, q + 1, r )
                    r ← q ? 1
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

快速排序之“采取“尾递归”和“三数取中”技术的快速排序” 的相关文章

  • 如何在 jQuery 中检查 null 对象

    我正在使用 jQuery 我想检查页面中是否存在某个元素 我写了以下代码 但它不起作用 if btext i null alert btext i text btext i text Branch i 如何检查元素是否存在 检查jQuery
  • SQL Server 不使用索引将日期时间与非空进行比较

    我有一个与其他任何表都不相关的简单表 它有一个非 PK 列 它是一个日期 我已经为该列创建了一个非聚集索引 如果我提出这个查询 select from table where datecolumn is not null 但如果我删除 no
  • 如何在c中的某个位置终止字符指针?

    我试图通过设置空终止符来终止 c 中的字符指针 在特定位置 例如 如果我有一个 char 指针 char hi hello 我希望它是 hell 通过设置o为空 我尝试过使用 strcpy 来执行此操作 例如 strcpy hi 4 0 但
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • 将 null 转换为对象?

    我今天遇到了这段代码 AsyncInvoke OnTimeMessageTimer object null ElapsedEventArgs null 有没有什么问题 有时 当方法重载时 您需要这样做 以告诉编译器您正在调用哪一个 null
  • 如何读取大型平面文件

    我有一个平面文件 其中包含 339276 行文本 大小为 62 1 MB 我试图读入所有行 根据我所拥有的某些条件解析它们 然后将它们插入数据库 我最初尝试使用 bufio Scan 循环和 bufio Text 来获取该行 但缓冲区空间不
  • AudioRecord - 如何将数据放入缓冲区?

    我在使用 AudioRecord 类时遇到一些问题 我想将记录的数据存储在缓冲区中 但我不确定实现这一目标的正确方法是什么 我查阅了大量示例 但大多数都很复杂并且代表了许多不同的方法 我正在寻找简单的一个或简单的解释 这是我的项目的音频设置
  • Java,将 null 分配给对象和仅声明之间有什么区别

    之间有什么区别 Object o null and Object o 仅声明 有人可以回答我吗 这取决于您声明变量的范围 例如 局部变量没有default values在这种情况下你将不得不分配null手动 在这种情况下实例变量分配 nul
  • 当没有数据时,空 json 对象而不是 null -> 如何使用 gson 反序列化

    我正在尝试使用 Google 的 gson 库解析 json 数据 但 json 数据表现不佳 当一切正常时 它确实看起来像这样 parent child one some String child two 4711 child one应该
  • AngularJs 表单发布数据在我的 spring 控制器中给出空值

    大家好 我正在尝试使用 Angular 发布表单 但我在 Spring 控制器中收到空值 此外 在我的控制台中 我看到 sysout 的空值 此外 即使我看到 bull 打印在我的控制台上 我也会收到错误警报 我的 JS 控制器 angul
  • KDB 排除具有空值的行

    我有一个表 其中有一些带有空值的单元格 分散在数据集中 有什么简单的方法可以排除任何列中包含空值的所有行吗 我只是想避免这种情况 select from T where not null col1 not null col2 not nul
  • 堆分配对象是否有一个永不为空的唯一所有者?

    目前 我正在存储一个集合std unique ptrs 到堆分配的多态类型对象 struct Foo virtual Foo default Collection
  • 了解 netty 通道缓冲区和水印

    我正在尝试了解网络缓冲区和水印 作为一个测试用例 我有一个 netty 服务器 它向客户端写入数据 客户端被阻止 基本上每次读取之间有 10 秒的睡眠时间 在正常 I O 下 如果接收方被阻塞 TCP 发送方将受到限制 由于流量控制 发送速
  • Java 空值检查

    我有一个thread1 if object null object play 和另一个thread2可以写null into object随时参考 我将同时运行这些线程 我知道thread2可以重写object后参考null检查并会抛出Nu
  • OpenGL:VAO 和 VBO 对于大型多边形渲染任务是否实用?

    如果您想渲染一次在视锥体中包含数千个多边形的大型景观 并且用户的视点不断变化 那么使用 VAO 或 VBO 是否实用 我的意思是 每次玩家的位置或摄像机旋转发生变化时 您都必须重新计算顶点数据 以便正确剔除不再可见的任何顶点或场景 以保持良
  • 使用 jq 过滤空值和/或 null 值

    我有一个包含 jsonlines 的文件 想找到空值 name Color TV price 1200 available name DVD player price 200 color null 并希望输出空和 或空值及其键 availa
  • 在 SQL Server SELECT 语句中使用 CASE 时消除 NULL

    我有一份大而混乱的报告要写 它连接了 5 个表 一个表中有一列用于多个不同的值 本质上是一个 标签 列 其中标签根据用户想要使用的各种元数据的类型以创造性的方式使用 因此 我对报告的查询返回 3 个几乎相同的行 仅 标签 列有所不同 例如
  • cout什么时候刷新?

    I know endl或致电flush 将冲洗它 我也知道当你打电话时cin after cout 它也会冲水 还有当程序退出时 是否还有其他情况cout脸红 我只是写了一个简单的循环 我没有刷新它 但我可以看到它被打印到屏幕上 为什么 谢
  • 空合并运算符分配给 self

    我目前在 Unity 中设置了两个脚本来处理一些 UI 音频 一个是管理器 另一个是为特定 UI 元素播放声音 我所拥有的简化版本是这样的 public class AudioUIManager MonoBehaviour Only one
  • 如何在 JavaScript 中检查未定义或 null 变量?

    我们经常在 JavaScript 代码中使用以下代码模式 if typeof some variable undefined some variable null Do something with some variable 是否有一种不

随机推荐