快速排序可以在没有堆栈和递归的情况下用C实现吗?

2024-04-09

我找到了这个帖子如何在c中不使用堆栈进行迭代快速排序? https://stackoverflow.com/questions/32388760/how-to-do-iterative-quicksort-without-using-stack-in-c/但建议的答案确实使用内联堆栈数组! (仅允许恒定数量的额外空间)


页面中的代码参考 http://alienryderflex.com/quicksort/提出一个大胆的主张:

STACK我的实现不使用堆栈来存储数据......

然而函数定义中有许多自动存储的变量,其中有 2 个具有 1000 个条目的数组,它们最终将使用固定但大量的堆栈空间:

//  quickSort
//
//  This public-domain C implementation by Darel Rex Finley.
//
//  * Returns YES if sort was successful, or NO if the nested
//    pivots went too deep, in which case your array will have
//    been re-ordered, but probably not sorted correctly.
//
//  * This function assumes it is called with valid parameters.
//
//  * Example calls:
//    quickSort(&myArray[0],5); // sorts elements 0, 1, 2, 3, and 4
//    quickSort(&myArray[3],5); // sorts elements 3, 4, 5, 6, and 7

bool quickSort(int *arr, int elements) {

  #define  MAX_LEVELS  1000

  int  piv, beg[MAX_LEVELS], end[MAX_LEVELS], i=0, L, R ;

  beg[0]=0; end[0]=elements;
  while (i>=0) {
    L=beg[i]; R=end[i]-1;
    if (L<R) {
      piv=arr[L]; if (i==MAX_LEVELS-1) return NO;
      while (L<R) {
        while (arr[R]>=piv && L<R) R--; if (L<R) arr[L++]=arr[R];
        while (arr[L]<=piv && L<R) L++; if (L<R) arr[R--]=arr[L]; }
      arr[L]=piv; beg[i+1]=L+1; end[i+1]=end[i]; end[i++]=L; }
    else {
      i--; }}
  return YES; }

缩进样式非常混乱。这是重新格式化的版本:

#define MAX_LEVELS  1000

bool quickSort(int *arr, int elements) {
    int piv, beg[MAX_LEVELS], end[MAX_LEVELS], i = 0, L, R;

    beg[0] = 0;
    end[0] = elements;
    while (i >= 0) {
        L = beg[i];
        R = end[i] - 1;
        if (L < R) {
            piv = arr[L];
            if (i == MAX_LEVELS - 1)
                return NO;
            while (L < R) {
                while (arr[R] >= piv && L < R)
                    R--;
                if (L < R)
                    arr[L++] = arr[R];
                while (arr[L] <= piv && L < R)
                    L++;
                if (L < R)
                    arr[R--] = arr[L];
            }
            arr[L] = piv;
            beg[i + 1] = L + 1;
            end[i + 1] = end[i];
            end[i++] = L;
        } else {
            i--;
        }
    }
    return YES;
}

注意1000很大,但对于已排序的中等大型数组上的病理情况来说还不够。函数返回NO对于大小仅为 1000 的数组,这是不可接受的。

A much lower value would suffice with an improved version of the algorithm where the larger range is pushed into the array and the loop iterates on the smaller range. This ensures that an array of N entries can handle a set of 2N entries. It still has quadratic time complexity on sorted arrays but at least would sort arrays of all possible sizes.

这是经过修改和检测的版本:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX_LEVELS  64

int quickSort(int *arr, size_t elements) {
    size_t beg[MAX_LEVELS], end[MAX_LEVELS], L, R;
    int i = 0;

    beg[0] = 0;
    end[0] = elements;
    while (i >= 0) {
        L = beg[i];
        R = end[i];
        if (L + 1 < R--) {
            int piv = arr[L];
            if (i == MAX_LEVELS - 1)
                return -1;
            while (L < R) {
                while (arr[R] >= piv && L < R)
                    R--;
                if (L < R)
                    arr[L++] = arr[R];
                while (arr[L] <= piv && L < R)
                    L++;
                if (L < R)
                    arr[R--] = arr[L];
            }
            arr[L] = piv;
            if (L - beg[i] > end[i] - R) { 
                beg[i + 1] = L + 1;
                end[i + 1] = end[i];
                end[i++] = L;
            } else {
                beg[i + 1] = beg[i];
                end[i + 1] = L;
                beg[i++] = L + 1;
            }
        } else {
            i--;
        }
    }
    return 0;
}

int testsort(int *a, size_t size, const char *desc) {
    clock_t t = clock();
    size_t i;

    if (quickSort(a, size)) {
        printf("%s: quickSort failure\n", desc);
        return 1;
    }
    for (i = 1; i < size; i++) {
        if (a[i - 1] > a[i]) {
            printf("%s: sorting error: a[%zu]=%d > a[%zu]=%d\n",
                   desc, i - 1, a[i - 1], i, a[i]);
            return 2;
        }
    }
    t = clock() - t;
    printf("%s: %zu elements sorted in %.3fms\n",
           desc, size, t * 1000.0 / CLOCKS_PER_SEC);
    return 0;
}

int main(int argc, char *argv[]) {
    size_t i, size = argc > 1 ? strtoull(argv[1], NULL, 0) : 1000;
    int *a = malloc(sizeof(*a) * size);
    if (a != NULL) {
        for (i = 0; i < size; i++)
            a[i] = rand();
        testsort(a, size, "random");
        for (i = 0; i < size; i++)
            a[i] = i;
        testsort(a, size, "sorted");
        for (i = 0; i < size; i++)
            a[i] = size - i;
        testsort(a, size, "reverse sorted");
        for (i = 0; i < size; i++)
            a[i] = 0;
        testsort(a, size, "constant");
        free(a);
    }
    return 0;
}

Output:

random: 100000 elements sorted in 7.379ms
sorted: 100000 elements sorted in 2799.752ms
reverse sorted: 100000 elements sorted in 2768.844ms
constant: 100000 elements sorted in 2786.612ms

这是一个稍微修改过的版本,对病理情况更具抵抗力:

#define MAX_LEVELS  48

int quickSort(int *arr, size_t elements) {
    size_t beg[MAX_LEVELS], end[MAX_LEVELS], L, R;
    int i = 0;

    beg[0] = 0;
    end[0] = elements;
    while (i >= 0) {
        L = beg[i];
        R = end[i];
        if (R - L > 1) {
            size_t M = L + ((R - L) >> 1);
            int piv = arr[M];
            arr[M] = arr[L];

            if (i == MAX_LEVELS - 1)
                return -1;
            R--;
            while (L < R) {
                while (arr[R] >= piv && L < R)
                    R--;
                if (L < R)
                    arr[L++] = arr[R];
                while (arr[L] <= piv && L < R)
                    L++;
                if (L < R)
                    arr[R--] = arr[L];
            }
            arr[L] = piv;
            M = L + 1;
            while (L > beg[i] && arr[L - 1] == piv)
                L--;
            while (M < end[i] && arr[M] == piv)
                M++;
            if (L - beg[i] > end[i] - M) {
                beg[i + 1] = M;
                end[i + 1] = end[i];
                end[i++] = L;
            } else {
                beg[i + 1] = beg[i];
                end[i + 1] = L;
                beg[i++] = M;
            }
        } else {
            i--;
        }
    }
    return 0;
}

Output:

random: 10000000 elements sorted in 963.973ms
sorted: 10000000 elements sorted in 167.621ms
reverse sorted: 10000000 elements sorted in 167.375ms
constant: 10000000 elements sorted in 9.335ms

作为结论:

  • 是的,无需递归即可实现快速排序,
  • 不,如果没有任何本地自动存储,就无法实现,
  • 是的,只需要恒定数量的额外空间,但这只是因为我们生活在一个小世界中,数组的最大大小受可用内存的限制。本地对象的大小为 64,可以处理比 Internet 大小更大的数组,比当前 64 位系统可以寻址的数组大得多。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

快速排序可以在没有堆栈和递归的情况下用C实现吗? 的相关文章

随机推荐

  • 通过 VPN 连接到 Flask 应用程序

    我是 Flask 新手 如果问题听起来微不足道 请不要介意 我有一个 Flask 应用程序 不是我编写的 当我直接连接到网络时 它可以在本地计算机和远程计算机上正常工作 但是当我通过 VPN 连接到该应用程序时 它不起作用 我可以在那台机器
  • 如何更改 Ember 中的查询参数?

    我正在编写一个动作处理程序route application actions changeFoo foo I want to change the fooId queryParam to foo get id 问题是我能找到的唯一记录的更改
  • 如何杀死Postgresql中的空闲连接?

    我正在使用 java servlet 和 pgadmin 9 1 问题是 servlet 中的连接未正确关闭 因此如果达到最大连接 它会导致空白屏幕 我不希望每个用户都扩展 pgadmin 中的最大连接 i在 servlet 的起始点和结束
  • 多重继承的机制与构建灵活设计的模板相比

    这是一个更窄的版本question https stackoverflow com questions 32549573 understanding the exposition of alexandrescu about the weak
  • 如何了解 Firebase 工具的当前版本

    在 node js 命令提示符下 使用 firebase help 给出这个列表 Usage firebase options command Options V version output the version number P pr
  • 使用 MSBuild 构建解决方案文件夹

    我们有一个解决方案文件其中包含一些解决方案文件夹 库 单元测试 应用程序等 With 视觉工作室2010 https en wikipedia org wiki Microsoft Visual Studio 2010我们可以通过右键单击给
  • 将进度条添加到 gdal.Warp()

    我试图找出一种在 gdal Warp 中使用进度条来显示工作完成情况的方法 对于进度条 我使用 Tqdm 和 gdal Warp 用于从远程 URL 裁剪图像 def getSubArea url vsicurl url vsicurl u
  • 如何在 Struts 2 的单个视图中使用多个表单/操作

    我有一个显示在每个页面上的搜索框 搜索框的 JSP 代码通过图块插入到每个页面中 搜索框有一个表单和一个操作类SearchAction它需要为下拉框预加载一些属性 这SearchAction类有一个input 方法 它执行此初始化 一些页面
  • VS2010 调试/分析时的性能差异

    请参阅编辑 底部 问题可能不是我最初想的 Hi All 我正在编写一个图形库 它可以处理许多滤镜 效果 包括模糊 我一直在尝试优化我的代码 但遇到了一些我不明白的东西 当我运行代码时without在性能向导中 小图像上的简单 3x3 模糊可
  • 在Android应用程序中使用DIAL协议

    我想在我的视频流应用程序中使用 DIAL 协议 我的应用程序是一个示例应用程序 仅使用 VideoView 播放 HLS 示例流 我想集成 DIAL 协议 http www dial multiscreen org http www dia
  • servlet 代码中类型信息丢失

    我有一个与 Jersey 一起使用的简单闪存实现 如下所示 PostConstruct def before flash rotateIn PreDestroy def after flash rotateOut object flash
  • 如何在 XCode5+ 中创建 Interface Builder 插件?

    我需要做一个对象库 一个 Interface Builder 插件 例如Mapkit这样用户就可以拖动我的自定义对象并添加到UIView 作为属性 我想用我的基本属性来显示和配置它 知道如何做到这一点吗 thanks 在 Xcode 4 0
  • 通过javascript设置iframe的useragent

    试图满足的业务需求 在 iframe 中加载现有页面 模拟 iPhone 用户代理 这需要在客户端发生的原因是 有客户端脚本它检测用户代理并将一些类附加到 html 元素上 基于此 站点的样式将发生根本性的变化 因为 CSS 的目标元素是基
  • DBMS_RANDOM 被认为是危险的吗?

    我们的数据库团队希望从 PUBLIC 撤销 DBMS RANDOM 上的执行 以解决安全问题 如果你用谷歌搜索它 一些安全专家会认为这个包很危险 但没有说出原因 Ingram 和 Shaul 的书 Practical Oracle Secu
  • Android 4.4.4 上的改造 SSL 错误

    我们有一个现有的 Android 应用程序 它使用 Retrofit 连接到服务器并发送和接收 JSON 自从将我的设备更新到 Android 4 4 4 后 我在尝试连接时收到以下错误 D Retrofit 8004 javax net
  • Android Volley ECONNRESET

    我尝试使用Volley库并将图像上传到服务器 该库应该在独立模式下执行此过程 但出现以下错误消息 java net SocketException 发送失败 ECONNRESET 连接重置 由同行 是否可能是服务器端配置错误 我尝试上传一个
  • 不需要时禁用 R Shiny 中的 selectInput

    我正在构建一个shiny网页由两个表单组成selectInput 第一个 静态 在ui部分和第二部分 动态 在server部分 实际问题的简化如下所示 require shiny ui lt fluidPage The static inp
  • 防止“删除和更新”firebase中的子项

    我发现没有办法设置安全规则来防止孩子的 删除和更新 write data exists newData exists newData exists 那没有道理 为了便于将来参考 Firebase 控制台允许您测试数据库安全规则 以便您可以在
  • EF 7 迁移到现有数据库

    我正在使用 ASP Net 5 和 EF7 开发一个 Web 项目 我已将现有数据库中的所有表导入到项目中的模型中 但是 我在迁移方面遇到了问题 我已经创建了初始迁移 对特定实体进行了一些更改 在所做的更改之后创建了另一个迁移 现在想要在数
  • 快速排序可以在没有堆栈和递归的情况下用C实现吗?

    我找到了这个帖子如何在c中不使用堆栈进行迭代快速排序 https stackoverflow com questions 32388760 how to do iterative quicksort without using stack