简体   繁体   English

从单链列表中添加和删除

[英]adding and removing from a singly linked list

I thought I had understanding of this in my previous question about linked lists, but I was terribly mistaken, I'm just as lost as I was when I initially posted. 我以为我在上一个有关链表的问题中已经了解了这一点,但我犯了一个非常错误的错误,我和最初发布时一样迷失了。

I realize that I'm technically asking two questions, but hopefully getting at least one should make the other easy (assuming they are just reverse of each other). 我意识到我在技术上是在问两个问题,但希望至少得到一个问题才能使另一个问题变得容易(假设它们彼此相反)。

I have 3 classes already given to me, they are: 我已经给了3个课程,它们是:

SLinkedList.java SLinkedList.java

package chapter3.linkedList;

    public class SLinkedList<V> {
        // instance variables.  Add the tail reference.
        protected Node<V> head, tail;
        protected long size;

        // methods, empty list constructor first
        public SLinkedList () {
            head = null;
            tail = null;
            size = 0;
        }  // end constructor of a SLinkedList

        // method to add nodes to the list.  Storage space for the node
        // is already allocated in the calling method
        public void addFirst (Node<V> node) {
            // set the tail only if this is the very first node
            if (tail == null)
                tail = node;
            node.setNext (head);    // make next of the new node refer to the head
            head = node;            // give head a new value

            // change our size
            size++;
        }  // end method addFirst

        // addAfter - add new node after current node, checking to see if we are at the tail
        public void addAfter (Node<V>currentNode, Node<V>newNode) {
            if (currentNode == tail)
                tail = newNode;
            newNode.setNext (currentNode.getNext ());
            currentNode.setNext (newNode);

            // change our size
            size++;
        }  // end method addAfter

        // addLast - add new node after the tail node.  Adapted from Code Fragment 3.15, p. 118.
        // Mike Qualls
        public void addLast (Node<V> node) {
            node.setNext (null);
            tail.setNext (node);
            tail = node;
            size++;     
        }  // end method addLast

        // methods to remove nodes from the list.  (Unfortunately, with a single linked list
        // there is no way to remove last.  Need a previous reference to do that.  (See
        // Double Linked Lists and the code below.)
        public Node<V> removeFirst () {
            if (head == null)
                System.err.println("Error:  Attempt to remove from an empty list");

            // save the one to return
            Node<V> temp = head;

            // do reference manipulation
            head = head.getNext ();
            temp.setNext(null);
            size--;

            return temp;

        }  // end method removeFirst

        // remove the node at the end of the list.  tail refers to this node, but
        // since the list is single linked, there is no way to refer to the node
        // before the tail node.  Need to traverse the list.
        public Node<V> removeLast () {
            // // declare local variables/objects
            Node<V> nodeBefore;
            Node<V> nodeToRemove;

            // make sure we have something to remove
            if (size == 0)
                System.err.println("Error:  Attempt to remove fron an empty list");

            // traverse through the list, getting a reference to the node before
            // the trailer.  Since there is no previous reference.
            nodeBefore = getFirst ();

            // potential error  ??  See an analysis and drawing that indicates the number of iterations
            // 9/21/10.  size - 2 to account for the head and tail nodes.  We want to refer to the one before the
            // tail.
            for (int count = 0; count < size - 2; count++)
                nodeBefore = nodeBefore.getNext ();

            // save the last node
            nodeToRemove = tail;

            // now, do the pointer manipulation
            nodeBefore.setNext (null);
            tail = nodeBefore;
            size--;

            return nodeToRemove;

        }  // end method removeLast

        // method remove.  Remove a known node from the list.  No need to search or return a value.  This method
        // makes use of a 'before' reference in order to allow list manipulation.
        public void remove (Node<V> nodeToRemove) {
            // declare local variables/references
            Node<V> nodeBefore, currentNode;

            // make sure we have something to remove
            if (size == 0)
                System.err.println("Error:  Attempt to remove fron an empty list");

            // starting at the beginning check for removal
            currentNode = getFirst ();
            if (currentNode == nodeToRemove)
                removeFirst ();
            currentNode = getLast ();
            if (currentNode == nodeToRemove)
                removeLast ();

            // we've already check two nodes, check the rest
            if (size - 2 > 0) {
                nodeBefore = getFirst ();
                currentNode = getFirst ().getNext ();
                for (int count = 0; count < size - 2; count++) {
                    if (currentNode == nodeToRemove) {
                        // remove current node
                        nodeBefore.setNext (currentNode.getNext ());
                        size--;
                        break;
                    }  // end if node found

                    // change references
                    nodeBefore = currentNode;
                    currentNode = currentNode.getNext ();
                }  // end loop to process elements
            }  // end if size - 2 > 0

        }  // end method remove

        // the gets to return the head and/or tail nodes and size of the list
        public Node<V> getFirst () { return head; }
        public Node<V> getLast () { return tail; }  
        public long getSize () { return size; }

    }  // end class SLinkedList

There's also Node.java 还有Node.java

package chapter3.linkedList;

public class Node<V> 
{
    // instance variables
    private V element;
    private Node<V> next;

    // methods, constructor first
    public Node () 
    {
        this (null, null);      // call the constructor with two args
    }  // end no argument constructor
    public Node (V element, Node<V> next) 
    {
        this.element = element;
        this.next = next;
    }  // end constructor with arguments

    // set/get methods
    public V getElement () 
    { 
        return element; 
    }
    public Node<V> getNext () 
    { 
        return next; 
    }
    public void setElement (V element) 
    { 
        this.element = element; 
    }
    public void setNext (Node<V> next) 
    { 
        this.next = next; 
    }

}  // end class Node

and finally GameEntry.java 最后是GameEntry.java

package Project_1;

public class GameEntry 
{
    protected String name;  // name of the person earning this score
    protected int score;    // the score value
    /** Constructor to create a game entry */
    public GameEntry(String name, int score) 
    {
      this.name = name;
      this.score = score;
    }
    /** Retrieves the name field */
    public String getName() 
    { 
        return name; 
    }
    /** Retrieves the score field */
    public int getScore() 
    { 
        return score; 
    }
    /** Returns a string representation of this entry */
    public String toString() 
    { 
      return name + ", " + score + "\n"; 
    }

}

EDIT POINT I created a driver called Scores.java, in it so far all I have is **I have added what I THINK i need for the classes, I'm probably wrong though: 编辑要点我创建了一个名为Scores.java的驱动程序,到目前为止,我所拥有的只是**我已经添加了我对类所需要的内容,但是我可能错了:

package Project_1;

import chapter3.linkedList.*;

import java.util.*;


/** Class for storing high scores in an array in non-decreasing order. */
public class Scores 
{

    //add function
    public SLinkedList<GameEntry> add(GameEntry rank, SLinkedList<GameEntry> scores)
    {
        Node<GameEntry> currentNode = scores.getFirst();
        Node<GameEntry> nextNode = null;
        Node<GameEntry> previousNode = null;
        Node<GameEntry> newNode = new Node<GameEntry>();
        newNode.setElement(rank);

        if(scores.getSize() == 0)
        {
            scores.addFirst(newNode);
        }
        else
        {
            while(currentNode != null)
            {               
                nextNode = currentNode.getNext();
                if(nextNode == null)
                {
                    scores.addLast(newNode);
                }
                else
                {
                    scores.addAfter(currentNode, newNode);
                    break;
                }               
            previousNode = currentNode;
            currentNode = currentNode.getNext();
            }
        }
        return scores;
    }

    //remove function
    public void remove(int i)
    {

    }

    //print function
    /*gameenter printing; 
printing=node.Getelement;           //pseudo code for making it work right
print(printing.getscore) 
print(print.getname) 
*/
    public void print(SLinkedList<GameEntry> scores)
    {
        Node<GameEntry> currentNode = scores.getFirst();        
        GameEntry currentEntry = currentNode.getElement();      
        System.out.printf("[");
        for(int i = 0; i < scores.getSize(); i++)
        {
                System.out.printf(", %s", currentEntry.toString());
                currentNode = currentNode.getNext();
                currentEntry = currentNode.getElement();
        }
        System.out.println("]");
    }
}

I have my test driver called ScoresTest.java, that I have pretty much filled out: 我有一个名为ScoresTest.java的测试驱动程序,我已经填写了很多:

package Project_1; 包Project_1;

import chapter3.linkedList.SLinkedList; 导入Chapter3.linkedList.SLinkedList;

 public class ScoresTest {
    /**
     * @param args
     */

    public static void main(String[] args) 
    {
        SLinkedList<GameEntry> highScores = new SLinkedList<GameEntry>();  //Linked List for Game Entry
        GameEntry entry;
        Scores rank = new Scores();     
        entry = new GameEntry("Flanders", 681);     
        highScores = rank.add(entry, highScores);
        entry = new GameEntry("Krusty", 324);
        highScores = rank.add(entry, highScores); 
        entry = new GameEntry("Otto", 438);
        highScores = rank.add(entry, highScores); 
        entry = new GameEntry("Bart", 875);
        highScores = rank.add(entry, highScores); 
        entry = new GameEntry("Homer", 12);
        highScores = rank.add(entry, highScores); 
        entry = new GameEntry("Lisa", 506);
        highScores = rank.add(entry, highScores); 
        entry = new GameEntry("Maggie", 980);
        highScores = rank.add(entry, highScores); 
        entry = new GameEntry("Apoo", 648);
        highScores = rank.add(entry, highScores); 
        entry = new GameEntry("Smithers", 150);
        highScores = rank.add(entry, highScores); 
        entry = new GameEntry("Burns", 152);
        highScores = rank.add(entry, highScores); 
        System.out.println("The Original High Scores");
        rank.print(highScores);

        entry = new GameEntry("Moe", 895);
        highScores = rank.add(entry, highScores);
        System.out.println("Scores after adding Moe");
        rank.print(highScores);

        //highScores = rank.remove(4);
        System.out.println("Scores after removing Apoo");
        rank.print(highScores);
    }
}

That's entirely finished, pretty sure I have nothing left to add for it. 这完全完成了,很确定我没有什么可补充的。

I'm not looking for someone to answer it for me, but I have no clue where to start or how to make the add or remove function, in any way. 我不是在找别人为我解答,但是我不知道从何处开始或如何进行添加或删除功能。 This is an intermediate course, the book does nothing for explaining linked lists (go ahead and look for yourself if you don't believe me, text is called Datastructures and Algorithms in Java, 5th edition). 这是一门中级课程,本书不做任何解释链表的操作(如果您不相信我,请继续寻找,文本称为Java中的数据结构和算法,第5版)。 It shows how to do such with an array quite easily...which works perfectly for a linked list, but apparently the teacher does not want us doing it this way, so sadly I am now utterly lost on how to do this. 它显示了如何非常容易地使用数组来执行此操作……这非常适合链接列表,但是显然老师不希望我们这样做,所以很遗憾,我现在完全不知道如何执行此操作。

I've tried looking at other peoples answers on here, and google, and so far nothing has clicked or made any sense at all, I just can't grasp how it works, and the teacher's explanation and example was only to draw boxes on the board, I've never seen a sort, add, or remove function coded for a linked list...can't know what I've not been taught or can't locate. 我尝试在这里和google上查看其他人的答案,到目前为止,没有任何点击或任何意义,我只是无法理解它的工作方式,而老师的解释和例子仅仅是在盒子上画上了方块。在板上,我从未见过为链接列表编码的排序,添加或删除功能……不知道我没有被教过的内容或找不到的内容。

Any help is greatly appreciated, and thank you in advance! 非常感谢您的任何帮助,并在此先感谢您!

EDIT 编辑

I looked at the import java.util.*; 我看着导入java.util。*; and the commands within it for linked lists, they seem painfully easy. 以及其中用于链接列表的命令,它们看起来非常简单。 to remove I'd just use list.sublist(i, i).clear(); 删除我只会使用list.sublist(i,i).clear(); and the value I wish to remove is removed, super easy, it seems to be just trying to utilize the slinkedlist.java and node.java, I just can't seem to follow them in any way shape or form. 并且我想要删除的值被删除了,非常简单,它似乎只是在尝试利用slinkedlist.java和node.java,我似乎无法以任何形式遵循它们。 I believe the teacher did indeed write them, and I've tried asking for his assistance, stayed 2 hours after class trying to get any understanding from him, and as you can see it did not help much at all. 我相信老师确实写过这些书,并且我尝试过寻求他的帮助,下课后仅停留了2个小时,试图使他有所了解,并且您可以看到这对他没有多大帮助。 Thank you again for the assistance! 再次感谢您的协助!

EDIT 编辑

I also apologize if this seems like it is vague, but I don't have a specific point where my confusion seems linked, I understand linked lists if we're talking about the java.util.linkedList;, but as far as using what I've been given in this circumstance, I can't follow the logic at all, leaving me quite lost and unsure of where to begin. 如果这似乎还很模糊,我也表示歉意,但是我没有一个混淆我链接的特定点,如果我们在谈论java.util.linkedList ;,我理解链接列表;但是就使用什么在这种情况下我被告知,我根本无法遵循逻辑,这让我很失落,不确定从哪里开始。

In pseudo-code (please note I am not including bound checking etc, simply the logic) 用伪代码(请注意,我不包括绑定检查等,只是逻辑)

To add a node to the front of the list: 要将节点添加到列表的前面:

newNode->nextNode = startNode
startNode = newNode

To add to a specific index: 要添加到特定索引:

index = 0
currentNode = startNode

// find the node in the list. here you will need to do all kinds of bound checking
while index is less than position
    currentNode = currentNode.nextNode  // move your node pointer to the position
    increment index

// so here we basically insert the new node into the list. what needs to happen is
// to NOT break the list by forgetting the node after the current node. this is why
// we first set the new nodes' next one, to the current nodes' (the one already in
// the list) next node. this way, we still have all the information we need. then,
// when we set the current nodes' next node to the new node, we essentially "break"
// the link and "repair" it by adding the new link.

newNode.nextNode = currentNode.nextNode // some more bound checking required
currentNode.nextNode = newNode

To remove from a specific index: 要从特定索引中删除:

index = 0
delNode = startNode

// find the node in the list. here you will need to do all kinds of bound checking
while index is less than (position - 1)
    delNode = delNode.nextNode  // move your node pointer to the position
    increment index

delNode.nextNode = delNode.nextNode.nextNode

// that's it. by setting the node's (before the one you whish to delete)
// next node to the node AFTER the one you want to delete, you basically
// "skip" over that node. since it is no longer referenced, the garbage
// collector will take care of the rest. if you wish to return that node
// you can do it quite easily by remembering it.

storeNode = delNode.nextNode                 // some more bound checking required
delNode.nextNode = delNode.nextNode.nextNode // some more bound checking required

// now you still have a reference to the deleted node in storeNode

UPDATE UPDATE

OK, so if I understand correctly, you need to create a linked list that stores scores in a ascending order. 好的,因此,如果我理解正确,则需要创建一个链接列表,以升序存储分数。 As far as I can see, the entire linked list has been implemented for you, you simply need to use the classes provided, and add the logic in Scores.java to keep the list sorted. 据我所知,整个链表已为您实现,您只需要使用提供的类,并在Scores.java添加逻辑以使列表保持排序。

First off, I see your nodes are not comparable. 首先,我看到您的节点不可比。 If you are at all allowed to change the source given to you, I would suggest having them implement Comparable<Node> and also override the equals(Object o) so that you have logic to compare them. 如果完全允许您更改提供给您的源,我建议让他们实现Comparable<Node>并重写equals(Object o)以便您有比较它们的逻辑。 Two nodes can contain the same element, but that does not mean that they are equal. 两个节点可以包含相同的元素,但这并不意味着它们相等。

Please note the change in the method signatures! 请注意方法签名的更改!

//add function
public void add(Node<GameEntry> score) {
    // adding is where you now want to keep everything sorted. so I highly
    // recommend that you implement `Comparable` as I mentioned above. if not,
    // you have to put the logic in here.

    Node<GameEntry> currentNode = highScored.getFirst();
    Node<GameEntry> prevNode = null;

    // if the list is empty, or the new node must go in before the head,
    // simply add it as the head.
    if (highScores.size() == 0 || score.compareTo(currentNode) < 0) {
        highScores.addFirst(score);
    }

    // search for the position of the new node. while the node has a higher score
    // than the current node, we need to continue on so we can place it in the
    // correct place.
    while (currentNode != null && currentNode.compareTo(score) > 0) {
        prevNode = currentNode;
        currentNode = currentNode.getNext();
    }

    // if the currentNode is null, it means it is the highest score, so
    // we can simply add it to the end
    if (currentNode == null) {
        highScores.addLast(score);
    } else {
        // otherwise just add it after the correct node
        highScores.addAfter(prevNode, score);
    }
}


//remove function
public void remove(Node<GameEntry> score) {
    // removing an element should be as described above. if you keep
    // your list sorted during the ADD method, removing any element
    // should not break the order.

    // find the element - removal from a linked list is O(n),
    // since we need to know what the element BEFORE the one
    // is that you want to remove. assuming you have implemented
    // the equals method to check equality of nodes:

    Node<GameEntry> currentNode = highScores.getFirst();
    Node<GameEntry> prevNode = null;
    while (currentNode != null && !currentNode.equals(score)) {
        prevNode = currentNode;
        currentNode = currentNode.getNext();
    }

    // if currentNode is null, the node we wanted to remove was not
    // in the list.
    if (currentNode == null) {
        System.out.println("Node not found");
        return;
    }

    // now, we need to check if there is a node after the one we want
    // to remove.
    if (prevNode.getNext().getNext() != null) {
        // if there is, we follow the logic from the pseudo code
        prevNode.setNext(prev.getNext().getNext());
    } else {
        // if not, we only need to remove the last entry (since the
        // one we want to remove is the last one)
        highScores.removeLast();
    }
}

IMPORTANT 重要

Please just double check the logic here. 请在这里仔细检查逻辑。 I did it really quickly without an IDE as I'm not at my development computer at the moment. 我现在没有开发计算机,因此在没有IDE的情况下确实可以很快完成操作。 If anyone finds any issues, please leave a comment and I'll fix it. 如果有人发现任何问题,请发表评论,我会解决。

If this is not exactly what you asked (your question is a bit vague), let me know. 如果这不是您所要问的(您的问题有点含糊),请告诉我。


UPDATE 2 更新2

Read up on Comparator s here , here and here . 此处此处此处阅读Comparator的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM