Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将链表节点数组从高到低排序(基于浮点值)_Java_Arrays_Sorting_Linked List - Fatal编程技术网

Java 如何将链表节点数组从高到低排序(基于浮点值)

Java 如何将链表节点数组从高到低排序(基于浮点值),java,arrays,sorting,linked-list,Java,Arrays,Sorting,Linked List,我有一个链表节点数组,对应于学生注册的课程,我需要将分数从最高到最低排序。我花了一整天的时间尝试不同的排序算法,但似乎无法让它正常工作。诚然,我不太擅长排序算法,但这并不是因为缺乏尝试。我第一次尝试mergesort,但失败惨重,我最近的努力也没有奏效。由于它是一个链表节点数组,我对如何实现排序感到困惑,因为大多数算法都是针对数组或链表,而不是两者 我遇到的问题: 一,。多次插入后显示的重复节点 二,。在节点之间交换坡率值,而不是交换节点本身 三,。根本没有显示任何数据 如果有人能为我指出正确的

我有一个链表节点数组,对应于学生注册的课程,我需要将分数从最高到最低排序。我花了一整天的时间尝试不同的排序算法,但似乎无法让它正常工作。诚然,我不太擅长排序算法,但这并不是因为缺乏尝试。我第一次尝试mergesort,但失败惨重,我最近的努力也没有奏效。由于它是一个链表节点数组,我对如何实现排序感到困惑,因为大多数算法都是针对数组或链表,而不是两者

我遇到的问题:

一,。多次插入后显示的重复节点

二,。在节点之间交换坡率值,而不是交换节点本身

三,。根本没有显示任何数据

如果有人能为我指出正确的方向,或者帮助我解释如何正确地对我的节点进行排序,我将不胜感激。我读了好几个小时的书,但没有成功

当我没有对节点进行排序时,节点链接良好,显示良好,因此我知道功能正常。我的类课程使用包装类AGradeListNode来保存节点插入数组所需的数据。我的代码中包括我最近尝试对不起作用的节点进行排序,这会导致重复。请不要对我大喊大叫,我真的想学

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;