【问题标题】:Circular LinkedList implementation in JavaJava中的循环链表实现
【发布时间】:2012-09-02 13:30:35
【问题描述】:

这是一个任务。我必须创建一个循环链表并删除列表中的每三个数字。当我的程序到达列表的末尾时,它应该回到头部并继续该过程,直到只剩下一个数字。

我在网上搜索了一些其他参考书,但无法解决我的问题。我发现的大多数参考资料都说:

除了循环列表没有结尾之外,它们与常规列表完全一样

或(取自我的教科书):

如果最后一个节点的后继节点是第一个,则单链表是循环链接的

但是这些并没有说明如何去做。我也尝试过使用我在这个网站上找到的一些代码,但这并没有解决任何问题。

我可以创建一个列表(我不知道它是否是一个循环链表)并显示它,但是元素的顺序很奇怪:

  • 如果列表有 6 个数字,则列表将为 1,6,5,4,3,2。
  • 如果列表有 8 个数字,则列表将为 1,8,7,6,5,4,3,2。

如果没有正确的列表,我可以正确地进行删除。以下代码有什么问题:

public class LastNumberDemo {
    public static void main(String[] args) {
        LastNumberNode ll=new LastNumberNode();
        System.out.println("how long is the list: ");
        Scanner keyboard = new Scanner(System.in);
        int input = keyboard.nextInt();

        if(input<=0) {
            System.out.println("no number to creat list");
        }
        if(input==1) {
            System.out.println("The Last number is 1.");
        }
        else {
            String[] n=new String[input];
            for(int index=0; index<n.length; index++)
                n[index]=Integer.toString(index+1);
            for(String e:n)
                ll.add(e);
            System.out.print("The list contains: \n");
            ll.print();
            System.out.print("\nThe last number is: ");
            ll.remove();
            ll.print();
        }
    }
}

//The circular linked list class
class LastNumberNode{
    private class Node{
        String value;  
        Node next;     

        Node(String val, Node n){
            value = val;
            next = n;
        }

        Node(String val){
            value=val;
            next=null;
        }
    } //This brace was missing - Edd

    private Node first;

    public LastNumberNode(){
      first = null;
    }

    public boolean isEmpty(){        
       return first == null;
    }

    public int size(){
        int count = 0;
        Node p = first.next;   
        while (p != first){
            count ++;
            p = p.next;
        }
        return count;
    }

    public void add(String e) {
        Node p=new Node(e);
        if(first==null){
            first=p;
            first.next=first;
        }
        else{
            first.next=new Node(e,first.next);
        }
    }

    public void remove(){
        while(size()>0){
            Node target=first.next.next;   
            Node temp=first;               
            target=target.next;          
            last.next=temp;
            first=target;
        }
    }

    public void print(){
        Node ref=first;
        for(int index=-1; index<size();index++)
            System.out.print(ref.value+" ");
        ref=ref.next;
    }
} //Extra brace removed - Edd

【问题讨论】:

  • 关闭内部类 Node 的大括号被放置在 LastNumberNode 类的最底部。

标签: java linked-list circular-list


【解决方案1】:

当您将新的Node 添加到您的列表中时,您会将新的Node 添加到第二个位置(first.next 指向您新添加的节点),但是这个新添加的节点将first 作为它的下一个节点,使列表的其余部分未被引用(因此被垃圾收集和销毁)。使用您的 add 方法,您的列表不可能包含除 0、1 或 2 Nodes 之外的任何内容。在列表中间添加新的Node 有点奇怪;要么将其添加到前面 (newnode.next = first; first = newnode; last.next = first;),要么保留对列表后面的引用(正如其他人建议的那样),然后将其添加到那里。

就个人而言,我会重组LastNumberNode 类,使其具有以下操作链表的方法:

  • private void addNode(Node node)
  • private void removeNode(Node node)
  • private Node findNode(Node nextNode)

如果您维护对列表中最后一个节点的引用,那么您的 addNode(Node node) 方法可能类似于以下内容:

if(isEmpty()) {
    first = node;
    last = node;
}
else {
    Node tail = last;
    tail.next = node;
    node.next = first;
    last = node;
}

removeNode(Node node) 基于以下内容:

Node prevNode = findNode(node);

if(node == first) {
    first = node.next;
    last.next = first;
}
else if(node == last) {
    prevNode.next = first;
    last = prevNode;
}
else {
    prevNode.next = node.next;
}

如果我要实现这一点,我可能会使用这种方法将列表缩减为单个 Node

public String reduceList() {
    Node curNode = first;
    while(first != last) {
        removeNode(curNode.getNext().getNext());
        curNode = curNode.getNext().getNext();
    }

    return first.getValue();
}

最后一点,我不会费心用序列号填充数组,然后遍历它以将元素添加到列表中。我会直奔以下内容:

for(int i = 1; i <= input; i++) {
    linkedlist.add(new Integer(i).toString());
}

【讨论】:

  • 您好 Edd,非常感谢您的建议。我重新设计了这些方法。现在我的 remove() 代码是: Node target=first.next;目标.下一个=目标.下一个.下一个;第一=目标。下一个;它完美地工作。再次感谢
【解决方案2】:

如果 first 已经设置,您的 add 方法会直接在 first 之后插入元素:

first.next = new Node(e, first.next);

这会导致观察到的行为。

如果要将新元素附加到列表末尾,则需要跟踪列表的 last 元素并将新元素添加为 last.next。一种方法是简单地保存对列表类成员变量中最后一个元素的引用,另一种方法是遍历列表,直到找到链接到 first 的节点,这将是最后一个节点。

【讨论】:

  • 我将其替换为:else{last.next= new Node(e, first.next);} 但 java 向我展示了 nullpointerexception。
  • 这样做会将最后一个节点链接到新节点,并将新节点链接到第二个节点。我很确定这不是你想要做的。
  • 谢谢大家。这就是我所做的。我已将该位更改为:last.next=new Node(e) 然后 last = last.next,然后 last.next = first。有用。现在的问题是从列表中删除第三个项目。
猜你喜欢
  • 2018-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多