【问题标题】:C Sort Algorithm Not Outputting Correct Values?C排序算法没有输出正确的值?
【发布时间】:2017-08-18 11:33:54
【问题描述】:

这里是 C 的新手。我正在制作一个程序,该程序将对随机整数列表进行排序和搜索以用于学习目的,并尝试实现冒泡排序,但在调试期间在我的控制台中得到奇怪的结果。

我有一个这样的数组:

arr[0] = 3
arr[1] = 2
arr[2] = 1

因此,如果我要将此列表从小到大排序,则应该是相反的顺序。相反,我的排序函数似乎在逻辑上存在缺陷,并且正在输出以下内容。

arr[0] = 0
arr[1] = 1
arr[2] = 2

显然我是新手,因为知道得更多的人可能会很快发现我的错误。

find.c

/**
 * Prompts user for as many as MAX values until EOF is reached, 
 * then proceeds to search that "haystack" of values for given needle.
 *
 * Usage: ./find needle
 *
 * where needle is the value to find in a haystack of values
 */

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

#include "helpers.h"

// maximum amount of hay
const int MAX = 65536;

int main(int argc, string argv[])
{
    // ensure proper usage
    if (argc != 2)
    {
        printf("Usage: ./find needle\n");
        return -1;
    }

    // remember needle
    int needle = atoi(argv[1]);

    // fill haystack
    int size;
    int haystack[MAX];
    for (size = 0; size < MAX; size++)
    {
        // wait for hay until EOF
        printf("\nhaystack[%i] = ", size);
        int straw = get_int();
        if (straw == INT_MAX)
        {
            break;
        }

        // add hay to stack
        haystack[size] = straw;
    }
    printf("\n");

    // sort the haystack
    sort(haystack, size);

    // try to find needle in haystack
    if (search(needle, haystack, size))
    {
        printf("\nFound needle in haystack!\n\n");
        return 0;
    }
    else
    {
        printf("\nDidn't find needle in haystack.\n\n");
        return 1;
    }
}

helpers.c

#include <cs50.h>

#include "helpers.h"
#include <stdio.h>
/**
 * Returns true if value is in array of n values, else false.
 */
bool search(int value, int values[], int n)
{
    // TODO: implement a searching algorithm
    return false;
}

/**
 * Sorts array of n values.
 */
void sort(int values[], int n)
{
    // TODO: implement an O(n^2) sorting algorithm
    int tmp = 0;
    int i = 0;
    bool swapped = false;
    bool sorted = false;

    for (int i = 0; i < n; i++)
    {
        printf("%i\n", values[i]);
    }

    while (!sorted)
    {
        //check if number on left is greater than number on right in sequential order of the array.
        if (values[i] > values[i+1])
        {
            tmp = values[i];
            values[i] = values[i+1];
            values[i+1] = tmp;
            swapped = true;
        }
        if (i >= n - 1)
        {
            if (!swapped)
            {
                //No swaps occured, meaning I can assume the list is sorted.
                for (int i = 0; i < n; i++)
                {
                    printf("%i\n", values[i]);
                }
                sorted = true;
                break;
            } else {
                //A swap occured on this pass through of the array.  Set the flag back to false for the next pass through, repeating until no swaps are detected.  (Meaning every number is in its proper place.)
                i = 0;
                swapped = false;
            }
        } else {
            i++;
        }
    }
}

【问题讨论】:

  • 您真的需要提供自己的sort 实现吗? C有一个in the standard library
  • 在调试器中单步调试程序,并检查变量的值。
  • @CodeDifferent 他显然是在学习算法。
  • @Barmar 嗨,我已经这样做了,但是对我最终得到 0 的方式有点困惑。:( 显然我的输出实际上非常接近它应该是的,只是似乎在某处减少 1 个数字。我已经调整了一些条件,但似乎仍然会遇到这个问题。
  • @CodeDifferent 我感谢您的回复,但这纯粹是出于教育目的。

标签: c arrays algorithm sorting cs50


【解决方案1】:

问题是您在进行测试之前进行比较和交换if (i &gt;= n - 1)。这意味着它将在i == n-1 时比较values[i] &gt; values[i+1],因此它将访问数组边界之外,这是未定义的行为。在您的情况下,数组后面的内存中恰好有 0,所以它被交换到数组中,然后它被排序到数组的开头。

改变

    if (values[i] > values[i+1])

    if (i < n-1 && values[i] > values[i+1])

【讨论】:

  • @PaulOgilvie 我已经更改了答案,请看一下。
  • @Barmar 我发誓我以为我已经尝试将 AND 条件添加到第一次检查中,并得到了相同的结果,但只是再次尝试,我得到了正确的输出。我将继续并将其标记为答案。谢谢!
  • 不错,巴马尔! (将 cmp/swap 移到 else 部分会更好。)
  • @PaulOgilvie 可能有更好的方法来重构它,但我想将我的更改保持在最低限度。
  • 是的,我是这么想的。对 OP 而言,这可能比对您而言更重要。这样你的观点就更清楚了。
【解决方案2】:

您可以在数组0..n-1 中交换的最高条目是n-2n-1。所以i 可能不会大于n-2 所以i+1 访问n-1

因此您的支票必须是:

if (i > n - 2)

【讨论】:

  • if (i &gt; n -1) 中的代码块从不进行任何交换,所以这不是问题。它要么跳出循环,要么设置i = 0
  • 是的,刚刚尝试了这个解决方案,似乎合法。虽然得到了相同的输出。废话。 @保罗奥格尔维
  • @Barmar,问题是else i++; 现在会越界。
  • 大卫,在输入后排序前打印数组;然后排序,然后再次打印。我看不出排序还有什么问题。
  • @PaulOgilvie 会这样做,但我只想提一下我做了检查 i > n - 3 并且它输出了正确的结果。我真的很困惑为什么,但这一定是问题所在。
猜你喜欢
  • 2017-10-24
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 2018-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
相关资源
最近更新 更多