0

我有一个结构数组,我需要从中检索数据。该数组包含名称和分数。

对于一个函数,我必须输出最高分和相关名称。如果有多种情况,我必须输出所有名称。

我不能使用向量或列表。(否则我会)我只想在同一步骤中执行这两个操作。

这就是我的处理方式:

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”案例。

4

6 回答 6

3

除了您的highScore变量之外,您还创建了第二个变量,例如 a std::list(或手动链表甚至是一个小数组,具体取决于您允许使用的内容)。在此列表中,您可以跟踪实际拥有当前高分的人的指数。如果发现新的高分,则清除该列表并添加具有新高分的人。如果发现某人具有高分,您只需将他添加到列表中。

然后在循环之后,您只需要打印具有此列表中索引的球员,而不是再次找出谁拥有最高分。

于 2012-09-10T22:18:40.747 回答
2

一种解决方案是在您搜索高分时记录玩家的姓名。如果它等于当前的高分,则在您的“名称集合字符串”中附加一个额外的名称,如果它更高,则将名称空白,并记录新的高分和新名称。我会实现名称的打印输出,ostringstream以确保您不会超出缓冲区。然后当你完成后,打印出你的名字集。

于 2012-09-10T22:19:50.570 回答
1

在您完成第一次(唯一)通过时,保留最高分数的索引集。然后,当您完成时,您将拥有对应于该最高分数的一组索引。在我刚刚编写的一种语言的伪代码中:

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.

如果您没有可用的动态列表,则该列表可以是与 score 数组大小相同的静态数组,以确保它始终足够大。

于 2012-09-10T22:20:32.193 回答
1

现在,您的第一个循环正在跟踪高分。如果它还跟踪所有匹配的名称,则可以在循环完成时输出名称。您仍然需要第二个循环来遍历这些名称,这是无法避免的。

于 2012-09-10T22:21:59.537 回答
1

以较小的存储成本,您可以在同一通道中计算高分和各自的玩家:

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;
}

要回答您最初的问题,我认为没有任何方法可以在一个循环中找到并输出所有得分高的玩家。即使对分数数组进行预排序也会比你已经拥有的更糟糕。

于 2012-09-10T22:52:40.390 回答
0

我不会保留完整的匹配索引集,而是保留第一个和最后一个。这使您可以跳过搜索整个列表,并在有唯一最高分的情况下完全避免第二遍。

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";
}
于 2012-09-10T22:30:26.820 回答