【问题标题】:C Basic Sort AlgorithmC 基本排序算法
【发布时间】:2017-03-01 05:27:17
【问题描述】:

我并不真正理解这个使用嵌套 For 循环的基本排序算法背后的过程:

for(i=0; i<MAX; i++){
        for(j=i; j<MAX; j++){
            if(data[i] > data[j]){
                tmp = data[i];
                data[i] = data[j];
                data[j] = tmp;
            }
        }
    }

如果j=i 那么它不会只是循环并比较相同的数字,因为 i 和 j 在循环中都从 0 开始?

我尝试在谷歌上搜索有关这段特定代码的解释,但找不到任何有用的信息。

完整程序:

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

#define MAX 10

int main()
{
    int data[MAX];
    int i, j, tmp;

    for(i=0;i<MAX;i++){
        printf("Enter number %d: ", i);
        scanf("%d", &data[i]);
    }

    for(i=0; i<MAX; i++){
        for(j=i; j<MAX; j++){
            if(data[i] > data[j]){
                tmp = data[i];
                data[i] = data[j];
                data[j] = tmp;
            }
        }
    }

    printf("\nSorted List:\n");
    for(i=0;i<MAX;i++){
        printf("Item %d: %d\n", i, data[i]);
    }
}

【问题讨论】:

  • 出于好奇,您从何处获得此代码?似乎有人无法在选择排序和冒泡排序之间做出决定,然后最终得到了一个比两者都差的混蛋版本。
  • 我一直在关注 Youtube 上的 C 教程,这个特定的代码来自这个视频:youtu.be/Dtbqs0M-B-s?t=19m9s
  • 是的,在该练习的上下文中这是一个不错的算法,但请不要在其他地方使用它;-)

标签: c algorithm sorting


【解决方案1】:

这个算法是一个虚拟化的selection sort - 它与维基百科上的选择排序描述相匹配:

该算法将输入列表分为两部分:已排序项的子列表,在列表的前面(左)从左到右构建,剩余待排序项的子列表占据列表的其余部分。最初,已排序的子列表为空,未排序的子列表是整个输入列表。该算法通过在未排序的子列表中找到最小(或最大,取决于排序顺序)元素,将其与最左边的未排序元素交换(交换)(将其按排序顺序),并将子列表边界向右移动一个元素.

但确实不是伪算法,因为它会进行一些不必要的交换。

第一内轮,i等于j,比较data[i] &gt; data[j]为假,不执行swap。

然后,j 将递增,现在它将ith 值与i + 1th 值进行比较。

为避免徒劳的比较,请将j 初始化为i + 1

for (i = 0; i < MAX; i++) {
    for (j = i + 1; j < MAX; j++) {
        if (data[i] > data[j]) {
            tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
        }
    }
}

它与普通选择排序的不同之处在于它会在ith 位置进行不必要的交换。普通的选择排序找到最小的索引并且对每个元素只做一次交换:

for (i = 0; i < MAX; i++) {
    int min = i;
    for (j = i + 1; j < MAX; j++) {
        if (data[min] > data[j]) {
            min = j;
        }
    }

    tmp = data[min];
    data[min] = data[i];
    data[i] = tmp;
}

尽管如此,原来的匹配选择排序的描述(运行时间是相同的,虽然常量由于不必要的交换而变得更糟):

算法通过在未排序的子列表中找到最小(或最大,取决于排序顺序)元素,与最左边的未排序元素交换(交换)(按排序顺序)

实现为算法在未排序的子列表中找到最小的元素,并在遍历列表时将当前最小的项与最左边的未排序项交换


C 标准库中已经包含qsort,可以使用它来代替重新发明轮子——我们只需要编写比较函数:

#include <stdlib.h>

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

int main(void) {
    ...
    qsort(data, MAX, sizeof(int), compare_ints);
    ...
}

【讨论】:

  • 不是选择排序。 OPs 代码与维基百科上的伪代码不匹配
  • @StoryTeller 是的,但它也不是冒泡排序。这是一个带有不必要交换的选择排序,因此 i 值来回交换 - 如果一个人跟踪最小值,那么这将有更少的交换。
  • 更好。好多了。
【解决方案2】:

不,它不会循环,因为您只需将data[i]data[i] 交换两次,尽管最好像这样重写这段代码:

for(i=0; i<MAX-1; i++){
    for(j=i+1; j<MAX; j++){
        if(data[i] > data[j]){
            tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
        }
    }
}

但这两个代码是一样的。

这段代码使用的算法是bubble sort。如果您想更好地了解它的作用,请查看维基百科文章。

【讨论】:

    【解决方案3】:

    这是Bubble Sort。它的要点是它交换它发现的任意两个相邻的值,直到所有的值都按顺序排列。

    【讨论】:

    • 这不是冒泡排序。
    • @AnttiHaapala - 这是冒泡排序,通过立即交换很明显。
    • @StoryTeller 这是带有不必要交换的选择排序,但不是冒泡排序。冒泡排序总是只比较相邻的元素。
    • @AnttiHaapala - 这是一个没有提前停止标志的冒泡排序。效率低下,但仍然是冒泡排序。
    • @StoryTeller Bubblesort:“比较每对相邻的项目,如果它们的顺序错误,则交换它们”。不它不是。这些事实不值得讨论。我是对的,你错了。
    【解决方案4】:

    代码

    for(i=0; i<MAX; i++){
            for(j=i; j<MAX; j++){
                if(data[i] > data[j]){
                    tmp = data[i];
                    data[i] = data[j];
                    data[j] = tmp;
                }
            }
        }
    

    显然不会按预期工作。它基本上需要比较数组的每个元素并对它们进行排序。基本上是时间复杂度为 O(n^2) 的冒泡排序。

    而不是 j=i

    应该是 j=i+1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      • 1970-01-01
      • 2013-01-12
      • 1970-01-01
      • 2015-04-27
      相关资源
      最近更新 更多