[英]C++ Condense Two for-loops to Improve Efficiency
我需要從中檢索數據的結構體數組。 該數組包含名稱和分數。
對於一項功能,我必須輸出最高分數和相關名稱。 如果有多種情況,我必須輸出所有名稱。
我不能使用矢量或列表。 (否則,我只想在同一步驟中執行這兩項操作。
這就是我的處理方式:
void highScorer ( player array[], int size )
{ // highScorer
int highScore = 0; //variable to hold the total score
// first loop determines highest score
for ( int i = 0; i < size; i++ ) {
if ( array[i].pointsScored > highScore ) {
highScore = array[i].pointsScored;
}
}
cout << "\nThe highest scoring player(s) were:\n";
// second loop finds players with scores matching highScore and prints their name(s)
for ( int i = 0; i < size; i++ ) {
// when a match is found, the players name is printed out
if ( array[i].pointsScored == highScore ) {
cout << array[i].playerName;
cout << ", scored ";
// conditional will output correct grammar
if ( array[i].pointsScored > 1 ) {
cout << array[i].pointsScored << " points!\n";
}
else {
cout << array[i].pointsScored << " point!\n";
}
}
}
cout << "\n"; // add new line for readability
return;
} // highScorer
我想將其濃縮為一個for循環。 除非有人建議使用一種更有效的方法。 我認為整理數據是不必要的。 另外,如果將其排序,那么如何一步就能確定是否有多個“ highScore”案例。
除了highScore
變量之外,您highScore
創建第二個變量,例如std::list
(或手動鏈接列表,甚至是一個小的數組,具體取決於允許使用的變量)。 在此列表中,您可以跟蹤實際擁有當前高分的人的指數。 如果找到新的高分,則清除該列表並添加具有新高分的人。 如果發現某人的得分最高,您只需將其添加到列表中。
然后在循環之后,您只需要打印具有此列表中索引的播放器,而無需再次查找誰擁有最高分。
一種解決方案是在搜索高分時記錄玩家的姓名。 如果它等於當前的最高分,則將一個附加名稱附加到“名稱集合字符串”中,如果更高,則將名稱空白,並記錄新的高分和新名稱。 我ostringstream
名稱的打印輸出實現為ostringstream
以確保您不會在緩沖區上運行。 然后,完成后,打印出一組名稱。
只要您經過第一(唯一)遍,就應保留得分最高的索引集。 然后,完成后,您將已經擁有與該最高分數相對應的一組索引。 用我剛剛編寫的語言的偽代碼:
int highestSoFar = 0;
list indexesOfHighScore = new list();
for (int i = 0; i < scores.count; i++) {
if (scores[i] > highestSoFar) {
highestSoFar = scores[i];
indexesOfHighScore.empty();
}
if (scores[i] == highestSoFar) {
indexesOfHighScore.add(i);
}
}
// Now I know the highest score, and all the indexes of entries that correspond to it.
如果沒有可用的動態列表,則該列表可以是與scores數組大小相同的靜態數組,以確保其始終足夠大。
現在,您的第一個循環是跟蹤高分。 如果它還跟蹤所有匹配的名稱,則可以在循環結束時輸出名稱。 您仍然需要第二個循環來遍歷這些名稱,這是不可避免的。
只需少量的存儲成本,您就可以在同一遍中計算出高分和各個玩家:
player ** highScorer ( player array[], int size )
{
player ** result = new player*[size + 1]; // The +1 handles the case where everyone ties
int highScore = 0;
int foundAt = 0;
for ( int i = 0; i < size; i++ )
{
if ( array[i].pointsScored > highScore )
{
highScore = array[i].pointsScored;
foundAt = 0;
}
if ( array[i].pointsScored == highScore )
{
result[foundAt] = &(array[i]);
foundAt++;
}
}
result[foundAt] = null; // Stopping condition, hence the +1 earlier
return result; // Remember to delete[] the resulting array
}
然而。
那不會給你輸出。 如果要輸出結果,您仍然需要第二個循環。
void outputScores ( player ** result )
{
cout << "\nThe highest scoring player(s) were:\n";
for ( int i = 0; result[i] != null; i++ )
{
cout << result[i]->playerName;
cout << ", scored ";
if ( result[i]->pointsScored == 1 )
cout << "1 point!\n";
else
cout << result[i]->pointsScored << " points!\n";
}
cout << "\n";
delete [] result;
}
要回答您最初的問題,我認為沒有任何方法可以在一個循環中找到並輸出所有得分較高的球員。 即使對分數數組進行預排序也會比您已經擁有的要差。
與其保留完整的匹配索引集,不如保留第一個和最后一個。 這樣一來,您就可以跳過搜索整個列表,並且在得分最高的情況下完全避免第二次通過。
void highScorer( player* array, int size )
{
int highScore = 0;
int firstHighI = -1, lastHighI = -1;
for ( int i = 0; i < size; i++ ) {
if ( array[i].pointsScored > highScore ) {
highScore = array[i].pointsScored;
firstHighI = i;
}
if ( array[i].pointsScored == highScore ) {
lastHighI = i;
}
}
if (firstHighI >= 0) {
std::cout << "\nThe highest scoring player(s) were:\n";
for ( int i = firstHighI; i < lastHighI; i++ ) {
if ( array[i].pointsScored == highScore ) {
std::cout << array[i].playerName << ", ";
}
}
std::cout << array[lastHighI].playerName << " with a score of " << highScore;
if ( highScore != 1 ) {
std::cout << " points!\n";
}
else {
std::cout << " point!\n";
}
}
std::cout << "\n";
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.