【问题标题】:Shifting Objects Up in an Array在数组中向上移动对象
【发布时间】:2018-04-19 11:17:04
【问题描述】:

我正在创建一个程序,该程序在数组大小为 8 的随机位置创建一个对象数组。创建后,我需要对它们进行排序,以便数组中的所有对象都向上移动,因此没有间隙存在于他们之间。我快到了,但我似乎无法让它们交换到数组中的索引 0,而是交换到索引 1。有什么建议吗? (必须按照我的方式完成,而不是使用其他排序算法或其他)

#include <iostream>
#include <string>
#include <ctime>
using namespace std;

struct WordCount {
    string name = "";
    int count = 0;
};

int main() {
    cout << "Original random array: " << endl;

    srand(static_cast<int>(time(0)));

    int i = 0;
    WordCount wordArr[8];

    while (i < 4) {
     int randomNum = 0 + (rand() % static_cast<int>(7 + 1));

     if(wordArr[randomNum].name == "") {
          wordArr[randomNum].name = "word" + static_cast<char>(i);
          wordArr[randomNum].count = i;
          i++;
     }
    }

    int j = 0;
    while (j < 8) {
      cout << wordArr[j].name << " " << wordArr[j].count << endl;
      j++;
    }

    cout << "\n\nSorted array: " << endl;

    for (int i = 7; i >= 0; i--) {
      for (int j = 0; j <= 7; j++) {
        if (wordArr[i].name != "") {
          if (wordArr[j].name == "") {
            WordCount temp = wordArr[i];
            wordArr[i] = wordArr[j];
            wordArr[j] = temp;
          }
        }
      }
    }

    int k = 0;
    while (k < 8) {
      cout << wordArr[k].name << " " << wordArr[k].count << endl;
      k++;
    }


    return 0;   
}

【问题讨论】:

  • C++ 数组没有间隙。
  • @juanchopanza 他的意思是零。检查我的答案。
  • 一旦你完成了这个手动操作的练习,请查看std::partition,它是作为标准一部分的经过良好测试的单个函数调用。请不要错误地认为标准算法会带来惩罚或需要外部库,或者在某种程度上不是“真正的”C++。它们不是,它们是 C++ 的一部分,供您使用。

标签: c++ arrays algorithm loops sorting


【解决方案1】:

有两个问题:

  1. wordArr[randomNum].name = "word" + static_cast&lt;char&gt;(i); 这不是你要找的东西,如果你想让你的名字正确生成,你需要这样的东西:

    wordArr[randomNum].name = "word " + std::to_string(i);
    
  2. 你的排序循环没有做你想做的事,它只是检查你所说的“差距”,你需要这样的东西:

    for (int i = 0; i < 8; ++i) {
            for (int j = i+1; j < 8; ++j) {
                if (wordArr[i].name == "" || (wordArr[i].count < wordArr[j].count)) {
                    WordCount temp = wordArr[i];
                    wordArr[i] = wordArr[j];
                    wordArr[j] = temp;
                }
            }
        }
    

【讨论】:

  • 使用 4 个空格来格式化代码在普通文本中有效。在列表下,您必须使用8 空格。我无法快速找到记录的位置。
【解决方案2】:

我发现了几个问题。

  1. "word" + static_cast&lt;char&gt;(i); 表达式没有做你希望做的事情。

    相当于:

    char const* w = "word";
    char const* p = w + i;
    

    i 为2 时,p 将为"rd"。您需要使用std::string("word") + std::to_string(i)

  2. 将具有非空名称的对象移动到具有空名称的对象的逻辑对我来说没有意义。它显然不适合你。以下更新版本适用于我:

    for (int i = 0; i <= 7; ++i) {
    
       // If the name of the object at wordArr[i] is not empty, move on to the
       // next item in the array. If it is empty, copy the next object that
       // has a non-empty name.
       if ( wordArr[i].name == "") {
    
          // Start comparing from the object at wordArr[i+1]. There
          // is no need to start at wordArr[i]. We know that it is empty.
          for (int j = i+1; j <= 7; ++j) {
             if (wordArr[j].name != "") {
                WordCount temp = wordArr[i];
                wordArr[i] = wordArr[j];
                wordArr[j] = temp;
             }
          }
       }
    }
    

【讨论】:

    【解决方案3】:

    您的算法对数组进行了排序,但随后又失去了排序。

    您只想在i &gt; j 时交换元素,以便仅将元素推到顶部。因此,您需要更改:

    if (wordArr[j].name == "")
    

    到这里:

    if (wordArr[j].name == "" && i > j)
    

    考虑这个数组示例:

     0
    ord 1
     0
     0
    rd 2
    word 0
    d 3
     0
    

    您的代码会将其排序为:

    d 3
    ord 1
    word 0
    rd 2
     0
     0
     0
     0
    

    但是当 i = 3 时,它会尝试填充第 5 个单元格,并将其与 rd 2 交换,这不是我们想要的。

    这会将rd 2 向下推,但我们不希望这样,我们希望间隙(零)到达数组的末尾,因此我们只需要在元素要变高时交换元素,而不是更低,相当于i &gt; j时说的。


    PS:如果您是初学者,请跳过该部分。

    您可以通过使用一个 if 语句和一个 break 关键字来优化内部循环,如下所示:

      for (int j = 0; j <= 7; j++) {
        if (wordArr[i].name != "" && wordArr[j].name == "" && i > j) {
            WordCount temp = wordArr[i];
            wordArr[i] = wordArr[j];
            wordArr[j] = temp;
            break;
        }
      }
    

    【讨论】:

      【解决方案4】:

      如果我正确理解您的要求,您希望将所有非空白条目移动到数组的开头。为此,您需要这样的算法,例如:

      for i = 0 to 7
          if wordArr[i].name is blank
              for j = i + 1 to 7
                if wordArr[j].name is not blank
                    swap [i] and [j]
                    break
      

      所以,从头开始,如果我们遇到一个空白条目,我们期待下一个非空白条目。如果我们找到这样的条目,我们交换空白条目和非空白条目,然后 break 循环再次寻找下一个空白条目。

      请注意,这不是最有效的解决方案,但可以帮助您入门。

      另请注意,我会将 4 和 8 替换为如下定义:

      #define MAX_ENTRIES (8)
      #define TO_GENERATE_ENTRIES (4)
      

      最后:

      wordArr[randomNum].name = "word" + static_cast<char>(i);
      

      那不会做你想做的事;试试:

      wordArr[randomNum].name = "word" + static_cast<char>('0' + i);
      

      将数字而不是字节码附加到数字的末尾。或者,if you have C++11:

      wordArr[randomNum].name = "word" + std::to_string(i);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-05-11
        • 1970-01-01
        • 1970-01-01
        • 2015-02-22
        • 2018-04-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多