Java中的自定义LinkedList,具有维护的插入顺序

时间:2014-08-26 04:04:12

标签: java data-structures

我试图用Java实现链表。我想出了以下简单的实现

public class Node{
  public String data;
  public Node next;
  public Node(String data){
     this.data = data  
  }
}

public class LinkedLst{
  public Node currentNode;

  public void add(String data){
    Node newNode = new Node(data);
    newNode.next = currentNode;
    currentNode = newNode;
  }
  public Node remove(){
    Node temp = currentNode;
    currentNode = currentNode.next;
    return temp;
  }
  public void printList(){
    Node temp = currentNode;
    while(temp!=null){
      System.out.println(temp.data + ",");
      temp = temp.next;
    }
  }
}

但我在这里看到的一个明显问题是由于我的设计缺陷,插入的顺序被颠倒了。但是在LinkedList中,应该保持插入顺序。我如何更改此代码来执行此操作。我现在无法从不同的角度思考。

5 个答案:

答案 0 :(得分:2)

尝试一步一步地分析问题。

我们假设您要在列表中添加以下数字序列 - 1,2,3,4,5。究竟发生了什么?

LinkedList类的对象中只有一个字段(currentNode)。让我们试着像这样想象它;

LinkedList
  currentNode = null

此时,我们列表中没有任何数据。现在让我们插入第一个节点(我指的是代表它们的字母)。

LinkedList
  currentNode = A

列表序列本身看起来像这样;

null <- A(value = 1)

现在让我们将第二个数据添加到列表中。注意会发生什么;

LinkedList
  currentNode = B

列表序列变为;

null <- A(value = 1) <- B(value = 2)

还有一些元素,你得到这种情况

LinkedList
  currentNode = E

序列为;

null <- A(value = 1) <- B(value = 2) <- C(value = 3) <- D(value = 4) <- E(value = 5)

在这种情况下,您可以遍历列表的唯一顺序是什么?相反。为什么?因为您只存储列表的LAST(或尾部)节点。如果要检索原始订单,则需要更改逻辑,以便存储列表的HEAD而不是尾部。首先,让我们按照以下方式重命名班级中的字段;

public class LinkedList {
    public Node HEAD;
}

我们需要解决的下一个更改是你的add()方法。考虑最终目标。你想如何在列表中存储东西?我怀疑这就是你要找的东西;

A(value = 1) -> B(value = 2) -> C(value = 3) -> D(value = 4) -> E(value = 5) -> null

如果您有上面列表中的第一个元素(HEAD = A),您将如何向列表中添加新元素?您需要遍历列表,直到到达最后一个节点并在那里插入新值。所以你的功能会变成;

public void add(String data) {
    Node newNode = new Node(data);
    // check if HEAD is empty or not
    if (HEAD == null) {
        HEAD = newNode;
        return;
    }
    Node temp = HEAD;
    while(temp.next != null) {
        temp = temp.next;
    }
    // we must be at the end of the list now.
    // add the next element in here.
    temp.next = newNode;
}

要验证这一点,需要对打印功能进行少量更改(使用HEAD而不是currentNode)。最后一堂课看起来像这样;

public class LinkedList {
    public Node HEAD;

    public void add(String data) {
        Node newNode = new Node(data);
        // check if HEAD is empty or not
        if (HEAD == null) {
            HEAD = newNode;
            return;
        }
        Node temp = HEAD;
        while(temp.next != null) {
            temp = temp.next;
        }
        // we must be at the end of the list now.
        // add the next element in here.
        temp.next = newNode;
    }

    public void printList() {
        Node temp = HEAD;
        while(temp != null) {
            System.out.print(temp.data + " -> " );
            temp = temp.next;
        }
    }
}

就remove()方法而言......我会把它作为练习留给你。不能只是放弃一切,现在可以吗? ;)

答案 1 :(得分:1)

试试这个。但是你需要检查一下在调用remove的情况下如何调用remove而不添加任何元素,你的代码中可能存在NPE,你需要处理这些场景以及你的列表的线程安全性和性能: -

package com.test.java;

import java.util.concurrent.atomic.AtomicInteger;

class Node<T> {
    T data;
    Node next;  
    int index;
    static AtomicInteger position = new AtomicInteger();
    public Node(T data){
        this.data = data;
        this.index = position.incrementAndGet(); 
    }
    @Override
    public String toString() {      
        return data.toString();
    }
}

public class LinkedLst<T> {
    private Node currentNode;

    public void add(T data){
        Node newNode = new Node(data);
        newNode.next = currentNode;
        currentNode = newNode;
    }

    public Node remove(){
        Node temp = currentNode;
        currentNode = currentNode.next;
        return temp;
    }

    public Node get(int index) {
        Node temp = currentNode;
        while(temp!=null){
            if(index == temp.index) {
                return temp;
            }
            temp = temp.next;
        }
        return null;
    }

    public void printList(){
        Node temp = currentNode;
        while(temp!=null){
            System.out.println(temp.data + ",");
            temp = temp.next;
        }
    }
}

答案 2 :(得分:0)

怎么样:

public void add(String data){
  Node newNode = new Node(data);
  newNode.next = currentNode.next;
  currentNode.next = newNode;
} 

答案 3 :(得分:0)

我想出了以下实现。

public class LinkedLst {
    public Node head;
    public Node prev;
    public Node last;

    public void add(String data) {
        Node newNode = new Node(data);
        if(head == null){
            head = newNode;
            prev = newNode;
            last = newNode;
            return;
        }else if(head == last){
            prev.next = newNode;
            last = newNode;
            return;
        }
        prev = prev.next;
        prev.next = newNode;
        last = newNode;
    }

    public void fwdPrintList() {
       Node temp = head;
       while (temp!=null){
           System.out.println(temp.data);
           temp = temp.next;
       }
    }

    public Node remove(){
        if(isEmpty()){
            System.out.println("List is Empty");
            return head;
        }
        Node temp = head;
        head = head.next;
        return temp;
    }
    public boolean contains(String data) {
        Node temp = head;
        while (temp!=null){
            if (temp.data.equals(data)) {
                return true;
            }
        temp = temp.next;
        }
        return false;
    }

    public boolean isEmpty(){
        if(head==null){
            return true;
        }
        return false;
    }
}

它工作正常。

答案 4 :(得分:0)

大多数LinkedLists都是使用headtail实现的。元素将添加到链接列表的末尾,并从链接列表的前面读取。

例如:

private Node head = new Node(null);
private Node tail = head;

public void add(Object o) {
    Node node = new Node(o);
    tail.next = node;
    tail = node; // Swing tail to the added node
}

public Object peek() {
    if (head != tail)
        return head.next.value; // Value of the next node
    return null; // Empty
}

public Object poll() {
    if (head != tail) {
        Object o = head.next.value;
        head = head.next;
        return o;
    }
    return null; // Empty
}

不应读取头部位置的物体。