0

我是 Java 新手,我正在尝试实现一个链接列表(我确实知道为此目的存在一个列表类,但是从头开始让我了解该语言在内部是如何工作的)

在 main 方法中,我声明了 4 个节点并初始化了 3 个。链表的头节点设置为 null。第一次使用参数head和newNode调用add函数时,head为null,所以我初始化head并将newNode的值赋给它。在 main 方法中,我希望 head 对象应该从 add 方法中设置新值。但是 head 仍然为空。

我很感激理解为什么会这样。

如果代码不干净,请致歉,非常感谢!

public class LinkedList
{
    public void add(Node newNode, Node head)
    {
        if(head == null) 
        {
            head = new Node(); 
            head = newNode;              
        }
        else 
        {
            Node temp = new Node(); 
            temp = head; 

            while(temp.next!=null)
            {
                temp = temp.next; 
            }
            temp.next = newNode; 
        }    
    }

    public void traverse(Node head)
    {
        Node temp = new Node(); 
        temp = head; 

        System.out.println("Linked List:: ");

        while(temp.next!=null);  
        {
           System.out.println(" "  + temp.data); 
            temp = temp.next;
        }
    }

    public static void main(String args[])
    {
        Node head = null;
        Node newNode = new Node(null, 5); 
        Node newNode2 = new Node(null, 15); 
        Node newNode3 = new Node(null,30); 

        LinkedList firstList = new LinkedList(); 

        firstList.add(newNode,head); 

       // Part that I don't understand
       // why is head still null here? 

        if(head==null)
        {
         System.out.println("true");
        }

        firstList.traverse(head); 
        firstList.add(newNode2,head); 
        firstList.traverse(head); 
        firstList.add(newNode3,head); 
        firstList.traverse(head); 

    }

}

public class Node
{
    public Node next; 
    public int data; 

    public Node(Node next, int data)
    {
        this.next = next; 
        this.data = data; 
    }

    public Node()
    {
        this.next = null; 
        this.data = 0; 
    }

}
4

5 回答 5

2

我认为问题出在“添加”函数内部。您只是在函数范围内更改“head”的值,而不是在它之外。您可以在此处找到有关 Java 处理传递参数值的方式的有用信息。

Java 中 LinkedList 的一个很好的实现在 这里

于 2012-08-30T23:07:35.810 回答
2

Java 方法参数是按值传递的。

public void add(Node newNode, Node head)
{
    if(head == null) 
    {
        head = new Node(); 
        head = newNode;              
    }
    ...

head上面只修改了 .范围内的局部变量add。不可能引用head范围内的局部变量。main如果您希望调用者能够检索新值,也许您应该返回该值。


老实说,面向对象编程的一个主要原则是封装;理想情况下head,您LinkedList应该是内部维护的字段。为什么它应该是一个单独的部分?如果你真的希望有head孤立的,那为什么不traverseadd静态呢?您应该尝试修改您的设计。我决定在这里重写你的代码。

final class List {

  private Node head;

  public void add(final Node node) {
    if (head == null) {
      head = new Node();
    }
    Node cur;
    for (cur = head; cur.next != null; cur = cur.next)
      ;
    cur.next = node;
  }

  public String toString() {
    final StringBuilder builder = new StringBuilder("Linked List::");
    for (Node cur = head.next; cur != null; cur = cur.next) {
      builder.append("\n ").append(cur.data);
    }
    return builder.toString();
  }
}

final class Node {

  int data;
  Node next;

  Node(final int data) {
    this.data = data;
  }

  Node() { }
}

...然后,测试:

  private static Node[] nodesFor(final int... values) {
    int n = values.length;
    final Node[] nodes = new Node[n];
    while (n > 0) {
      nodes[--n] = new Node(values[n]);
    }
    return nodes;
  }

  public static void main(final String[] argv) {
    final List list = new List();
    for (final Node node : nodesFor(5, 15, 30)) {
      list.add(node);
      System.out.println(list);
    }
  }
于 2012-08-30T22:26:17.497 回答
1

使“head”引用另一个节点对调用代码没有影响(java传递引用,在java中是地址的“值”)。

你需要一个对头部的永久引用,所以让它成为你类的一个字段:

private Node head = new Node(); // the head of your Node tree

public void add(Node newNode, Node parent) {
    // add node to parent.
    // for some calls, the parent will be the head
}
于 2012-08-30T22:29:41.690 回答
0

这是您的链接列表的更好植入。请注意:

  1. _head 应该是私有成员
  2. 节点是一种内部机制。你应该给你的 add 方法一个 data 参数而不是一个 Node 对象
  3. 我写了这个,简单,但基于你的代码,实现

    public class LinkedList{
    private Node _head;
    public void add(int data)
    {               
            //Understand this code! What happens if _head=null?                 
            _head=new Node(_head,data); 
            /*
                 //Use the following code for a "Normal" nodes-order
                 if(_head==null)
                    _head=new Node(null,data);
                 else{
                   Node temp=_head;
                   while( temp.next!=null)
                      temp=temp.next;            
                   temp.next=new Node(null,data); 
                 }
            */
    }
    public void traverse()
    {
        System.out.println("Linked List:: ");
        Node temp=_head;
        while(temp!=null){
                System.out.println(" "  + temp.data); 
                temp = temp.next;
        }
    }
    public LinkedList(){
        _head=null;         //null is our lists anchor
    }
    
    public static void main(String args[])
    {
        LinkedList firstList = new LinkedList(); 
    
        firstList.add(5); 
        firstList.traverse(); 
        firstList.add(15); 
        firstList.traverse(); 
        firstList.add(30); 
        firstList.traverse(); 
    
    }
    

    }

于 2012-08-30T23:09:43.670 回答
0
    firstList.add(newNode,head); 

   /*
    Part you should know is, head is a local variable pointing to null.
    Passing head as parameter doesn't make it feasible to alter this local variable.
    Your check is worthless.
    Make public Node add(Node newNode, Node head) and return head from there.
   */ 
    head=firstList.add(newNode,head);

    if(head==null)
    {
     System.out.println("true");
    }
于 2012-08-30T22:27:11.617 回答