在阵列中向上移动对象

Shifting Objects Up in an Array

本文关键字:移动 对象 阵列      更新时间:2023-10-16

我正在创建一个程序,该程序在数组大小为 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 << "nnSorted 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;   
}

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

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

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

请注意,这不是最有效的解决方案,但它会让您入门。

另请注意,我将 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);

将数字(而不是字节代码)附加到数字的末尾。或者,如果您有 C++11:

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

我看到了几个问题。

  1. 表达式"word" + static_cast<char>(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;
             }
          }
       }
    }
    

有两个问题:

  1. wordArr[randomNum].name = "word" + static_cast<char>(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;
                }
            }
        }
    

您的算法对数组进行排序,但随后再次丢失排序。

您希望仅在i > 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向下推,但我们不希望这样,我们希望间隙(零)进入数组的末尾,因此我们只需要在它们要走高而不是更低时才交换 eleemnts,这相当于说当i > 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;
    }
  }