【问题标题】:error in deleting a node from singly linked circular linked list in Java从 Java 中的单链循环链表中删除节点时出错
【发布时间】:2014-01-30 22:26:22
【问题描述】:

我在从专门删除头节点的循环链表中删除节点时遇到了一些麻烦。我尝试调试代码,我发现的问题是头节点在删除后没有得到更新。这意味着如果我的列表是 1->2->3->1(这里末尾的 1 实际上是头节点 1 的重复以显示循环链接列表),在尝试删除 '1' 后,列表变为 1->2- >3->2...所以基本上头节点没有得到更新,因此当我尝试打印这个链表时,它进入无限循环,因为头节点只遇到一次并且不再满足停止条件。以下是我为删除而编写的代码

public class cirlinklist {

private int data;
private cirlinklist next;
private cirlinklist head;

public cirlinklist()
    {
    data = 0;
    next = this;
    }

public cirlinklist(int val) 
    {
    data = val;
    next = this;
    }

public void cirlist(int val)
    {
    cirlinklist node = new cirlinklist(val);

    if(this.next == this)                         //only one node present
        {
        node.next = this;
        this.next = node;
        }

    else
        {

        cirlinklist temp = this.next;
        //cirlinklist head = this;
        /*while(node != head)
            node = node.next;*/
        node.next = temp.next;                    //adding after the last added node.For adding before last added node change to temp here and temp.next in next line    
        this.next.next = node;
        }

    }

public void printlist()
    {
    //cirlinklist head = this;                             //start node
    cirlinklist node = this;                             //node for traversing and printing
    System.out.println("Circular Link list data is:");

    do
        {
        System.out.println(node.data);
        node = node.next;
        }
    while(node != head);
    System.out.println(node.data);
    }

public void check()
    {

    }

public cirlinklist delete(int val)
    {
    head = this;
    cirlinklist node = head;
    cirlinklist node2 = node;
    if(head.data == val)                   //if the node to be deleted is head node
        {
        //this = this.next;
        while(node.next != head)          //iterate till the last node i.e. the node which is pointing to head
            {
            node = node.next;
            }
        node.next = node.next.next;       // update current node pointer to next node of head

        //node = node.next;

        head = head.next;                //update head node

        /*this.next = head.next.next;
        this.data = head.next.data;*/

        return this;
        }
    else                                // if node to be deleted is other than head node
        {
        while(node.data != val)        // find the node
            {
            node = node.next;
            node2.next = node;
            }
        node2.next = node.next; //updating next field of previous node to next of current node.current node deleted
        node = null;
        return this;
        }
    }

public static void main(String [] args)
    {
    cirlinklist obj = new cirlinklist(1);
    cirlinklist obj2 = new cirlinklist();
    //obj.cirlist(1);
    obj.cirlist(2);
    obj.cirlist(3);

    obj.printlist();
    obj2 = obj.delete(1);
    System.out.println("Circular list after deletion is");
    obj2.printlist();
    }
}

请告诉我哪里出错了

【问题讨论】:

  • 在你给我们的例子中,如果我想删除'1',它应该删除第一个和最后一个?
  • @HugoSousa 最后的'1'节点实际上只是头节点。因为它是循环链接列表所以我重复了'1'。实际上只有一个'1'是头节点
  • 请注意,如果我们可以看到其余代码,调试起来会更容易,因为您所做的一切都是用 void 函数进行的,并且没有可见的全局数据使用。
  • @RyanJ 我已经在上面的帖子中进行了更改。我已经发布了完整的代码,并进行了一些修改,但仍然存在相同的无限循环问题

标签: java linked-list


【解决方案1】:
if(head.data == val)                   //if the node to be deleted is head node
    {
    //this = this.next;
    while(node.next != head)          //iterate till the last node i.e. the node which is pointing to head
        {
        node = node.next;
        }
    node.next = node.next.next;      // update current node pointer to next node of head
    //node = node.next;
    head = head.next;                //update head node
    }

在这段代码中,头指向的位置在哪里

node.next = node.next.next ?

可能问题出在那儿。

【讨论】:

    【解决方案2】:

    自从发布此答案以来,您的代码发生了很大变化,因此我重新开始。我可以解决您目前存在的问题,但您的列表设计确实存在一些问题,我会提到并建议您重新设计您拥有的内容。

    首先,您的打印功能正在中断,因为您没有设置head 的任何内容,您可以使用它来确定何时继续打印。

    将你的构造函数修改为:

    public cirlinklist()
    {
        data = 0;
        next = this;
        head = this;
    }
    
    public cirlinklist(int val)
    {
        data = val;
        next = this;
        head = this;
    }
    

    其次,您的删除函数需要返回 head,因为这是您在该函数中修改的内容。

    我在这里发布了清洁功能:

    public cirlinklist delete(int val)
    {
    
        cirlinklist node = head;
    
    
        if(head.data == val)                   //if the node to be deleted is head node
        {
            //this = this.next;
            while(node.next != head)          //iterate till the last node i.e. the node which is pointing to head
            {
                node = node.next;
            }
            node.next = node.next.next;       // update current node pointer to next node of head
    
            //node = node.next;
    
            head = head.next;                //update head node
    
        /*this.next = head.next.next;
        this.data = head.next.data;*/
    
            return this;
        }
        else                                // if node to be deleted is other than head node
        {
            cirlinklist prev = node;               // track previous node from current (node)
            while(node.data != val)        // find the node
            {
                prev = node;
                node = node.next;
            }
            prev.next = node.next; //updating next field of previous node to next of current node.current node deleted
            return head;
        }
    }
    

    这应该可以得到你想要的。

    但是,您还没有看到一个问题,如果您尝试返回 head,然后希望它是列表的副本,那么它不是。您实际上是在修改头列表,然后在它返回时将其分发给其他方法,这意味着 cirlist obj2 = obj.delete(1); 不会为您提供已删除列表的新副本,而使 obj 保持不变。如果您在此之后添加另一个删除操作并打印,您可以看到这一点。

    话虽如此,我修改了函数以在删除中间节点时正确反应。

    您可能还想测试的另一件事是删除尾节点,因为您也可能遇到这种情况的问题。

    我建议的最后一件事是重新定义数据结构。在这种情况下,您使用标识符 node 来表示列表节点,而事实上,正如您定义的那样,它们实际上是列表本身。通常定义的链表是一组链接在一起的节点,整个集合就是链表。

    如果您创建一个数据结构来表示node,即它是一个具有数据元素和指向下一个节点的指针的对象,那么您的列表可以完全位于不同的类中,您可以对其进行操作节点,同时只保留列表的一个副本,您可以更轻松地控制和复制。

    类似这样的:

    public class ListNode {
        public int data;
        public ListNode next = null;
    
        public ListNode() {
           data = 0;
        }
    
        public ListNode(int data) {
           this.data = data;
        }
    
        public ListNode(ListNode node) {
           if ( node != null) {
              this.data = node.data;
              this.next = node.next;
           }
        }
    }
    

    然后你可以有另一个真正提供操作的类

    public class CircularLinkedList {
        public ListNode head;
    
        public CircularLinkedList(...) {}
    
        public void addToList(int data) {}
        public void deleteFromList(int data) {}
    
        ... // and so-on
    }
    

    在这种情况下,head 是您的列表,任何时候您进行更改或需要对其进行操作时,您都可以根据 head 定义执行此操作的函数,然后采取适当的行动。

    祝你好运

    【讨论】:

    • 我也尝试过这样做,但仍然无法解决问题。我已经在上面发布了我的完整代码以及您的建议(现在已注释掉,但我尝试过)但仍然相同出现死循环问题
    猜你喜欢
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多