我正在创建一个程序,在数组大小为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;
}
答案 0 :(得分:1)
如果我正确理解您的要求,您希望将所有非空白条目移动到数组的开头。为此,您需要一个这样的算法,例如:
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);
将数字而不是字节代码附加到数字的末尾。或许,if you have C++11:
wordArr[randomNum].name = "word" + std::to_string(i);
答案 1 :(得分: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)
。
将具有非空名称的对象移动到具有空名称的对象的逻辑对我来说没有意义。它显然不适合你。以下更新版本适用于我:
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;
}
}
}
}
答案 2 :(得分:1)
有两个问题:
wordArr[randomNum].name = "word" + static_cast<char>(i);
这不是你想要的,如果你想要你的名字正确生成你需要这样的东西:
wordArr[randomNum].name = "word " + std::to_string(i);
你的排序循环不能达到你想要的效果,它只是检查你所说的“差距”,你需要这样的东西:
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;
}
}
}
答案 3 :(得分:0)
您的算法对数组进行排序,然后再次丢失排序。
您只想在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
向下,但我们不希望这样,我们希望间隙(零)到达数组的末尾,因此我们只需要在他们去的时候交换元素更高,而不是更低,这相当于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;
}
}