k& r QuickSort问题

发布于 2025-01-18 20:54:54 字数 2138 浏览 3 评论 0原文

我似乎无法理解 K&R(C 编程语言第二版)的 qsort 实现中的问题所在。

void qsort_1(int v[], int left, int right)
{
    int i, last;

    void swap(int v[], int i, int j);

    if (left >= right) 
            return;
    swap(v, left, (left + right)/2);
    last = left;                    
    for (i = left + 1; i <= right; i++)
            if (v[i] < v[left])
                    swap(v, ++last, i);
    swap(v, left, last);
    qsort_1(v, left, last-1);
    qsort_1(v, last+1, right);
}

这是他们的版本,我只是将其重命名为 qsort_1,以便我可以同时使用内置版本。

int arr_len = 9;

int main() {
int a[] = { 5, 5, 4, 6, 3, 7, 8, 13, 17 };
int b[] = { 5, 5, 4, 6, 3, 7, 8, 13, 17 };

    print_a(a, arr_len); // print first array
    print_a(b, arr_len); // print second array
    putchar('\n'); // space
    
    qsort(b, arr_len, sizeof(int), cmpfunc); // sort second array with standard qsort
    qsort_1(a, 0, arr_len); // sort first array with K&R qsort
    
    print_a(a, arr_len); // print first array
    print_a(b, arr_len); // print second array
    
    return 0;

}

print_a 是一个用于显示数组的迷你函数,只需一个 for 循环。 qsort 是官方标准实现。

我得到的输出是:

gcc -O2 -lm -o qsort qsort.c
5 5 4 6 3 7 8 13 17
5 5 4 6 3 7 8 13 17

0 3 4 5 5 6 7 8 13
3 4 5 5 6 7 8 13 17

似乎有一个前导 0 并且每次 K&R qsort 中最后一个元素都会被删除。 ...帮助

void print_a(int a[], int len) {
    for (int i = 0; i < len; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
}

int cmpfunc (const void * a, const void * b) {
   return ( *(int*)a - *(int*)b );
}

如果需要,这里有 cmpfuncprint_a

尝试用谷歌搜索这个问题,但似乎没有人遇到同样的问题。

编辑: main函数中的代码发生了变化:

int main() {
    int a[] = { 5 , 5 ,4 ,6 ,3 ,7 ,8, 13, 17 };
    int b[] = { 5 , 5 ,4 ,6 ,3 ,7 ,8, 13, 17 };

    print_a(a, arr_len);
    print_a(b, arr_len);
    putchar('\n');

    qsort(b, arr_len, sizeof(int), cmpfunc);
    qsort_1(a, 0, **arr_len - 1**);

    print_a(a, arr_len);
    print_a(b, arr_len);

    return 0;
}

I seem to be having a problem understanding where the issue is in the qsort implementation by K&R (C Programming Language second edition).

void qsort_1(int v[], int left, int right)
{
    int i, last;

    void swap(int v[], int i, int j);

    if (left >= right) 
            return;
    swap(v, left, (left + right)/2);
    last = left;                    
    for (i = left + 1; i <= right; i++)
            if (v[i] < v[left])
                    swap(v, ++last, i);
    swap(v, left, last);
    qsort_1(v, left, last-1);
    qsort_1(v, last+1, right);
}

This is their version, I only renamed it to qsort_1 so that I could use the built in one at the same time.

int arr_len = 9;

int main() {
int a[] = { 5, 5, 4, 6, 3, 7, 8, 13, 17 };
int b[] = { 5, 5, 4, 6, 3, 7, 8, 13, 17 };

    print_a(a, arr_len); // print first array
    print_a(b, arr_len); // print second array
    putchar('\n'); // space
    
    qsort(b, arr_len, sizeof(int), cmpfunc); // sort second array with standard qsort
    qsort_1(a, 0, arr_len); // sort first array with K&R qsort
    
    print_a(a, arr_len); // print first array
    print_a(b, arr_len); // print second array
    
    return 0;

}

print_a is a mini function for displaying an array, just one for loop.
qsort is the official standard implementation.

The output I get is:

gcc -O2 -lm -o qsort qsort.c
5 5 4 6 3 7 8 13 17
5 5 4 6 3 7 8 13 17

0 3 4 5 5 6 7 8 13
3 4 5 5 6 7 8 13 17

There seems to be a leading 0 and the last element is removed in the K&R qsort everytime. ...Help

void print_a(int a[], int len) {
    for (int i = 0; i < len; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
}

int cmpfunc (const void * a, const void * b) {
   return ( *(int*)a - *(int*)b );
}

If needed, here are the cmpfunc and print_a.

Tried googling the problem but no one seemed to have the same issue.

EDIT:
The code changed in the main function:

int main() {
    int a[] = { 5 , 5 ,4 ,6 ,3 ,7 ,8, 13, 17 };
    int b[] = { 5 , 5 ,4 ,6 ,3 ,7 ,8, 13, 17 };

    print_a(a, arr_len);
    print_a(b, arr_len);
    putchar('\n');

    qsort(b, arr_len, sizeof(int), cmpfunc);
    qsort_1(a, 0, **arr_len - 1**);

    print_a(a, arr_len);
    print_a(b, arr_len);

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

短暂陪伴 2025-01-25 20:54:54

如有疑问,请查看代码 写道。

  • 我们可以假设K&amp; r知道他们在做什么。
  • 我们可以进一步假设标准库中Qsort的作者也知道他们在做什么。

因此,我们应该查看 you 撰写的第一个地方。那你真正的作者是什么。打印功能,Qsort比较器,基本上是main中的所有内容。快速审查显示:

  • print_a肯定可以,只要基本地址和长度有效(在这种用法中,它们是有效的),所以这已经消失了。
  • QSORT比较器似乎正确,因为(a)起作用,并且(b)它与完全无关的函数的可疑输出无关,qsort_1。所以出来了。

仅留下main。在该功能中,我们可以:

int main() 
{
    int a[] = { 5, 5, 4, 6, 3, 7, 8, 13, 17 };
    int b[] = { 5, 5, 4, 6, 3, 7, 8, 13, 17 };

    print_a(a, arr_len); // print first array
    print_a(b, arr_len); // print second array
    putchar('\n'); // space
    
    qsort(b, arr_len, sizeof(int), cmpfunc); // sort second array with standard qsort
    qsort_1(a, 0, arr_len); // sort first array with K&R qsort
    
    print_a(a, arr_len); // print first array
    print_a(b, arr_len); // print second array
    
    return 0;

}

从中:

  • 数组声明当然可以。
  • print_a呼叫查看OK(基本地址和长度有效)。
  • 调用QSort是无关的,显然还可以。

在整个程序中只留下一行代码,可能是罪魁祸首:

qsort_1(a, 0, arr_len); // sort first array with K&R qsort

检查算法,k&amp; r函数期望:

  • 阵列基础地址(确定)
  • 分区中第一个分类的索引,在这种情况下,在这种情况下进行排序。 0 。 (确定)
  • 分区中的最后一个索引。嗯...

这就是问题。 arr_len不是最后一个索引。它是序列的长度。由于C中的数组是基于0索引的数组,因此最后一个索引为arr_len-1,而不是arr_len

修复了这一点:

qsort_1(a, 0, arr_len-1);

代码将正常工作。

When in doubt, look at the code you wrote.

  • We can assume for a moment that K&R knew what they were doing.
  • We can further assume that the authors of qsort in the standard library knew what they were doing as well.

Therefore, the first places we should look at what you authored. So what did you really author. The print function, the qsort comparator, and basically everything in main. A quick review reveals:

  • print_a is certainly ok, provided the base address and length are valid (and they are in this usage case), so that's out.
  • The qsort comparator seems correct, since (a) it works, and (b) it has nothing to do with questionable output from a totally unrelated function, qsort_1. So that's out.

That leaves only main. Within that function we have:

int main() 
{
    int a[] = { 5, 5, 4, 6, 3, 7, 8, 13, 17 };
    int b[] = { 5, 5, 4, 6, 3, 7, 8, 13, 17 };

    print_a(a, arr_len); // print first array
    print_a(b, arr_len); // print second array
    putchar('\n'); // space
    
    qsort(b, arr_len, sizeof(int), cmpfunc); // sort second array with standard qsort
    qsort_1(a, 0, arr_len); // sort first array with K&R qsort
    
    print_a(a, arr_len); // print first array
    print_a(b, arr_len); // print second array
    
    return 0;

}

From this:

  • The array declarations are certainly ok.
  • The print_a calls check out ok (base address and length are valid).
  • The call to qsort is unrelated, and obviously ok.

That leave only one line of code in this entire program that could be the culprit:

qsort_1(a, 0, arr_len); // sort first array with K&R qsort

Checking the algorithm, the K&R function expects:

  • The array base address (ok)
  • The first index in the partition to sort, in this case 0. (ok)
  • The last index in the partition to sort. Um...

That's the problem. arr_len is not the last index. It is the length of the sequence. Since arrays in C are 0-index based, the last index is therefore arr_len-1, not arr_len.

Fix that:

qsort_1(a, 0, arr_len-1);

And the code will work as-expected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文