Java 如何将链表节点数组从高到低排序(基于浮点值)
我有一个链表节点数组,对应于学生注册的课程,我需要将分数从最高到最低排序。我花了一整天的时间尝试不同的排序算法,但似乎无法让它正常工作。诚然,我不太擅长排序算法,但这并不是因为缺乏尝试。我第一次尝试mergesort,但失败惨重,我最近的努力也没有奏效。由于它是一个链表节点数组,我对如何实现排序感到困惑,因为大多数算法都是针对数组或链表,而不是两者 我遇到的问题: 一,。多次插入后显示的重复节点 二,。在节点之间交换坡率值,而不是交换节点本身 三,。根本没有显示任何数据 如果有人能为我指出正确的方向,或者帮助我解释如何正确地对我的节点进行排序,我将不胜感激。我读了好几个小时的书,但没有成功 当我没有对节点进行排序时,节点链接良好,显示良好,因此我知道功能正常。我的类课程使用包装类AGradeListNode来保存节点插入数组所需的数据。我的代码中包括我最近尝试对不起作用的节点进行排序,这会导致重复。请不要对我大喊大叫,我真的想学Java 如何将链表节点数组从高到低排序(基于浮点值),java,arrays,sorting,linked-list,Java,Arrays,Sorting,Linked List,我有一个链表节点数组,对应于学生注册的课程,我需要将分数从最高到最低排序。我花了一整天的时间尝试不同的排序算法,但似乎无法让它正常工作。诚然,我不太擅长排序算法,但这并不是因为缺乏尝试。我第一次尝试mergesort,但失败惨重,我最近的努力也没有奏效。由于它是一个链表节点数组,我对如何实现排序感到困惑,因为大多数算法都是针对数组或链表,而不是两者 我遇到的问题: 一,。多次插入后显示的重复节点 二,。在节点之间交换坡率值,而不是交换节点本身 三,。根本没有显示任何数据 如果有人能为我指出正确的
public class Course implements Serializable
{
private String courseName;
private String classTime;
private int courseID;
private Instructor instructor;
private int numStudents; //variable for number of students in the list
private int hold; //used to hold location of node
protected static final int NUL = -1; //Constant class var for end of list symbol.
protected int currentPos; //Current position for iteration
protected int list; //Reference to the first node on the list
protected int free; //Reference to the first node on the free list
protected AGradeListNode[] nodes; // Array of AListNode holds the linked list
// set by find method
protected boolean found; // true if element found, else false
protected int location; // node containing element, if found
protected int previous; // node preceding location
//wrapper class to create nodes for linked list array
protected class AGradeListNode
{
private float grade;
private Student student;
private int next; //a link to the next node in linked list array
//displays nodes as neatly formatted string
@Override
public String toString()
{
return "Student: " + student.getLastName() + ", " + student.getFirstName() + "\n" +
"Grade: " + grade + "\n";
}
}
//constructor initializes array of nodes with 2 lists: used and free.
//contains other data needed for Course object instantiation as well
public Course(int maxNumStudents, String courseName, String classTime, int courseID, Instructor instructor)
{
nodes = new AGradeListNode[maxNumStudents];
for (int i = 0; i < maxNumStudents; i++)
{
nodes[i] = new AGradeListNode();
}
//link together the free nodes
for (int i = 1; i < maxNumStudents; i++)
{
nodes[i - 1].next = i;
}
nodes[maxNumStudents - 1].next = NUL;
list = NUL;
free = 0;
numStudents = 0;
currentPos = NUL;
this.courseName = courseName;
this.classTime = classTime;
this.courseID = courseID;
this.instructor = instructor;
}
// Returns the index of the next available node from the free list
// and updates the free list index
protected int getNode()
{
hold = free;
free = nodes[free].next;
return hold;
}
//Frees the node at array position index by linking it into the
//free list
protected void freeNode(int index)
{
nodes[index].next = free;
free = index;
}
//here is where im having issues. I'm attempting to sort the nodes based on
//grade from high to low. Each grade belongs to a specific student object
public void addStudentGrade(Student stu, float grade)
{
if (isFull())
{
return;
}
int newNode = getNode();
nodes[newNode].student = stu;
nodes[newNode].grade = grade;
nodes[newNode].next = list;
list = newNode;
numStudents++;
//sorting list, not working :/
for (int j = 1; j <= numStudents; j++)
{
float hold = nodes[j].grade;
int i = j-1;
while ((i > -1) && (nodes[i].grade > hold))
{
nodes[i+1] = nodes[i];
i--;
}
nodes[i+1] = nodes[j];
}
for (int i = 0; i < numStudents; i++)
{
System.out.println(nodes[i].toString());
}
}
最后一次编辑:这是我完整的、功能强大的类,包含的方法没有发布在我的原始代码中。我还包含了其他方法来删除、替换和检索学生成绩,希望它将来能帮助其他人。它现在按照应该的降序排序,而不是在插入时排序,我在调用printData方法时对列表进行排序。我非常感谢安德烈亚斯帮我解决了这项任务,没有你我不可能完成它!至少在所需的指定时间范围内:
// Returns the index of the next available node from the free list
// and updates the free list index
protected int getNode()
{
hold = free;
free = nodes[free].next;
return hold;
}
//Frees the node at array position index by linking it into the
//free list
protected void freeNode(int index)
{
nodes[index].next = free;
free = index;
nodes[free].student = null;
}
private void find(int id)
{
found = false;
current = list;
previous = NUL;
while (!found || current != NUL )
{
if (nodes[current].student.getId() == id)
{
found = true;
location = current;
return;
}
previous = current;
current = nodes[current].next;
}
}
//Method used to add student grades to nodes array. After LL node
//is added, method sorts the used nodes in descending order based
//off the float value grade
public void addStudentGrade(Student stu, float grade)
{
if (isFull())
{
return;
}
int newNode = getNode();
nodes[newNode].student = stu;
nodes[newNode].grade = grade;
nodes[newNode].next = list;
list = newNode;
numStudents++;
//printing sorted data to console
printData();
}
public boolean removeStudentGrade(int id)
{
find(id);
if (found)
{
hold = location;
if (list == location)
{
list = nodes[list].next; // remove first node
System.out.println("Removing first node");
}
else
{
nodes[previous].next = nodes[location].next;
}
freeNode(hold);
numStudents--;
}
return found;
}
//updates student grade from nodes array based on student id
public void updateStudentGrade(int id, float newGrade)
{
find(id);
if (found)
{
hold = location;
nodes[hold].grade = newGrade;
}
else
{
System.out.println("Student ID not found. Please check data entry and try again.");
}
}
//Method that searches array for student by id #. if found,
//students grade is returned. if not, -1 is returned
public float findStudentGrade(int id)
{
find(id);
if (found)
{
hold = location;
return nodes[hold].grade;
}
else
{
System.out.println("Student ID not found. Please check data entry and try again.");
}
return -1;
}
//method that sorts student's grades for a specific course in descending order
private void sort()
{
//storing used nodes in temp Integer array which will be used
//to compare and sort the grade values of each node
Integer[] usedNodes = new Integer[numStudents];
for (int i = list, j = 0; i != NUL; i = nodes[i].next)
{
usedNodes[j++] = i;
}
//sorting the temp array in descending order using custom
//comparator and Arrays.sort from Java.util.Arrays.
Arrays.sort(usedNodes, (i1, i2) ->
{
return Float.compare(nodes[i2].grade, nodes[i1].grade);
});
//rebuilding the linked list after sorting
list = usedNodes[0];
for (int i = 1; i < usedNodes.length; i++)
{
nodes[usedNodes[i-1]].next = usedNodes[i];
}
nodes[usedNodes[usedNodes.length - 1]].next = NUL;
}
//Determines whether this list is full
public boolean isFull()
{
return (free == NUL);
}
//prints grades for a specific course. Calls sort()
//method before printing
public void printData()
{
current = list;
while (current != NUL)
{
sort();
System.out.println(nodes[current].toString());
previous = current;
current = nodes[current].next;
}
}
我认为您真正的问题是对需求的误解,分别是数据模型不足 我的意思是:你的学生班级应该知道成绩。例如,一个学生对象可能包含一个等级地图,其中的键可能代表不同的课程。当然,每个真实的学生只有一个学生对象 现在,你可以把同一个学生放入不同的数组/列表中,然后根据合适的标准对一个列表进行排序。长话短说,您对节点数组进行排序的想法只会造成概念上的混乱 我想说的是:以这种方式对课程的成员进行分类是没有意义的。一门课程只知道有多少座位。所以,当增加一个学生时,你只会担心课程是否满了 然后一门课程可能会有列出注册学生的特点;使用您想要的任何排序标准 这是两个完全独立的用例,您应该避免将它们混淆在一起 更新后的原始答案假设您只是想在事实发生后对列表进行排序,但仔细看,似乎您想插入已排序的列表,相同成绩的学生应按插入顺序插入 为此,addStudentGrade方法大部分需要替换。不进行排序,而是搜索插入点,然后在那里添加新节点 为了说明这一点,我将代码简化为一个最小、完整且可验证的示例。您可以在上看到完整的代码 原始答案 这是一个非常奇怪的类,它将一个基于索引的链表放入一个固定大小的节点数组中 我建议,要对非空闲节点进行排序,首先在数组中收集这些节点,或者更确切地说,收集它们的节点索引。因为您知道有多少个在用节点,即numstudent,所以创建一个该大小的新数组,然后用在用节点的索引填充它。请注意,数组必须是整数[],而不是整数[],因此可以为排序提供自定义比较器:
Integer[] inuse = new Integer[numStudents];
for (int i = list, j = 0; i != NUL; i = nodes[i].next)
inuse[j++] = i;
然后使用自定义比较器对其进行排序,例如使用Java 8 lambda:
Arrays.sort(inuse, (i1, i2) -> {
return Float.compare(nodes[i2].grade, nodes[i1].grade); // descending
});
现在它们已排序,您需要重新构建链接列表:
list = inuse[0];
for (int j = 1; j < inuse.length; j++)
nodes[inuse[j - 1]].next = inuse[j];
nodes[inuse[inuse.length - 1]].next = NUL;
我认为应该这样做。你试过了吗?不需要实现您自己的排序算法。我的印象是,对于给定的实现,它不起作用,但您认为值得一试?不幸的是,它不起作用,但感谢您的建议。我完全同意您的看法,但这就是我的教授指导我实施该计划的方式,他有着令人质疑的教学历史。唉,我仍然需要根据节点的浮动等级值对节点进行排序。。。编辑:这是一个非常非常大的实现的一个非常小的部分,因此有些事情可能会因此而显得可疑。我感谢您的输入。我的课程中确实有一部分是与本课程相关的,所以从整体来看,这是有意义的。这不是问题
我知道这是最伟大的实现。不过我会继续尝试,谢谢:非常感谢,我很感谢你的意见!在你发布这篇文章之前,我尝试了另一种排序算法,但它也不起作用。我同意这是一个非常奇怪的类,但它是如何指导我实现设计的。嗯,列表仍然没有正确排序。功能确实得到了改进,但是等级是根据它们出现的顺序进行排序的。我真诚地感谢您的意见,如果您有机会再次与我一起查看,我将永远感激您。再次感谢你,Andreas:实际上我使用了你最初的实现,我自己做了一些调整。我没有对每个加法进行排序,而是对方法进行排序,每次调用display方法时都调用该方法。到目前为止似乎工作得很好!说真的,非常感谢。您的代码非常优雅:我花了一分钟的时间来理解它,但一旦我这样做了,它就非常直观。
Arrays.sort(inuse, (i1, i2) -> {
return Float.compare(nodes[i2].grade, nodes[i1].grade); // descending
});
list = inuse[0];
for (int j = 1; j < inuse.length; j++)
nodes[inuse[j - 1]].next = inuse[j];
nodes[inuse[inuse.length - 1]].next = NUL;