添加和删​​除单个链接列表

时间:2011-09-15 06:52:04

标签: java linked-list singly-linked-list

我以为我在之前关于链接列表的问题中已经理解了这一点,但我非常错误,我和我最初发布时的情况一样迷失。

我意识到我在技术上提出了两个问题,但希望至少有一个问题可以让另一个问题变得容易(假设它们只是彼此相反)。

我已经给了3个课程,他们是:

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

还有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

最后是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"; 
    }

}

编辑点 我创建了一个名为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("]");
    }
}

我有一个名为ScoresTest.java的测试驱动程序,我已经填写了很多内容:

包Project_1;

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

这完全结束了,我确定没有什么可以添加的。

我不是在寻找有人为我解答,但我不知道从哪里开始或如何以任何方式进行添加或删除功能。这是一个中级课程,本书对解释链表没有任何作用(如果您不相信我,请继续寻找自己,文本称为Java中的数据结构和算法,第5版)。它显示了如何使用数组很容易地做到这一点......这对链接列表非常有效,但显然教师不希望我们这样做,所以很遗憾我现在完全迷失了如何做到这一点。

我试过在这里查看其他人的答案,谷歌,到目前为止没有任何点击或任何意义,我只是无法掌握它是如何工作的,老师的解释和例子只是为了在棋盘上画盒子,我从未见过排序,添加或删除链接列表编码的功能......无法知道我没有教过或找不到的东西。

非常感谢任何帮助,并提前感谢您!

修改

我查看了import java.util。*;以及链接列表中的命令,它们看起来非常简单。删除我只使用list.sublist(i,i).clear();我希望删除的值被删除,超级简单,似乎只是试图利用slinkedlist.java和node.java,我似乎无法以任何方式跟随它们的形状或形式。我相信老师确实写了他们,我已经尝试过要求他的帮助,在课后2小时试图让他得到任何理解,而你可以看到它根本没有帮助。再次感谢您的帮助!

修改

我也道歉,如果这看起来很模糊,但我没有一个特定的点,我的困惑似乎链接,我理解链接列表,如果我们谈论java.util.linkedList;,但到目前为止使用我在这种情况下给予的东西,我根本无法遵循逻辑,让我迷失方向,不确定从哪里开始。

1 个答案:

答案 0 :(得分:4)

在伪代码中(请注意我不包括绑定检查等,只是逻辑)

要将节点添加到列表的前面:

newNode->nextNode = startNode
startNode = newNode

要添加到特定索引:

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

要从特定索引中删除:

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

<强>更新

好的,所以如果我理解正确,你需要创建一个链接列表,按升序存储分数。据我所知,整个链表已经为您实现,您只需要使用提供的类,并在Scores.java中添加逻辑以保持列表的排序。 / p>

首先,我看到你的节点没有可比性。如果您完全允许更改提供给您的来源,我建议让他们实施Comparable<Node>并覆盖equals(Object o),以便您有逻辑来比较它们。两个节点可以包含相同的元素,但这并不意味着它们是相同的。

请注意方法签名的更改!

//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();
    }
}

重要

请仔细检查这里的逻辑。我没有IDE就很快完成了,因为我现在不在我的开发计算机上。如果有人发现任何问题,请发表评论我会解决。

如果这不是你提出的问题(你的问题有点模糊),请告诉我。


更新2

阅读Comparator hereherehere