使用插入排序将高分数添加到数组会导致重复

时间:2017-07-10 02:07:38

标签: java arrays sorting

我现在已经摸不着头脑了一段时间。我对编程很陌生,所以我的代码可能效率不高,但它让我感到害怕,我无法弄清楚出了什么问题。

目标是比较uScore' (刚刚玩过的游戏的分数,其中较低的是更好的)到存储在对象数组记录中的高分的排序列表,使用记录[i] .getName()来检索该分数。位置。然后我标记了uScore'的位置。将使用' insertScoreHere'插入,然后将数组中的所有内容向下移动一个位置。然后,我将分数的值设置为' insertScoreHere'到uScore,以及' uName' (来自游戏的玩家名称)。

public void sortWinners() {

    for (int i = 0; i < 10; i++) {
        if (uScore < records[i].getScore()) {
            insertScoreHere = i;
            i = 10; //this is terrible i know
        }
    }

    for (int i = 9; i > insertScoreHere; i--) {
        records[i] = records[i-1];
    }

    records[insertScoreHere].setName(uName);
    records[insertScoreHere].setScore(uScore);
}

现在,如果最近一场比赛中的球员名字是&#39; sam&#39;并且他的得分是&#39; 8&#39;,并且阵列是空的,那么这就是正在发生的事情(下面是阵列&#39;记录&#39;):

 NAME: sam, SCORE: 8

 NAME: sam, SCORE: 8

 NAME: , SCORE: 0

 NAME: , SCORE: 0

 NAME: , SCORE: 0

 NAME: , SCORE: 0

 NAME: , SCORE: 0

 NAME: , SCORE: 0

 NAME: , SCORE: 0

 NAME: , SCORE: 0

我已经尽可能多地记录了所有内容,并将其添加到我的代码中:

public void sortWinners() {

    for (int i = 0; i < 10; i++) {
        if (uScore < records[i].getScore()) {
            insertScoreHere = i;
            i = 10;
        }
    }

    Log.v("ARRAY", "PLACE TO INSERT SCORE: " + insertScoreHere);

    for (int i = 9; i > insertScoreHere; i--) {

        Log.v("ARRAY", "BEFORE ITERATION I = " + i + ": " +
                " | " + records[0].getScore() +
                " | " + records[1].getScore() +
                " | " + records[2].getScore() +
                " | " + records[3].getScore() +
                " | " + records[4].getScore() +
                " | " + records[5].getScore() +
                " | " + records[6].getScore() +
                " | " + records[7].getScore() +
                " | " + records[8].getScore() +
                " | " + records[9].getScore());
        records[i] = records[i-1];

        Log.v("ARRAY", " AFTER ITERATION I = " + i + ": " +
                      " | " + records[0].getScore() +
                      " | " + records[1].getScore() +
                      " | " + records[2].getScore() +
                      " | " + records[3].getScore() +
                      " | " + records[4].getScore() +
                      " | " + records[5].getScore() +
                      " | " + records[6].getScore() +
                      " | " + records[7].getScore() +
                      " | " + records[8].getScore() +
                      " | " + records[9].getScore());
    }
    records[insertScoreHere].setName(uName);
    records[insertScoreHere].setScore(uScore);

    Log.v("ARRAY", "AFTER SORTING");
    for (int i = 0; i < 10; i++) {
        Log.v("ARRAY", "NAME: " + records[i].getName() + ", SCORE: " + records[i].getScore());
    }
}

以下是日志记录结果的示例。假设我们有一个填充数组(已经发生了重复),例如:

NAME: milfred, SCORE: 1

NAME: milfred, SCORE: 1

NAME: timmy, SCORE: 3

NAME: john, SCORE: 5

NAME: sam, SCORE: 7

NAME: dhshs, SCORE: 8

NAME: , SCORE: 0

NAME: , SCORE: 0

NAME: , SCORE: 0

NAME: , SCORE: 0

现在让我们说下一场比赛得分为&#39; 6&#39;和一名球员姓名&#39; stringray&#39;。这是我的日志记录返回的内容:

PLACE TO INSERT SCORE: 4

BEFORE ITERATION I = 9:  | 1 | 1 | 3 | 5 | 7 | 8 | 0 | 0 | 0 | 0

 AFTER ITERATION I = 9:  | 1 | 1 | 3 | 5 | 7 | 8 | 0 | 0 | 0 | 0

BEFORE ITERATION I = 8:  | 1 | 1 | 3 | 5 | 7 | 8 | 0 | 0 | 0 | 0

 AFTER ITERATION I = 8:  | 1 | 1 | 3 | 5 | 7 | 8 | 0 | 0 | 0 | 0

BEFORE ITERATION I = 7:  | 1 | 1 | 3 | 5 | 7 | 8 | 0 | 0 | 0 | 0

 AFTER ITERATION I = 7:  | 1 | 1 | 3 | 5 | 7 | 8 | 0 | 0 | 0 | 0

BEFORE ITERATION I = 6:  | 1 | 1 | 3 | 5 | 7 | 8 | 0 | 0 | 0 | 0

 AFTER ITERATION I = 6:  | 1 | 1 | 3 | 5 | 7 | 8 | 8 | 0 | 0 | 0

BEFORE ITERATION I = 5:  | 1 | 1 | 3 | 5 | 7 | 8 | 8 | 0 | 0 | 0

 AFTER ITERATION I = 5:  | 1 | 1 | 3 | 5 | 7 | 7 | 8 | 0 | 0 | 0



AFTER SORTING

NAME: milfred, SCORE: 1

NAME: milfred, SCORE: 1

NAME: timmy, SCORE: 3

NAME: john, SCORE: 5

NAME: stingray, SCORE: 6

NAME: stingray, SCORE: 6

NAME: dhshs, SCORE: 8

NAME: , SCORE: 0

NAME: , SCORE: 0

NAME: , SCORE: 0

最后,在我的数据类型中:

String uName;
int uScore;
playerRecord records[] = new playerRecord[10];

playerRecord:

public class playerRecord {
    private String name;
    private int score;

    public playerRecord(String input_name, int input_score) {
        name = input_name;
        score = input_score;
    }

    public String getName() {
        return name;
    }

    public int getScore() {
        return score;
    }

    public void setName(String set_name) {
        name = set_name;
    }

    public void setScore(int set_score) {
        score = set_score;
    }
}

填充playerRecord:

for (int i = 0; i < 10; i++) {
            records[i] = new playerRecord("", (0));
        }

我希望我能够正确地说明问题。如果需要任何其他细节,请告诉我。

2 个答案:

答案 0 :(得分:0)

当您想要插入新分数

时,会出现这些问题
records[insertScoreHere].setName(uName);
records[insertScoreHere].setScore(uScore);

这实际上做的是替换该索引处的playerRecord的名称和分数。这也是你现在已经改组到下一个索引(insertScoreHere + 1)

的同一个对象

要向您展示这一切,您需要做的就是在阵列中打印播放器记录的地址:

playerRecord@996db8, playerRecord@996db8, playerRecord@163006a, playerRecord@1be847c, ...

这是在我调用你的sortWinners方法一次之后 - 你可以看到数组中的前两个元素引用同一个对象playerRecord@996db8

要解决此问题,您只需要通过调用此

在该索引处插入新分数
records[insertScoreHere] = new PlayerRecord(uName, uScore)

您可能还想查看naming conventions for Java

答案 1 :(得分:0)

您遇到内存指针问题。你的10个分数数组实际上是一个10个指向playerRecord对象的数组。我知道它看起来并不像,但是当你有一个对象数组时,这就是幕后发生的事情。

在执行排序操作后,数组中的两个重复元素实际上是在寻址同一块内存!

我们说i = 4;并insertScoreHere = 3.

records[i] = records[i-1];

# records[4] = records[3]; 
# BUT what actually happens here is records[4] is now pointing to the 
# same piece of memory as records[3]. So then:
# records[4] => memory_address_x
# records[3] => memory_address_x

records[insertScoreHere].setName(uName);
records[insertScoreHere].setScore(uScore); 

#so now this code: records[3].setName(uName); is actually modifying 
#the same piece of memory as records[4]. 

解决方案#1:

在排序时交换指针。我会在i == 9处使用该对象,因为无论如何都要擦除它。

public void sortWinners() {
    for (int i = 0; i < 10; i++) {
        if (uScore < records[i].getScore()) {
            insertScoreHere = i;
            i = 10; //this is terrible i know
        }
    }

    # EDIT 1: lets save this record for reuse
    playerRecord temp = records[9]; 
    for (int i = 9; i > insertScoreHere; i--) {
        records[i] = records[i-1];
    }

    # EDIT 2: change the record to point to a separate record
    records[insertScoreHere] = temp; 
    # ^ this index now points to a separate record from records[i] 
    records[insertScoreHere].setName(uName);
    records[insertScoreHere].setScore(uScore);
}

解决方案#2:

避免弄乱内存指针的另一种方法是将数据从一个记录复制到另一个记录:

public void sortWinners() {
    for (int i = 0; i < 10; i++) {
        if (uScore < records[i].getScore()) {
            insertScoreHere = i;
            i = 10; //this is terrible i know
        }
    }

    for (int i = 9; i > insertScoreHere; i--) {
        records[i].setName(records[i-1].getName());  # EDIT 1 **
        records[i].setScore(records[i-1].getScore());# EDIT 2 **
    }

    records[insertScoreHere].setName(uName);
    records[insertScoreHere].setScore(uScore);
}