【问题标题】:Recursive selection in C++ not fully workingC ++中的递归选择不完全工作
【发布时间】:2017-06-28 10:12:49
【问题描述】:

我正在尝试编写一个递归函数,通过选择对一个小数组进行排序。我可以加载并运行所有内容,但是当数组为{3, 1, 8, 5} 时的输出一直输出为{1, 3, 3, 3}。我认为这与最小值的分配方式有关,但我坚持到底在哪里。有什么建议吗?

#include <iostream>
#include <conio.h>
#include <array>

using namespace std;

int arrLength = 4;
int minimum;
int counter = 0;

int sortedArr[];
int tempArr[];

void sortFunc(int, int);

int valueArr[4] = { 3,1,8,5 };
int tempArr[4] = {};

void main() {

    cout << "Before sorting..." << endl;

    for (int i = 0; i < 4; i++) {
        cout << valueArr[i] << " ";
    }

    cout << endl;

    sortFunc(4, counter);

    cout << "After sorting..." << endl;

    for (int i = 0; i < 4; i++) { //either broken here
        cout << tempArr[i] << " ";
    }

    _getch();
}

void sortFunc(int size, int counter) {
    minimum = valueArr[0];

    for (int i = 1 + (counter); i <  size; i++) { //or here
        if (valueArr[i] < minimum) {
            minimum = valueArr[i];
        }
    }

    tempArr[counter] = minimum;

    if (counter < size) {
        counter++;
        sortFunc(size, counter);
    }
}

【问题讨论】:

  • 如果您以前没有使用过调试器,那么现在是学习它的最佳时机。使用调试器,您可以逐行单步执行代码,同时监视变量及其值。能够使用调试器对于任何程序员来说都是一项至关重要的技能。
  • 哦,你有 一些 检查 counter 没有越界,但不是真正需要的地方,所以你 离开界限并具有未定义的行为。如果您使用调试器,这将非常明显。

标签: c++ arrays algorithm recursion selection-sort


【解决方案1】:

我无法清楚地看到如何稍微调整您的策略以使您的功能正常工作。我认为您需要通过交换元素对数组进行适当的排序。为此,您需要:

  1. 先将valueArr复制到tempArr
  2. tempArr 进行适当的排序。这使valueArr 处于其原始状态。我假设这是你的意图。

main 中,使用:

// Copy valueArr to tempArr
std::copy(valueArr, valueArr+4, tempArr);

sortFunc 中,使用:

void sortFunc(int size, int counter) {
   if ( size == counter )
   {
      return;
   }

    int minimum = tempArr[counter];

    for (int i = 1 + (counter); i <  size; i++) {
        if (tempArr[i] < minimum) {
            minimum = tempArr[i];
            std::swap(tempArr[counter], tempArr[i]); 
        }
    }

    sortFunc(size, counter+1);
}

进一步清理的建议。

  1. 不要使用任何全局变量。
  2. 将所有参数传递给sortFunc
  3. main的返回类型改为int

这是一个清理后的版本。

#include <iostream>
#include <algorithm>

using namespace std;

void sortFunc(int arr[], int, int);

int main() {

    cout << "Before sorting..." << endl;

    int valueArr[4] = { 3,1,8,5 };
    int tempArr[4] = {};

    for (int i = 0; i < 4; i++) {
        cout << valueArr[i] << " ";
    }

    cout << endl;

    // Copy valueArr to tempArr
    std::copy(valueArr, valueArr+4, tempArr);
    sortFunc(tempArr, 4, 0);

    cout << "After sorting..." << endl;

    for (int i = 0; i < 4; i++) { //either broken here
        cout << tempArr[i] << " ";
    }
    cout << endl;
}

void sortFunc(int arr[], int size, int counter) {
   if ( size == counter )
   {
      return;
   }

    int minimum = arr[counter];

    for (int i = 1 + (counter); i <  size; i++) {
        if (arr[i] < minimum) {
            minimum = arr[i];
            std::swap(arr[counter], arr[i]); 
        }
    }

    sortFunc(arr, size, counter+1);
}

【讨论】:

    【解决方案2】:

    我认为你不应该在行初始化最小值

    minimum = valueArr[0];

    而只是将其分配给大数字或使用valueArr[counter + 1]

    这种奇怪行为的原因可能是 valueArr 中的第一个条目实际上比您稍后在数组中遇到的那些小,因此它不会被正确初始化...

    添加:请参阅 INT_MAXnumeric_limits 了解“大量”


    ADD2:无论如何,仔细观察,您的递归概念不正确...如果您打算对数组进行排序,则必须始终将当前元素与您在每次迭代中选择的元素交换。否则,您将开始丢失元素,就像您一样。在任何情况下,递归可能不是解决排序问题的最佳方法......也许尝试两个嵌套循环

    【讨论】:

      【解决方案3】:

      您的代码中有一些基本的逻辑错误,

      void sortFunc(int size, int counter) {
          minimum = 2147483647; // Point 1
          int mytemp;
          for (int i = 0; i <  size; i++) { // Point 3
              if (valueArr[i] < minimum) {
                  minimum = valueArr[i];  //Point 2
                  mytemp = i;
              }
          }
          valueArr[mytemp] = 2147483647;
          tempArr[counter] = minimum;
      
          if (counter < size) {
              counter++;
              sortFunc(size, counter);
          }
      }
      

      1。 minimum 变量应该始终是可能的最大值,您需要跟踪 valueArr 中最小值的索引

      1. valueArr找到一个最小值后,你需要确保你不会再次访问相同的值,所以跟踪它的索引并改变它的值

      2. 循环可迭代从代码中的1+(counter) 开始,如果最小值在此之前怎么办?这就是为什么你需要从头开始。

      我希望你明白我的意思。干杯!

      【讨论】:

        【解决方案4】:

        除了R Sahuanswer 中提供的有用建议和技巧之外,以下函数模板将作为选择排序的递归类似STL 实现 算法:

        #include <iterator>   // std::next
        #include <algorithm>  // std::min_element
        
        template<typename ForwardIt>
        void sortFunc(ForwardIt first, ForwardIt last) {
            // base case
            if (first == last || std::next(first) == last)
                return; // empty range or range with a single element
        
            // recursive case
            auto selected_it = std::min_element(first, last);
            using std::swap;
            swap(*selected_it, *first);
            return selection_sort(++first, last);
        }
        

        这种方式选择排序可以在任何实现operator&lt;的类型上执行,并且不仅限于int(如您的sortFunc())。

        上面的实现允许tail recursion optimisation 发生,所以,如果你要对大数组(或其他集合)进行排序,不要忘记启用它。


        您可以将上面的 sortFunc 函数模板与 C 样式数组一起使用(如您的示例中所示):

        // copy valueArr to tempArr
        std::copy(valueArr, valueArr+4, tempArr);
        // sort tempArr
        sortFunc(tempArr, tempArr+4);
        

        以及任何实现前向迭代器的 STL 容器:

        std::vector<int> vec(valueArr, valueArr+4);
        std::list<int> lst(valueArr, valueArr+4);
        std::forward_list<int> fwdlst(valueArr, valueArr+4);
        
        sortFunc(vec.begin(), vec.end());
        sortFunc(lst.begin(), lst.end());
        sortFunc(fwdlst.begin(), fwdlst.end());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-18
          • 2013-05-22
          • 2011-08-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-10
          相关资源
          最近更新 更多