当前位置: 首页 > 知识库问答 >
问题:

“pi+1”语句是如何在quicksort函数中调用尾消去的?quicksort函数使用了Lomuto算法进行分区?

冯哲彦
2023-03-14

/*尾部调用消除后的快速排序*/

#include<stdio.h>

交换两个元素的效用函数

void swap(int* a, int* b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

/*此函数将最后一个元素作为pivot,将pivot元素放置在排序数组中的正确位置,并将所有较小(小于pivot)的元素放置在pivot的左侧,将所有较大的元素放置在pivot的右侧。它使用的是Lomuto分区算法。*/

int partition (int arr[], int low, int high)
{
    int pivot = arr[high];    `// pivot`
    int i = (low - 1);  `// Index of smaller element`

    for (int j = low; j <= high- 1; j++)
    {
        `// If the current element is smaller than or equal to pivot `
        if (arr[j] <= pivot)
        {
            i++;    `// increment index of smaller element`
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);
    return (i + 1);
}

/*实现QuickSort的主要函数arr[]-->要排序的数组,低-->起始索引,高-->结束索引*/

void quickSort(int arr[], int low, int high)
{
    while (low < high)
    {
        `/* pi is partitioning index, arr[p] is now at right place */`
        int pi = partition(arr, low, high);

        `// Separately sort elements before partition and after partition`
        quickSort(arr, low, pi - 1);

        low = pi+1;
    }
}

函数来打印数组

void printArray(int arr[], int size)
{
    for (int i=0; i < size; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

测试上述功能的驱动程序

int main()
{
    int arr[] = {10, 7, 8, 9, 1, 5};
    int n = sizeof(arr)/sizeof(arr[0]);
    quickSort(arr, 0, n-1);
    printf("Sorted array: \n");
    printArray(arr, n);
    return 0;
}

共有1个答案

黄俊誉
2023-03-14

quicksort函数中“pi+1”语句如何实现尾部调用消除

它没有。所有主流的x86编译器都无法从代码中展开递归。例如GCC-O3(godbolt):

quickSort:
        cmp     esi, edx
        jge     .L6
        push    r13
        mov     r13, rdi
        push    r12
        mov     r12d, edx
        push    rbp
        mov     ebp, esi
        push    rbx
        sub     rsp, 8
.L3:
        mov     esi, ebp
        mov     edx, r12d
        mov     rdi, r13
        call    partition
        mov     esi, ebp
        mov     rdi, r13
        mov     ebx, eax
        lea     edx, [rax-1]
        call    quickSort     // recursive call
        lea     ebp, [rbx+1]
        cmp     r12d, ebp
        jg      .L3
        add     rsp, 8
        pop     rbx
        pop     rbp
        pop     r12
        pop     r13
        ret
 类似资料:
  • 我已经理解了quicksort算法中的分区部分是如何完成的,但是我在理解quicksort递归函数时遇到了麻烦。谁能一步一步地给我解释一下它是怎么工作的吗?这里粘贴的是C++代码。 我的逻辑到目前为止(一步一步)是这样的:

  • 我想修改QuickSort(在Java中),这样每次调用Partition时,都会以比例数组的中值作为支点。 我在Java中有一个中值选择算法,它返回第k个最小的元素,在本例中是中值。我有大量的java快速排序算法,它们都可以独立工作,对数组进行排序。不幸的是,我不能结合这两者来实现上述目标...每次我尝试它,我通常得到堆栈溢出错误。 任何人都可以向我展示代码,看看它是如何完成的吗? 谢谢 编辑:

  • 我试图在一个保护语句中调用一个名为“nextPage”的函数,但它说“()”不能转换为“Bool”。要调用此函数,我需要做什么

  • 问题内容: 我有一个plsql函数,我想从我的函数中调用另一个函数。我怎样才能做到这一点? 这是正确的方法吗? 问题答案: 函数必须返回一个值,否则您应该具有该函数的分配目标。

  • 1. 函数调用 我们用下面的代码来研究函数调用的过程。 例 19.1. 研究函数的调用过程 int bar(int c, int d) { int e = c + d; return e; } int foo(int a, int b) { return bar(a, b); } int main(void) { foo(2, 3); return 0; } 如果在编译时加上-g选项

  • 问题内容: 我使用数组中的第一个元素作为枢轴实现了一个有效的quickSort算法,如下所示: 效果很好,但是如果我将更改为可以得到以下结果: 我如何使算法与数据透视表一起用作任何索引 问题答案: 您可以在开始排序之前简单地将所选的数据透视图与数组中的第一个元素交换,这样它将完全像以前一样工作。