【问题标题】:Local variable loses its value: selection sort algorithm局部变量失去价值:选择排序算法
【发布时间】:2017-01-03 07:31:26
【问题描述】:

我之前为冒泡排序算法测试了名为“交换”的相同变量,它运行良好。现在,通过选择排序,变量即使在递增之后也会失去它的值。 任何帮助将不胜感激。

int list[] = {10, 5, 6, 3, 4, 11, 9, 7, 2};
int min = list[0], pos = 0, temp_max = 0;

// Loop until no swap is needed
for (int j = 0, n = sizeof(list) / sizeof(int); j < n; j++)
{
    int swaps = 0, 

    // Iterate through array to find min value
    for (int i = j, y = sizeof(list) / sizeof(int); i < y; i++)
    {
        if (list[i] < min)
        {
            min = list[i];
            pos = i;
        }
    }

    // Insert min value in left most position and add 1 to swaps, meaning array is not yet sorted
    if (pos > j)
    {
        temp_max = list[j];
        list[j] = min;
        list[pos] = temp_max;
        swaps++;
    }

    // The error might occur here: "swaps" keeping value 0 after previous if statement ends
    printf ("swaps = %d\n", swaps);

    // If no swaps ocurred, array is sorted
    if (swaps == 0)
    {       
        // Print sorted array and return  
    }
}

【问题讨论】:

  • 您可以在两个循环中使用n,因为y 始终与n 具有相同的值。不过,这不会影响您的问题。
  • 1) int swaps = 0, 无法编译。也许您想要int swaps = 0;; 而不是, 2) 解决第一个问题后,我看不到swaps 有任何问题 - 请参阅ideone.com/Z40FXl - 它增加得很好。确定您发布了正确的代码?

标签: c variables scope selection-sort


【解决方案1】:

将声明 int swaps = 0 移到 for 循环之外。


换句话说,改变这个:

for (int j = 0, n = sizeof(list) / sizeof(int); j < n; j++)
{
    int swaps = 0;
    ...
}

到这里:

int swaps = 0;
for (int j = 0, n = sizeof(list) / sizeof(int); j < n; j++)
{
    ...
}

【讨论】:

  • 怎么回事?如果它在 1 次迭代后排序怎么办?
  • @coderredoc:怎么回事?如果它在 1 次迭代后排序,那么一切都很好。 OP 在for 循环的范围内声明了这个变量,所以它显然只在这个范围内保留它的值(即,在每次迭代开始时初始化为 0)。
  • @coderredoc:我只提到了 OP 关于局部变量“丢失”其值的投诉(在代码中也表示为 The error might occur here: "swaps" keeping value 0 after previous if statement ends)。当然可能还有其他问题。
  • 编译时启用警告(例如-Wall -Wextra)将帮助您发现问题。阅读警告和错误(它们非常好),这将有助于缩小您的问题范围。没有魔法,只要做到足以让它沉入其中......
  • @MarcelloScattolini:它确实与变量范围有关。 swaps 变量的范围是 for 循环内部,因此在每次迭代中,该变量都被声明并初始化为 0
【解决方案2】:

非常感谢大家。在您的帮助下,我已经解决了这个问题。原来错误与变量范围(它被声明的地方)有关。按照下面的工作代码。

int main (void)
{

//Declare list to be sorted and other variables
int list[] = {9, 5, 7, 8, 4, 3, 2, 1, 6};
int minValPos = 0, maxTempVal = list[0];

for (int j = 0, siz = sizeof (list) / sizeof (int); j < siz; j++)
{
    int swaps = 0, minVal = list[j];

    // Look for min value after each j iteration
    for (int i = j; i < siz; i++)
    {

        // Find minimum value (minVal) and store its position (minValPos)
        if (list[i] < minVal)
        {
            minVal = list[i];
            minValPos = i;
        }

    }

    // Once with MinVal pinpointed, proceed to swap with jth item
    if (minValPos > j)
    {
        maxTempVal = list[j];
        list[j] = minVal;
        list[minValPos] = maxTempVal;
        swaps++;
    }

    // When array did not need any swaps, it means it is sorted
    if (swaps == 0)
    {
        for (int r = 0; r < siz; r++)
        {
            printf ("Position [%d] = %d\n", r, list[r]);
        }
    }
}

}

【讨论】:

    【解决方案3】:

    这意味着您的 if 声明在此期间并未成为现实。

    min应该在j的每个循环中设置。

    min=list[j] in for(j=...){min=list[j]; ... }

    还有pos=j

    【讨论】:

    • Coderredoc,感谢您的帮助。一个观察:当 if 语句执行时,交换值更改为 1。但是如果我 printf 在右括号后立即交换,值返回到 0。我猜它与变量范围有关。再次感谢!
    • 感谢@BLUEPIXY,观察得很好。
    • @MarcelloScattolini 你说的是不可能的......如果if被执行并交换更改,那么它就无法打印0
    • 我的DV的原因?
    • 请问什么是DV?谢谢!
    【解决方案4】:

    添加到其他答案,这将专门解决您的代码问题,您也可以像这样处理选择排序算法。

    为数组编写此算法的步骤:

    1.编写一个辅助函数来查找数组中最大元素的索引:

    size_t index_of_largest(int list[], size_t n) {
        size_t i, biggest;
    
        biggest = 0;
        for (i = 0; i < n; i++) {
            if (list[i] > list[biggest]) {
                biggest = i;
            }
        }
        return biggest;
    }
    

    2. 遍历i=ni=1,找到list[0]list[i-1] 之间的最大值。找到此元素后,将其交换到最后一个位置。该函数可能如下所示:

    void sort_list(int list[], size_t n) {
        size_t i, biggest;
    
        for (i = n; i > 0; i--) {
            biggest = index_of_largest(list, i);
            int_swap(&list[biggest], &list[i-1]); /* swapping function */
        }
    }
    

    3. 考虑到这些想法,您可以编写一个简单的算法版本,如下所示:

    #include <stdio.h>
    
    void sort_list(int list[], size_t n);
    size_t index_of_largest(int list[], size_t n);
    void print_array(int list[], size_t n);
    void int_swap(int *x, int *y);
    
    int main(void) {
        int list[] = {10, 5, 6, 3, 4, 11, 9, 7, 2};
        size_t n = sizeof list / sizeof *list;
    
        printf("Before: ");
        print_array(list, n);
    
        sort_list(list, n);
    
        printf("After: ");
        print_array(list, n);
    
        return 0;
    }
    
    void sort_list(int list[], size_t n) {
        size_t i, biggest;
    
        for (i = n; i > 0; i--) {
            biggest = index_of_largest(list, i);
            int_swap(&list[biggest], &list[i-1]);
        }
    }
    
    size_t index_of_largest(int list[], size_t n) {
        size_t i, biggest;
    
        biggest = 0;
        for (i = 0; i < n; i++) {
            if (list[i] > list[biggest]) {
                biggest = i;
            }
        }
        return biggest;
    }
    
    void print_array(int list[], size_t n) {
        size_t i;
    
        for (i = 0; i < n; i++) {
            printf("%d ", list[i]);
        }
        printf("\n");
    }
    
    void int_swap(int *x, int *y) {
        int temp;
        temp = *x;
        *x = *y;
        *y = temp;
    }
    

    输出:

    Before: 10 5 6 3 4 11 9 7 2
    After: 2 3 4 5 6 7 9 10 11
    

    编译:

    gcc -Wall -Wextra -o progname progname.c
    

    【讨论】:

    • 很高兴您知道如何编写选择排序。您不认为OP也应该有机会自己解决吗?此处的 OP 问题具体是关于为什么 swaps 变量会失去其价值,而这个答案根本没有解决这个问题。
    • Caleb,在这个社区中,我学到了很多东西,这是一种学习体验。到目前为止,我将发布我的看法。谢谢。
    • @Caleb,我不明白为什么您认为向 OP 展示另一种执行此算法的方法是不可接受的。 OP 将从看到不同的方法中学到很多东西,而不仅仅是指出他在代码中的错误,正如其他 3 个答案已经完成的那样。我不知道你是如何学习编程的,但我知道这对任何学习算法的人都有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多