从Java中单个链接的循环链表中删除节点时出错

时间:2014-01-30 22:26:23

标签: java linked-list

我在删除循环链接列表中的节点时遇到了一些麻烦,特别是删除了头节点。我试图调试代码和问题,我发现删除后头节点没有得到更新。这意味着我的列表是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();
    }
}

请告诉我哪里出错了

2 个答案:

答案 0 :(得分:0)

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 ?

可能就是问题所在。

答案 1 :(得分:0)

由于你的代码发布后我的代码发生了很大的变化,所以我开始新鲜了。我可以解决您目前存在的问题,但是您的列表设计确实存在一些问题我会提及并建议您重新设计所拥有的问题。

首先,您的打印功能正在破坏,因为您没有设置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方面执行此操作的函数,然后执行相应的操作。

祝你好运