简体   繁体   English

Java中的自定义LinkedList,其插入顺序保持不变

[英]Custom LinkedList in Java with a maintained order of insertion

I was trying to implement a linked list in Java. 我试图用Java实现一个链表。 I came up with the following simple implementation 我想出了以下简单的实现

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;
    }
  }
}

But one obvious problem I see here is that the order of insertion gets reversed due to my design flaw. 但是我在这里看到的一个明显问题是,由于我的设计缺陷,插入顺序被颠倒了。 But in a LinkedList, the order of insertion should be maintained. 但是在LinkedList中,插入顺序应保持不变。 How would I change this code to do that. 我将如何更改此代码来做到这一点。 I just could not think from a different perspective now. 我现在无法从另一个角度思考。

Try analyzing the problem one step at a time. 尝试一次分析问题。

Let us assume that you want to add the following number sequence into your list - 1, 2, 3, 4, 5. What EXACTLY happens? 让我们假设您想将以下数字序列添加到列表中-1,2,3,4,5。究竟发生了什么?

There is only one field (currentNode) in an object of your LinkedList class. LinkedList类的对象中只有一个字段(currentNode)。 Let's try visualizing it like this; 让我们尝试像这样可视化它;

LinkedList
  currentNode = null

At this point, we don't have any data in the list. 至此,列表中没有任何数据。 Now let's insert the first node (I'm assigning letters to represent them). 现在,我们插入第一个节点(我正在分配字母来表示它们)。

LinkedList
  currentNode = A

The list sequence itself would look like this; 列表序列本身看起来像这样;

null <- A(value = 1)

Now lets add the second data into the list. 现在,将第二个数据添加到列表中。 Note what happens; 注意会发生什么;

LinkedList
  currentNode = B

And the list sequence becomes; 列表序列变为:

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

And a few more elements and you get this situation 还有其他一些元素,您会遇到这种情况

LinkedList
  currentNode = E

with the sequence being; 顺序是

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

In this situation, what is the ONLY order with which you can traverse the list? 在这种情况下,您可以遍历列表的唯一顺序是什么? In reverse. 相反。 Why? 为什么? Because you are only storing the LAST (or tail) node of the list. 因为您仅存储列表的LAST(或尾部)节点。 If you want to retrieve the original order, you'll need to change your logic so that instead of the tail, you are storing the HEAD of the list. 如果要检索原始订单,则需要更改逻辑,以便存储列表的HEAD(而不是尾部)。 For starters, let's rename the field in your class as follows; 首先,让我们按照以下步骤重命名班级中的字段;

public class LinkedList {
    public Node HEAD;
}

The next change we'll need to address is your add() method. 我们需要解决的下一个更改是您的add()方法。 Think with the end objective in mind. 考虑最终目标。 How do you want to store things in the list? 您想如何在列表中存储内容? I suspect this is what you are looking for; 我怀疑这就是您要找的东西;

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

If you have the first element in the above list (HEAD = A), how would you go about adding a new element to the list? 如果您在上面的列表中有第一个元素(HEAD = A),您将如何向列表中添加新元素? You would need to traverse the list till you reach the last node and insert your new value there. 您将需要遍历列表,直到到达最后一个节点,然后在其中插入新值。 So your function would become; 这样您的功能就会变成;

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;
}

To verify this, a small change in your print function is needed (to use HEAD instead of currentNode). 为了验证这一点,需要对打印功能进行一些小的更改(使用HEAD代替currentNode)。 The final class would look like this; 最后一堂课看起来像这样;

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;
        }
    }
}

As far as the remove() method is concerned ... I'll leave that to you as an exercise. 至于remove()方法……我将作为练习留给您。 Can't just give everything away, now can we? 不能只是放弃一切,现在可以吗? ;) ;)

Try this. 尝试这个。 But again you need to check cases where in remove is called without adding any element where in there is a possibility of NPE in your code you need to handle those scenarios and also about thread safety and performance of your list:- 但是再次,您需要检查在调用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;
        }
    }
}

What about: 关于什么:

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

I came up with the following implementation. 我想出了以下实现。

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;
    }
}

and it works fine. 而且效果很好。

Most LinkedLists are implemented with a head and tail . 大多数LinkedList是用headtail Elements are added to end of the linked list, and read from the front of the linked list. 元素将添加到链接列表的末尾,并从链接列表的开头读取。

For example: 例如:

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
}

Objects in the head position should not be read. 头部位置的物体不应被读取。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM