我用C语言编写了一个递归快速排序实现,我想使用STACK将其转换为迭代实现.

这是我用C:

int random_partition(int* arr, int start, int end) {
    srand(time(NULL));
    int random_pivot = rand() % (start - end) + start;
    swap(&arr[random_pivot], &arr[end]);
    int pivot = arr[end], pivot_index = start;
    for (int i = start; i < end; i++) {
        if (arr[i] <= pivot) {
            swap(&arr[pivot_index], &arr[i]);
            pivot_index++;
        }
    }
    swap(&arr[pivot_index], &arr[end]);
    return pivot_index;
}

void quick_sort(int* arr, int start, int end) {
    if (start < end)  {
        int pivot_index = random_partition(arr, start, end);
        quick_sort(arr, start, pivot_index - 1);
        quick_sort(arr, pivot_index + 1, end);
    }
}

这是我做的事情,但在弹出的时候我什么都不做,因为在递归中S我们做的是什么.

void quick_sort_iter(int* arr, int start, int end) {
  stack* s = create_stack(n);
  int pivot_index = random_partition(arr, start, end);
  int p = pivot_index;
  while (start < pivot_index) {
    pivot_index = random_partition(arr, start, end);
    push(s, start);
    push(s, pivot_index--);
  }
  pivot_index = p;
  while (pivot_index < end) {
    push(s, pivot_index++);
    push(s, end);
    pivot_index = random_partition(arr, start, end);
  }
  while(!is_empty(s)) {
    int e = pop(s);
    int s = pop(s);
    // do nothing, because in recursion the return doesn't do anything
  }
  return arr;
}

我首先想问的是,这是不是一条正确的道路,或者如何接近这一点?

推荐答案

您的两个循环将只创建从最左侧(start)开始或在最右侧(end)结束的分区,但正确的算法还会创建在数组的任何一端都没有边界的分区.

为此,首先将整个数组范围推送到堆栈上,然后在一个循环中,从堆栈中弹出一个范围,如果它至少有两个元素,则对其进行分区,并将两个生成的分区范围推回堆栈.继续执行此操作,直到堆栈中没有任何内容:

void quick_sort_iter(int* arr, int size) {
    stack* s = create_stack(2*size);
    push(s, 0);
    push(s, size-1);
    while (!is_empty(s)) {
        int end = pop(s);
        int start = pop(s);
        if (start < end) {
            int pivot_index = random_partition(arr, start, end);
            push(s, start);
            push(s, pivot_index - 1);
            push(s, pivot_index + 1);
            push(s, end);
        }
    }
}

以下是一些 comments :

  • 该函数只需要数组的大小作为参数.startend在循环中本地管理.因此,调整来自main的调用,只传递数组指针和数组大小.
  • 该函数为void,不应返回array.该数组是就地排序的,就像递归实现一样.
  • 您传递了n作为堆栈大小,但不清楚该n代表什么值.在这里,我使用数组大小的两倍(因为每次我们推入一对索引)作为堆栈的大小,这足以应对最坏的情况.因为您有一个随机的轴心点 Select ,堆栈的预期空间使用量是O(对数?).正如注释中所指出的,您可以通过首先将较大的分区放在堆栈上来使其达到最大值(2log2条目).

C++相关问答推荐

从内联程序集调用Rust函数和调用约定

如何解决C中的严格别名?

MISRA C:2012 11.3违规强制转换(FLOAT*)到(uint32_t*)

正在try 将文件/文件夹名从目录 struct 存储到链接列表

为什么STM32G474RE上没有启用RCC PLL

C中的指针增量和减量(*--*++p)

为什么该函数不将参数值保存到数据 struct 中?

如何捕捉只有换行符或空格字符缓冲区的边缘大小写

预先分配虚拟地址空间的区域

有什么方法可以将字符串与我们 Select 的子字符串分开吗?喜欢:SIN(LOG(10))

这个计算C中阶乘的函数正确吗?

在另一个函数中使用realloc和指针指向指针

#定义SSL_CONNECTION_NO_CONST

C语言中的外部关键字

如何摆脱-WIMPLICIT-Function-声明

为什么GCC 13没有显示正确的二进制表示法?

区分MySQL C界面中的文本和BLOB字段

如何解释数组中的*(ptr)和*(ptr+2)?

通过GTK';传递回调参数;s g_signal_connect()导致C中出现意外值

我正在使用 klib 库 我可以使用 (khash) KHASH_SET_INIT_INT64() 负值作为键.因为我在头文件中看到它使用 unsigned long int