【问题标题】:qsort - What goes on behind the scenes? [closed]qsort - 幕后发生了什么? [关闭]
【发布时间】:2018-01-18 20:02:06
【问题描述】:

使用这个简单的示例,目前有 6 个数字排序为 5、4、3、2、1、0,并将排序为:0、1、2、3、4、5

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

int values[] = {5,4,3,2,1,0};
int sizeOfArray = sizeof(values)/sizeof(int);

int cmpfunc (const void * a, const void * b) 
{
    printf("Comparing %d and %d \n",*(int*)a, *(int*)b);
   return ( *(int*)a - *(int*)b );
}

int main () {
   int n;
   printf("Size of Array : %d\n", sizeOfArray);
   printf("Before sorting the list is: \n");
   for( n = 0 ; n < sizeOfArray; n++ ) {
      printf("%d ", values[n]);
   }

   printf("\n");

   qsort(values, sizeOfArray, sizeof(int), cmpfunc);

   printf("\nAfter sorting the list is: \n");
   for( n = 0 ; n < sizeOfArray; n++ ) {   
      printf("%d ", values[n]);
   }

   return(0);
}

在 cmpfunc 函数中添加了一个 printf 命令,用于在调用每个函数时显示正在比较的数字。

Size of Array : 6
Before sorting the list is: 
5 4 3 2 1 0 
Comparing 4 and 3 
Comparing 5 and 3 
Comparing 5 and 4 
Comparing 1 and 0 
Comparing 2 and 0 
Comparing 2 and 1 
Comparing 3 and 0 
Comparing 3 and 1 
Comparing 3 and 2 

After sorting the list is: 
0 1 2 3 4 5 

请注意,应用程序只调用 cmpfunc 9 次。 我本来希望这个函数被多次调用。 另请注意,5 或 4 永远不会与 2 或 1 进行比较。

有没有人能够解释导致这个例程如此高效的幕后发生的事情?

【问题讨论】:

  • 了解快速排序算法的工作原理。 我本来期望... - 如果你有一些期望,你应该证明它们是合理的。
  • 只是谷歌快速排序
  • "另外请注意,5 或 4 永远不会与 2 或 1 进行比较。"但是 5 与 4 进行比较,4 与 3 进行比较,3 与 2 和 1 进行比较。排序满足transitivity,因此这些比较提供了足够的信息来知道5 &gt; 1(例如)。跨度>
  • 请注意,qsort() 未指定使用快速排序算法。

标签: c arrays qsort


【解决方案1】:

在研究了“QuckSort”之后,它变得更有意义了。 我修改了示例以添加额外的打印语句。

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

int values[] = { 5,4,3,2,1,0};
int sizeOfArray = sizeof(values)/sizeof(int);

int cmpfunc (const void * a, const void * b) 
{
    int n = 0;
   printf("Comparing %d and %d  current array looks like this :" ,*(int*)a, *(int*)b);
   for( n = 0 ; n < sizeOfArray; n++ ) 
   {
      printf("%d ", values[n]);
   }
   printf("\n");
   return ( *(int*)a - *(int*)b );
}

int main () {
   int n;
   printf("Size of Array : %d\n", sizeOfArray);
   printf("Before sorting the list is: \n");
   for( n = 0 ; n < sizeOfArray; n++ ) 
   {
      printf("%d ", values[n]);
   }

   printf("\n");

   qsort(values, sizeOfArray, sizeof(int), cmpfunc);

   printf("\nAfter sorting the list is: \n");
   for( n = 0 ; n < sizeOfArray; n++ ) {   
      printf("%d ", values[n]);
   }

   return(0);
}

在阅读了维基百科页面并打印出数组的状态后,每次它都有意义并且与图表流程相匹配。

Size of Array : 6
Before sorting the list is: 
5 4 3 2 1 0 
Comparing 4 and 3  current array looks like this :5 4 3 2 1 0 
Comparing 5 and 3  current array looks like this :5 3 4 2 1 0 
Comparing 5 and 4  current array looks like this :5 3 4 2 1 0 
Comparing 1 and 0  current array looks like this :3 4 5 2 1 0 
Comparing 2 and 0  current array looks like this :3 4 5 2 0 1 
Comparing 2 and 1  current array looks like this :3 4 5 2 0 1 
Comparing 3 and 0  current array looks like this :3 4 5 0 1 2 
Comparing 3 and 1  current array looks like this :3 4 5 0 1 2 
Comparing 3 and 2  current array looks like this :3 4 5 0 1 2 

After sorting the list is: 
0 1 2 3 4 5 

【讨论】:

  • 对于最后 3 次比较,我注意到数组没有改变它的顺序。对于最后 3 次比较,这些数组顺序不应该有所不同吗?
  • 在进行交换之前提前展望可能会加快速度。我还没有真正研究过算法,但我认为此时它基本上知道3、4和5相互之间是有序的,0、1和2相互之间是有序的。所以现在它正在弄清楚这些部分是如何相互关联的。它看到 3 大于 0,但不是在 0 之后移动 {3,4,5},而是针对 1 进行检查。看到它属于 1 之后的某个位置,然后检查 2。看到它属于 2 之后,并且在 2 之后什么都没有,因此找到了 {3,4,5} 所属的位置。
  • 既然这个“快速排序”是关于效率的,你所说的有道理。如果您正在搜索何时可以完成一次移动,为什么还要每次都进行移动。谢谢。
  • @UnhandledException:比较没有理由导致元素顺序发生任何变化。在进行比较之前,您不知道是否需要进行更改。比较可能会告诉您需要更改,或者可能会告诉您不需要更改。如果不需要更改,则不进行更改。考虑一下如果将已经排序的数组传递给qsort 会发生什么。然后它根本不需要进行任何更改。但在进行多次比较之前,它无法知道这一点。
  • @Eric - 基于返回值的规则 if ">0 p1 指向的元素在 p2 指向的元素之后" 这被解释为它们实际上交换但重新读取并且它没有'没有说明发生了交换,只是注意 p1 在 p2 之后,这与您发布的内容一致。谢谢。
猜你喜欢
  • 2011-10-19
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-29
  • 2019-06-05
相关资源
最近更新 更多