从链表中删除节点时出现逻辑错误

时间:2016-07-27 07:56:15

标签: java data-structures linked-list

我正在尝试创建一种从链表中删除节点的方法(可能是第一个节点,中间节点或最后一个节点)。这是方法:

public static Node deleteNode(Node head, int value){
    if(head==null){
        return null;
    }else{
        if(head.next==null){ // if there is only one element 
            if(head.value == value){
                head =null; 
            }
        }
        else{                 // if there a more than one elements in the list
            Node t1= head;
            Node t2 = head.next;
            while(t2.next!=null){
                if(t2.value ==value){
                    t1 = t2.next;
                    t2.next=null; 
                    return t2; 
                }
                t2 = t2.next;
                t1 = t1.next; 
            }
            return null; 
        }
    }
    return null; 
}

为了测试这个方法,我添加了一些节点,其中包含我之前制作的两个方法,然后告诉它查找链表中是否有9并删除它:

    head = addAtTheBeginning(head,3); printLinkedList(head); 
    head = addAtTheBeginning(head,19);printLinkedList(head); 
    head = addAtTheBeginning(head, 4);printLinkedList(head); 
    head = addAtTheBeginning(head, 9);printLinkedList(head); 
    head = addAtTheBeginning(head, 7); printLinkedList(head); 
    head = addAtTheEnd(head, 100); printLinkedList(head); 
    head = addAtTheEnd(head, 200); printLinkedList(head); 
    System.out.println("---"); 
    Node del = deleteNode(head, 9);
    System.out.println(del); 
    System.out.println("---"); 
    del.printNode();
    printLinkedList(head);

打印出来:

[3]->]
[19]->[3]->]
[4]->[19]->[3]->]
[9]->[4]->[19]->[3]->]
[7]->[9]->[4]->[19]->[3]->]
[7]->[9]->[4]->[19]->[3]->[100]->]
[7]->[9]->[4]->[19]->[3]->[100]->[200]->]
---
[9]->
---
[9]->[7]->[9]->]

我相信我的代码中存在逻辑错误,但我找不到它。

这是完整的代码,因此您可以更好地理解它。

class Node{
    public int value; 
    public Node next;

    public Node (int value){
        this.value = value;
        this.next = null; 
    }

    public void printNode(){
        System.out.print( this.toString() ); 
    }

    public String toString(){
        return new String("["+value+"]->");
    }


}

public class m14_06{
    public static void main(String[] args){
        Node head = null; 

        head = addAtTheBeginning(head,3); printLinkedList(head); 
        head = addAtTheBeginning(head,19);printLinkedList(head); 
        head = addAtTheBeginning(head, 4);printLinkedList(head); 
        head = addAtTheBeginning(head, 9);printLinkedList(head); 
        head = addAtTheBeginning(head, 7); printLinkedList(head); 
        head = addAtTheEnd(head, 100); printLinkedList(head); 
        head = addAtTheEnd(head, 200); printLinkedList(head); 
        System.out.println("---"); 
        Node del = deleteNode(head, 9);
        System.out.println(del); 
        System.out.println("---"); 
        del.printNode();
        printLinkedList(head); 

    }


    public static Node deleteNode(Node head, int value){
        if(head==null){
            return null;
        }else{
            if(head.next==null){ // if there is only one element 
                if(head.value == value){
                    head =null; 
                }
            }
            else{                 // if there a more than one elements in the list
                Node t1= head;
                Node t2 = head.next;
                while(t2.next!=null){
                    if(t2.value ==value){
                        t1 = t2.next;
                        t2.next=null; 
                        return t2; 
                    }
                    t2 = t2.next;
                    t1 = t1.next; 
                }
                return null; 
            }
        }
        return null; 
    }

    /*
    * returns the number of Node in the linked list. 
    */
    public static int countElements(Node head){
        int count = 0; 
        Node t = head;
        while(t!=null){ // while t does point to a node. 
            count++;   // count the node
            t=t.next;  // move to the next

        }
        return count; 
    }

    public static Node search(Node head, int value){
        Node p = head;
        while(p!=null){
            if(p.value==value){
                return p;
            }
            p = p.next; 
        }
        return null; 
    }

    public static void printLinkedList(Node head){
        Node p = head;
        while(p!=null){
            p.printNode();
            p = p.next;
        }
        System.out.println("]"); 
    }

    public static Node addAtTheBeginning(Node head, int value){
        Node temp = new Node(value); 
        if(head==null){
            head = temp ; 
            return head; 
        }else{
            temp.next = head;  // (1) 
            head = temp; 
        }
        return head; 
    }

    public static Node addAtTheEnd(Node head, int value){
        Node temp = new Node(value);
        Node p; 
        if(head == null){
            head = temp;
            return head; 
        }else{
            p = head;
            while(p.next!=null){
                p=p.next;
            }
            p.next = temp; 
            return head; 
        }
    }   
}

感谢。

5 个答案:

答案 0 :(得分:0)

   public static Node deleteNode(Node head, int value){
    if(head==null){
        return null;
    }else{
        if(head.next==null){ // if there is only one element 
            if(head.value == value){
                head =null; 
            }
        }
        else{                 // if there a more than one elements in the list
            Node t1= head;
            Node t2 = head.next;
            while(t2.next!=null){
                if(t2.value ==value){
                    t1 = t2.next;
                    t2.next=null; 
                    return t2; 
                }
                t2 = t2.next;
                t1 = t1.next; 
            }
            return null; 
        }
    }
    return null; 
}

好的,从哪里开始......返回值在这里完全无关紧要。你从不使用它。即使你这样做,你几乎总是返回null,除非你返回想要删除的节点。

此外,您永远不会删除您要搜索的节点。决不。

让我们先来看看它不是头脑。您将找到节点(在您的示例中为9)并删除后面的所有内容:

if(t2.value ==value){
    t1 = t2.next;
    t2.next=null; 
    return t2; 
}

这将删除您要删除的备注后面的所有内容(t2.next=null)。 此外,t1 = t2.next;完全没有意义,因为你在返回后再也不会使用t1。

if(t2.value ==value){
    t1.next = t2.next;
    return; 
}

这更符合您的需求。您需要通过将t1的下一个设置为t2的下一个来“跳过”t2。我还删除了不必要的返回类型,但只有在方法无效时才会有效。

好的,下一步:如果是头脑怎么办?

您将设置head = null;

如果它有效,那将是很好的,除非它不会,因为你只会将参数指向的对象更改为null,而不是列表的实际头部指向的对象。

遗憾的是,使用这样的静态方法,你根本无法删除头部。您可以使用返回值来指示您需要在方法之后移除头部,但这会使目的失败。

更好的选择可能是使用列表参数而不是节点参数,因此您可以更改给定列表的实际引用,而不仅仅是本地引用。

答案 1 :(得分:0)

此解决方案将从输入列表中删除所有匹配节点。如果您只想删除第一个匹配节点,下面的代码需要一个轻微的重构。我已经在IntelliJ上测试了这个代码,它可以正确地用于每个用例。

public static Node deleteNode(Node head, int value) {
    if (head == null) {
        return null;
    }

    while (head.value == value) {
        head = head.next;
        if (head == null) return null;
    }

    Node t1 = head;
    Node t2 = t1.next;

    while (t2 != null) {
        // check for a match
        if (t2.value == value) {
            // splice out node t2
            t1.next = t2.next;
            t2 = t2.next;
        }
        // otherwise advance pointers by one
        else {
            t1 = t2;
            t2 = t2.next;
        }
    }

    return head; 
}

答案 2 :(得分:0)

相反,这部分

<?php

class DB_Functions {

private $conn;

// constructor
function __construct() {
    require_once 'DB_Connect.php';
    // connecting to database
    $db = new Db_Connect();
    $this->conn = $db->connect();
}

// destructor
function __destruct() {

}

/**
 * Storing new user
 * returns user details
 */
public function storeUser($username, $email, $country, $phone_number, 
$password, $lat, $lon) {
    $uuid = uniqid('', true);
    $height = 0; 
    $weight = 0;
    $is_number_verified = False;
    $is_safe = True;
    $is_login = False;
    $hash = $this->hashSSHA($password);
    $encrypted_password = $hash["encrypted"]; // encrypted password
    $salt = $hash["salt"]; // salt

    $stmt = $this->conn->prepare("INSERT INTO users (unique_id, username, 
email, country, phone_number, password, salt, height, weight, 
is_number_verified, is_safe, is_login, lat, lon, created_at) VALUES(?, ?, ?, 
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,NOW())");
    $stmt->bind_param("ssssssssssssss", $uuid, $username, $email, $country, 
$phone_number, $encrypted_password, $salt, $height, $weight, 
$is_number_verified, $is_safe, $is_login, $lat, $lon);
    $result = $stmt->execute();
    $stmt->close();

    // check for successful store
    if ($result) {
        $stmt = $this->conn->prepare("SELECT * FROM users WHERE phone_number 
= ?");
        $stmt->bind_param("s", $phone_number);
        $stmt->execute();
        $user = $stmt->get_result()->fetch_assoc();
        $stmt->close();

        return $user;
    } else {
        return false;
    }
}
}
?>

if (t2.value == value) { 
t1 = t2.next;
t2.next = null;
return t2;
}

然后列表将删除[9],如if (t2.value == value) { t1.next = t2.next; return t2; }

答案 3 :(得分:0)

我已经发布了一个答案,这个问题只是为了帮助您了解代码出了什么问题(我将假装初始列表以3结尾):

enter image description here

答案 4 :(得分:0)

在deleteNode中检查多个元素的其他部分中,使用以下条件更改条件:

     while (t2.next != null) {
        if (t2.value == value) {
            t1.next = t2.next;
            t2.next = null;
            return t2;
        }
        t2 = t2.next;
        t1 = t1.next;
     }

同时显示您在打印已删除节点和打印列表之间没有给出空间。这就是为什么它看起来像删除节点在开始时添加。请给那里的println:

del.printNode();
System.out.println("  ");
printLinkedList(head);

希望它有所帮助。 :)