从头开始创建 LinkedList 类

Posted

技术标签:

【中文标题】从头开始创建 LinkedList 类【英文标题】:Creating a LinkedList class from scratch 【发布时间】:2011-05-03 06:38:46 【问题描述】:

我们被分配了从头开始创建 LinkedList 的任务,但绝对没有任何读数可以指导我们完成这个导致偏头痛的任务。此外,网上的一切似乎都只是使用 Java 内置的 LinkedList 方法和东西。无论如何,链表在使用 Java 的默认东西时非常有意义,但从头开始创建它是没有任何意义的。假设我有

public class LinkedList 
  private LinkedList next;  
  private final String word;
  // constructor
  public LinkedList(String word, LinkedList next) 
    this.word = word;
    this.next = next;
  

因此神奇地我们有一个链表。到底是怎么回事?我是如何创建这样的链表的?这是如何运作的?我应该编写一个追加方法,将给定的String word 参数添加到this 链表的末尾。我尝试查看内置 java 链表类的 addLast 内置方法,但这对我没有帮助,因为我真的不明白发生了什么。有人愿意帮助我:)

【问题讨论】:

【参考方案1】:

请在下面找到程序

class Node 
    int data;
    Node next;

    public Node(int data) 
        this.data = data;
        this.next = null;
    


public class LinkedListManual 

    Node node;

    public void pushElement(int next_node) 
        Node nd = new Node(next_node);
        nd.next = node;
        node = nd;
    

    public int getSize() 
        Node temp = node;
        int count = 0;
        while (temp != null) 
            count++;
            temp = temp.next;
        
        return count;
    

    public void getElement() 
        Node temp = node;
        while (temp != null) 
            System.out.println(temp.data);
            temp = temp.next;
        
    

    public static void main(String[] args) 
        LinkedListManual obj = new LinkedListManual();
        obj.pushElement(1);
        obj.pushElement(2);
        obj.pushElement(3);
        obj.getElement(); //get element
        System.out.println(obj.getSize());  //get size of link list
    


【讨论】:

【参考方案2】:

如果您实际上是在构建一个真实的系统,那么是的,如果您需要的东西在那里可用,您通常只需使用标准库中的东西。也就是说,不要认为这是一个毫无意义的练习。了解事物的工作原理很好,了解链表是了解更复杂数据结构的重要一步,其中许多数据结构在标准库中不存在。

创建链接列表的方式与 Java 集合 API 的创建方式之间存在一些差异。 Collections API 试图遵循更复杂的接口。 Collections API 链表也是一个双向链表,而您正在构建一个单链表。你正在做的更适合课堂作业。

对于您的LinkedList 类,实例将始终是至少一个元素的列表。通过这种设置,您可以在需要空列表时使用 null

next 视为“列表的其余部分”。事实上,许多类似的实现使用名称“tail”而不是“next”。

这是一个包含 3 个元素的 LinkedList 的图表:

请注意,它是一个 LinkedList 对象,指向一个单词(“Hello”)和一个包含 2 个元素的列表。 2 个元素的列表有一个单词(“Stack”)和一个包含 1 个元素的列表。 1 个元素的列表有一个单词(“溢出”)和一个空列表(null)。因此,您可以将 next 视为恰好是一个短一个元素的另一个列表。

您可能想要添加另一个只接受字符串的构造函数,并设置在null 旁边。这将用于创建一个 1 元素列表。

要追加,请检查 next 是否为 null。如果是,则创建一个新的元素列表并将next 设置为该列表。

next = new LinkedList(word);

如果 next 不是 null,则追加到 next

next.append(word);

这是递归方法,代码量最少。您可以将其转换为迭代解决方案,这在 Java* 中会更有效,并且不会冒着列表很长的堆栈溢出的风险,但我猜不需要那种复杂程度为你的任务。


* 一些语言有尾调用消除,这是一种优化,允许语言实现将“尾调用”(作为返回前的最后一步调用另一个函数)转换为(有效)“goto” .这使得此类代码完全避免使用堆栈,从而使其更安全(如果不使用堆栈,则不能溢出堆栈)并且通常更高效。 Scheme 可能是具有此功能的语言中最著名的示例。

【讨论】:

好的,递归方法是我需要的,但我不明白它是如何工作的。因此,如果它为空,那么任务很简单。如果不是,我们在 next 上再次运行 append。如果 next.next==null?我不明白,这是如何工作的? 如果next.next==null 那么这意味着下一个不是null。所以你打电话给next.append(word)。现在我们在what-was-nextappend 方法中。所以我们现在称之为this 就是我们之前称之为next 的东西。我们查看next(我们之前会称之为next.next),它是null,所以我们设置next = new LinkedList(word)【参考方案3】:

具有以下功能的链表程序

1 Insert At Start
2 Insert At End
3 Insert At any Position
4 Delete At any Position
5 Display 
6 Get Size
7 Empty Status
8 Replace data at given postion
9 Search Element by position
10 Delete a Node by Given Data
11 Search Element Iteratively
12 Search Element Recursively




 package com.elegant.ds.linkedlist.practice;

import java.util.Scanner;

class Node 

    Node link = null;
    int data = 0;

    public Node() 
        link = null;
        data = 0;
    

    public Node(int data, Node link) 
        this.data = data;
        this.link = null;
    

    public Node getLink() 
        return link;
    

    public void setLink(Node link) 
        this.link = link;
    

    public int getData() 
        return data;
    

    public void setData(int data) 
        this.data = data;
    



class SinglyLinkedListImpl 

    Node start = null;
    Node end = null;
    int size = 0;

    public SinglyLinkedListImpl() 
        start = null;
        end = null;
        size = 0;
    

    public void insertAtStart(int data) 
        Node nptr = new Node(data, null);
        if (start == null) 
            start = nptr;
            end = start;
         else 
            nptr.setLink(start);
            start = nptr;
        
        size++;
    

    public void insertAtEnd(int data) 
        Node nptr = new Node(data, null);
        if (start == null) 
            start = nptr;
            end = nptr;
         else 
            end.setLink(nptr);
            end = nptr;
        
        size++;
    

    public void insertAtPosition(int position, int data) 
        Node nptr = new Node(data, null);
        Node ptr = start;
        position = position - 1;
        for (int i = 1; i < size; i++) 
            if (i == position) 
                Node temp = ptr.getLink();
                ptr.setLink(nptr);
                nptr.setLink(temp);
                break;
            
            ptr = ptr.getLink();
        
        size++;
    

    public void repleaceDataAtPosition(int position, int data) 
        if (start == null) 
            System.out.println("Empty!");
            return;
        

        Node ptr = start;
        for (int i = 1; i < size; i++) 
            if (i == position) 
                ptr.setData(data);
            
            ptr = ptr.getLink();
        
    

    public void deleteAtPosition(int position) 
        if (start == null) 
            System.out.println("Empty!");
            return;
        

        if (position == size) 
            Node startPtr = start;
            Node endPtr = start;
            while (startPtr != null) 
                endPtr = startPtr;
                startPtr = startPtr.getLink();
            
            end = endPtr;
            end.setLink(null);
            size--;
            return;
        

        Node ptr = start;
        position = position - 1;
        for (int i = 1; i < size; i++) 

            if (i == position) 
                Node temp = ptr.getLink();
                temp = temp.getLink();
                ptr.setLink(temp);
                break;
            
            ptr = ptr.getLink();
        
        size--;
    

    public void deleteNodeByGivenData(int data) 
        if (start == null) 
            System.out.println("Empty!");
            return;
        

        if (start.getData() == data && start.getLink() == null) 
            start = null;
            end = null;
            size--;
            return;
        

        if (start.getData() == data && start.getLink() != null) 
            start = start.getLink();
            size--;
            return;
        

        if (end.getData() == data) 
            Node startPtr = start;
            Node endPtr = start;

            startPtr = startPtr.getLink();
            while (startPtr.getLink() != null) 
                endPtr = startPtr;
                startPtr = startPtr.getLink();
            
            end = endPtr;
            end.setLink(null);
            size--;
            return;
        

        Node startPtr = start;
        Node prevLink = startPtr;
        startPtr = startPtr.getLink();
        while (startPtr.getData() != data && startPtr.getLink() != null) 
            prevLink = startPtr;
            startPtr = startPtr.getLink();
        
        if (startPtr.getData() == data) 
            Node temp = prevLink.getLink();
            temp = temp.getLink();
            prevLink.setLink(temp);
            size--;
            return;
        

        System.out.println(data + " not found!");
    

    public void disply() 
        if (start == null) 
            System.out.println("Empty!");
            return;
        

        if (start.getLink() == null) 
            System.out.println(start.getData());
            return;
        

        Node ptr = start;
        System.out.print(ptr.getData() + "->");
        ptr = start.getLink();
        while (ptr.getLink() != null) 
            System.out.print(ptr.getData() + "->");
            ptr = ptr.getLink();
        
        System.out.println(ptr.getData() + "\n");
    

    public void searchElementByPosition(int position) 
        if (position == 1) 
            System.out.println("Element at " + position + " is : " + start.getData());
            return;
        

        if (position == size) 
            System.out.println("Element at " + position + " is : " + end.getData());
            return;
        

        Node ptr = start;
        for (int i = 1; i < size; i++) 
            if (i == position) 
                System.out.println("Element at " + position + " is : " + ptr.getData());
                break;
            
            ptr = ptr.getLink();
        
    

    public void searchElementIteratively(int data) 

        if (isEmpty()) 
            System.out.println("Empty!");
            return;
        

        if (start.getData() == data) 
            System.out.println(data + " found at " + 1 + " position");
            return;
        

        if (start.getLink() != null && end.getData() == data) 
            System.out.println(data + " found at " + size + " position");
            return;
        

        Node startPtr = start;
        int position = 0;
        while (startPtr.getLink() != null) 
            ++position;
            if (startPtr.getData() == data) 
                break;
            
            startPtr = startPtr.getLink();
        
        if (startPtr.getData() == data) 
            System.out.println(data + " found at " + position);
            return;
        

        System.out.println(data + " No found!");
    

    public void searchElementRecursively(Node start, int data, int count) 

        if (isEmpty()) 
            System.out.println("Empty!");
            return;
        
        if (start.getData() == data) 
            System.out.println(data + " found at " + (++count));
            return;
        
        if (start.getLink() == null) 
            System.out.println(data + " not found!");
            return;
        
        searchElementRecursively(start.getLink(), data, ++count);
    

    public int getSize() 
        return size;
    

    public boolean isEmpty() 
        return start == null;
    


public class SinglyLinkedList 

    @SuppressWarnings("resource")
    public static void main(String[] args) 
        SinglyLinkedListImpl listImpl = new SinglyLinkedListImpl();
        System.out.println("Singly Linked list : ");
        boolean yes = true;
        do 
            System.out.println("1 Insert At Start :");
            System.out.println("2 Insert At End :");
            System.out.println("3 Insert At any Position :");
            System.out.println("4 Delete At any Position :");
            System.out.println("5 Display :");
            System.out.println("6 Get Size");
            System.out.println("7 Empty Status");
            System.out.println("8 Replace data at given postion");
            System.out.println("9 Search Element by position ");
            System.out.println("10 Delete a Node by Given Data");
            System.out.println("11 Search Element Iteratively");
            System.out.println("12 Search Element Recursively");
            System.out.println("13 Exit :");
            Scanner scanner = new Scanner(System.in);
            int choice = scanner.nextInt();
            switch (choice) 
            case 1:
                listImpl.insertAtStart(scanner.nextInt());
                break;

            case 2:
                listImpl.insertAtEnd(scanner.nextInt());
                break;

            case 3:
                int position = scanner.nextInt();
                if (position <= 1 || position > listImpl.getSize()) 
                    System.out.println("invalid position!");
                 else 
                    listImpl.insertAtPosition(position, scanner.nextInt());
                
                break;

            case 4:
                int deletePosition = scanner.nextInt();
                if (deletePosition <= 1 || deletePosition > listImpl.getSize()) 
                    System.out.println("invalid position!");
                 else 
                    listImpl.deleteAtPosition(deletePosition);
                
                break;

            case 5:
                listImpl.disply();
                break;

            case 6:
                System.out.println(listImpl.getSize());
                break;

            case 7:
                System.out.println(listImpl.isEmpty());
                break;

            case 8:
                int replacePosition = scanner.nextInt();
                if (replacePosition < 1 || replacePosition > listImpl.getSize()) 
                    System.out.println("Invalid position!");
                 else 
                    listImpl.repleaceDataAtPosition(replacePosition, scanner.nextInt());
                
                break;

            case 9:
                int searchPosition = scanner.nextInt();
                if (searchPosition < 1 || searchPosition > listImpl.getSize()) 
                    System.out.println("Invalid position!");
                 else 
                    listImpl.searchElementByPosition(searchPosition);
                
                break;

            case 10:
                listImpl.deleteNodeByGivenData(scanner.nextInt());
                break;

            case 11:
                listImpl.searchElementIteratively(scanner.nextInt());
                break;

            case 12:
                listImpl.searchElementRecursively(listImpl.start, scanner.nextInt(), 0);
                break;

            default:
                System.out.println("invalid choice");
                break;
            
         while (yes);
    

它会帮助你在链表中。

【讨论】:

这是一个非常好的实现,但我认为在节点类的参数化构造函数中,您应该设置this.link = link; 这里是从头开始实现二叉搜索树的链接:***.com/questions/2052563/…【参考方案4】:

提示1:阅读http://en.wikipedia.org/wiki/Linked_list链接列表的描述

提示 2:LinkedList 的 Java 实现是一个双向链表。你的是一个单链表。算法不直接适用。


还有:

...但是从头开始创建[链表类]毫无意义。

这取决于所需的工作成果是什么。如果目标是生成满足某些功能/非功能要求的代码,那么您是对的。如果真正的目标是让您学习如何编程/设计 API/实现非平凡的数据结构,那么最终产品的实用性几乎完全无关紧要。

因此神奇地我们有一个链表

您实际上拥有的是一种开放数据类型,可用于构建(某种)列表。但这不是你的老师想要的。它当然不会被认为是一个有用的列表抽象。一个有用的抽象包括:

程序员不想一遍又一遍地重复的事情的方法,以及

阻止程序员“破坏”列表的抽象层;例如不小心创建了一个循环,或者不小心将两个列表中的一个子列表拼接成一个倒排树。

【讨论】:

【参考方案5】:

演示Java中的Insert Front、Delete Front、Insert Rear和Delete Rear操作的链表:

import java.io.DataInputStream;
import java.io.IOException;


public class LinkedListTest 

public static void main(String[] args) 
    // TODO Auto-generated method stub      
    Node root = null;

    DataInputStream reader = new DataInputStream(System.in);        
    int op = 0;
    while(op != 6)

        try 
            System.out.println("Enter Option:\n1:Insert Front 2:Delete Front 3:Insert Rear 4:Delete Rear 5:Display List 6:Exit");
            //op = reader.nextInt();
            op = Integer.parseInt(reader.readLine());
            switch (op) 
            case 1:
                System.out.println("Enter Value: ");
                int val = Integer.parseInt(reader.readLine());
                root = insertNodeFront(val,root);
                display(root);
                break;
            case 2:
                root=removeNodeFront(root);
                display(root);
                break;
            case 3:
                System.out.println("Enter Value: ");
                val = Integer.parseInt(reader.readLine());
                root = insertNodeRear(val,root);
                display(root);
                break;
            case 4:
                root=removeNodeRear(root);
                display(root);
                break;
            case 5:
                display(root);
                break;
            default:
                System.out.println("Invalid Option");
                break;
            
         catch (Exception e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    
    System.out.println("Exited!!!");
    try 
        reader.close();
     catch (IOException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
           


static Node insertNodeFront(int value, Node root)  
    Node temp = new Node(value);
    if(root==null)
        return temp; // as root or first
    
    else
    
        temp.next = root;
        return temp;
                   


static Node removeNodeFront(Node root)
    if(root==null)
        System.out.println("List is Empty");
        return null;
    
    if(root.next==null)
        return null; // remove root itself
    
    else
    
        root=root.next;// make next node as root
        return root;
                   


static Node insertNodeRear(int value, Node root)   
    Node temp = new Node(value);
    Node cur = root;
    if(root==null)
        return temp; // as root or first
    
    else
    
        while(cur.next!=null)
        
            cur = cur.next;
        
        cur.next = temp;
        return root;
                   


static Node removeNodeRear(Node root)
    if(root==null)
        System.out.println("List is Empty");
        return null;
    
    Node cur = root;
    Node prev = null;
    if(root.next==null)
        return null; // remove root itself
    
    else
    
        while(cur.next!=null)
        
            prev = cur;
            cur = cur.next;
        
        prev.next=null;// remove last node
        return root;
                   


static void display(Node root)
    System.out.println("Current List:");
    if(root==null)
        System.out.println("List is Empty");
        return;
    
    while (root!=null)
        System.out.print(root.val+"->");
        root=root.next;
    
    System.out.println();


static class Node
    int val;
    Node next;
    public Node(int value) 
        // TODO Auto-generated constructor stub
        val = value;
        next = null;
    


【讨论】:

【参考方案6】:

请阅读这篇文章:How To Implement a LinkedList Class From Scratch In Java

package com.crunchify.tutorials;

/**
 * @author Crunchify.com
 */

public class CrunchifyLinkedListTest 

    public static void main(String[] args) 
        CrunchifyLinkedList lList = new CrunchifyLinkedList();

        // add elements to LinkedList
        lList.add("1");
        lList.add("2");
        lList.add("3");
        lList.add("4");
        lList.add("5");

        /*
         * Please note that primitive values can not be added into LinkedList
         * directly. They must be converted to their corresponding wrapper
         * class.
         */

        System.out.println("lList - print linkedlist: " + lList);
        System.out.println("lList.size() - print linkedlist size: " + lList.size());
        System.out.println("lList.get(3) - get 3rd element: " + lList.get(3));
        System.out.println("lList.remove(2) - remove 2nd element: " + lList.remove(2));
        System.out.println("lList.get(3) - get 3rd element: " + lList.get(3));
        System.out.println("lList.size() - print linkedlist size: " + lList.size());
        System.out.println("lList - print linkedlist: " + lList);
    


class CrunchifyLinkedList 
    // reference to the head node.
    private Node head;
    private int listCount;

    // LinkedList constructor
    public CrunchifyLinkedList() 
        // this is an empty list, so the reference to the head node
        // is set to a new node with no data
        head = new Node(null);
        listCount = 0;
    

    public void add(Object data)
    // appends the specified element to the end of this list.
    
        Node crunchifyTemp = new Node(data);
        Node crunchifyCurrent = head;
        // starting at the head node, crawl to the end of the list
        while (crunchifyCurrent.getNext() != null) 
            crunchifyCurrent = crunchifyCurrent.getNext();
        
        // the last node's "next" reference set to our new node
        crunchifyCurrent.setNext(crunchifyTemp);
        listCount++;// increment the number of elements variable
    

    public void add(Object data, int index)
    // inserts the specified element at the specified position in this list
    
        Node crunchifyTemp = new Node(data);
        Node crunchifyCurrent = head;
        // crawl to the requested index or the last element in the list,
        // whichever comes first
        for (int i = 1; i < index && crunchifyCurrent.getNext() != null; i++) 
            crunchifyCurrent = crunchifyCurrent.getNext();
        
        // set the new node's next-node reference to this node's next-node
        // reference
        crunchifyTemp.setNext(crunchifyCurrent.getNext());
        // now set this node's next-node reference to the new node
        crunchifyCurrent.setNext(crunchifyTemp);
        listCount++;// increment the number of elements variable
    

    public Object get(int index)
    // returns the element at the specified position in this list.
    
        // index must be 1 or higher
        if (index <= 0)
            return null;

        Node crunchifyCurrent = head.getNext();
        for (int i = 1; i < index; i++) 
            if (crunchifyCurrent.getNext() == null)
                return null;

            crunchifyCurrent = crunchifyCurrent.getNext();
        
        return crunchifyCurrent.getData();
    

    public boolean remove(int index)
    // removes the element at the specified position in this list.
    
        // if the index is out of range, exit
        if (index < 1 || index > size())
            return false;

        Node crunchifyCurrent = head;
        for (int i = 1; i < index; i++) 
            if (crunchifyCurrent.getNext() == null)
                return false;

            crunchifyCurrent = crunchifyCurrent.getNext();
        
        crunchifyCurrent.setNext(crunchifyCurrent.getNext().getNext());
        listCount--; // decrement the number of elements variable
        return true;
    

    public int size()
    // returns the number of elements in this list.
    
        return listCount;
    

    public String toString() 
        Node crunchifyCurrent = head.getNext();
        String output = "";
        while (crunchifyCurrent != null) 
            output += "[" + crunchifyCurrent.getData().toString() + "]";
            crunchifyCurrent = crunchifyCurrent.getNext();
        
        return output;
    

    private class Node 
        // reference to the next node in the chain,
        // or null if there isn't one.
        Node next;
        // data carried by this node.
        // could be of any type you need.
        Object data;

        // Node constructor
        public Node(Object dataValue) 
            next = null;
            data = dataValue;
        

        // another Node constructor if we want to
        // specify the node to point to.
        public Node(Object dataValue, Node nextValue) 
            next = nextValue;
            data = dataValue;
        

        // these methods should be self-explanatory
        public Object getData() 
            return data;
        

        public void setData(Object dataValue) 
            data = dataValue;
        

        public Node getNext() 
            return next;
        

        public void setNext(Node nextValue) 
            next = nextValue;
        
    

输出

lList - print linkedlist: [1][2][3][4][5]
lList.size() - print linkedlist size: 5
lList.get(3) - get 3rd element: 3
lList.remove(2) - remove 2nd element: true
lList.get(3) - get 3rd element: 4
lList.size() - print linkedlist size: 4
lList - print linkedlist: [1][3][4][5]

【讨论】:

【参考方案7】:

非递归链表的全功能实现怎么样?

我为我的算法创建了这个作为垫脚石,以便在开始为作业编写双向链接队列类之前获得更好的理解。

代码如下:

import java.util.Iterator;
import java.util.NoSuchElementException;

public class LinkedList<T> implements Iterable<T> 
    private Node first;
    private Node last;
    private int N;

    public LinkedList() 
        first = null;
        last = null;
        N = 0;
    

    public void add(T item) 
        if (item == null)  throw new NullPointerException("The first argument for addLast() is null."); 
        if (!isEmpty()) 
            Node prev = last;
            last = new Node(item, null);
            prev.next = last;
        
        else 
            last = new Node(item, null);
            first = last;
        
        N++;
    

    public boolean remove(T item) 
        if (isEmpty())  throw new IllegalStateException("Cannot remove() from and empty list."); 
        boolean result = false;
        Node prev = first;
        Node curr = first;
        while (curr.next != null || curr == last) 
            if (curr.data.equals(item)) 
                // remove the last remaining element
                if (N == 1)  first = null; last = null; 
                // remove first element
                else if (curr.equals(first))  first = first.next; 
                // remove last element
                else if (curr.equals(last))  last = prev; last.next = null; 
                // remove element
                else  prev.next = curr.next; 
                N--;
                result = true;
                break;
            
            prev = curr;
            curr = prev.next;
        
        return result;
    

    public int size() 
        return N;
    

    public boolean isEmpty() 
        return N == 0;
    

    private class Node 
        private T data;
        private Node next;

        public Node(T data, Node next) 
            this.data = data;
            this.next = next;
        
    

    public Iterator<T> iterator()  return new LinkedListIterator(); 

    private class LinkedListIterator implements Iterator<T> 
        private Node current = first;

        public T next() 
            if (!hasNext())  throw new NoSuchElementException(); 
            T item = current.data;
            current = current.next;
            return item;
        

        public boolean hasNext()  return current != null; 

        public void remove()  throw new UnsupportedOperationException(); 
    

    @Override public String toString() 
        StringBuilder s = new StringBuilder();
        for (T item : this)
            s.append(item + " ");
        return s.toString();
    

    public static void main(String[] args) 
        LinkedList<String> list = new LinkedList<>();
        while(!StdIn.isEmpty()) 
            String input = StdIn.readString();
            if (input.equals("print"))  StdOut.println(list.toString()); continue; 
            if (input.charAt(0) == ('+'))  list.add(input.substring(1)); continue; 
            if (input.charAt(0) == ('-'))  list.remove(input.substring(1)); continue; 
            break;
        
    

注意:这是一个非常基本的单链表实现。 'T' 类型是泛型类型占位符。基本上,这个链表应该适用于任何继承自 Object 的类型。如果将其用于原始类型,请务必使用可为空的类等价物(例如,'int' 类型的'Integer')。 'last' 变量实际上并不是必需的,只是它将插入时间缩短到 O(1) 时间。删除速度很慢,因为它们在 O(N) 时间内运行,但它允许您删除列表中第一次出现的值。

如果你愿意,你也可以考虑实施:

addFirst() - 将新项目添加到 LinkedList 的开头 removeFirst() - 从 LinkedList 中删除第一项 removeLast() - 从 LinkedList 中删除最后一项 addAll() - 将项目列表/数组添加到 LinkedList removeAll() - 从 LinkedList 中删除项目列表/数组 contains() - 检查 LinkedList 是否包含项目 contains() - 清除 LinkedList 中的所有项目

老实说,只需要几行代码就可以使它成为一个双向链表。这与双向链表的主要区别在于,双向链表的 Node 实例需要一个额外的引用,该引用指向列表中的前一个元素。

与递归实现相比,这样做的好处是速度更快,并且您不必担心在遍历大型列表时会溢出堆栈。

有 3 个命令可以在调试器/控制台中对此进行测试:

以“+”作为前缀会将其添加到列表中。 使用“-”作为前缀将从列表中删除第一个匹配项。 键入“print”将打印出列表,其中的值由空格分隔。

如果您从未见过其中一种工作原理的内部结构,我建议您在调试器中逐步完成以下操作:

add() - 如果列表为空,则在末尾添加一个新节点或初始化第一个/最后一个值 remove() - 从头到尾遍历列表。如果找到匹配项,它将删除该项目并连接链中前一个和下一个链接之间的断开链接。当没有上一个或下一个链接时,会添加特殊例外。 toString() - 使用 foreach 迭代器简单地从头到尾遍历列表链。

虽然对于数组列表等列表有更好、更有效的方法,但了解应用程序如何通过引用/指针遍历对于了解有多少更高级别的数据结构起作用是不可或缺的。

【讨论】:

【参考方案8】:
class Node

  int data;
     Node link;

     public Node()
     
         data=0;
         link=null;
        

     Node ptr,start,temp;

    void create()throws  IOException
     
         int n;
         BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
         System.out.println("Enter first data");
         this.data=Integer.parseInt(br.readLine());
         ptr=this;
         start=ptr;
         char ins ='y';
         do
         
             System.out.println("Wanna Insert another node???");
             ins=(char)br.read();
             br.read();
             if(ins=='y')
             
                 temp=new Node();
                 System.out.println("Enter next data");
                 temp.data=Integer.parseInt(br.readLine());
                 temp.link=null;
                 ptr.link=temp;
                 temp=null;
                 ptr=ptr.link;
                
            while(ins=='y');
        

public static void main(String args[])throws IOException
     
       Node first= new Node();
       first.create();


【讨论】:

【参考方案9】:

你编码的不是LinkedList,至少不是我认识的。对于这个作业,您要创建两个类:

LinkNode
LinkedList

LinkNode 有一个成员字段用于其包含的数据,LinkNodeLinkedList 中的下一个LinkNode 的引用。是的,它是一个自引用数据结构。 LinkedList 只是有一个特殊的 LinkNode 引用,它引用列表中的第一项。

当您在LinkedList 中添加一个项目时,您会遍历所有LinkNode's,直到到达最后一个。这个LinkNode's next 应该为空。然后在此处构造一个新的LinkNode,设置它的值,并将其添加到LinkedList

public class LinkNode  

    String data;
    LinkNode next;

    public LinkNode(String item)  

       data = item;

    



public class LinkedList  

    LinkNode head;

    public LinkedList(String item)  

       head = new LinkNode(item);

    

    public void add(String item)  

       //pseudo code: while next isn't null, walk the list
       //once you reach the end, create a new LinkNode and add the item to it.  Then
       //set the last LinkNode's next to this new LinkNode

    



【讨论】:

【参考方案10】:

当然,对于 n00bs 编程来说,Linked List 有点令人困惑,很容易将其视为俄罗斯娃娃,因为它看起来就是 LinkedList 对象中的 LinkedList 对象。但这有点难以想象,不如把它当作一台电脑来看待。

LinkedList = 数据 + 下一个成员

如果 next 为 NULL,则它是列表的最后一个成员

所以一个有 5 个成员的 LinkedList 将是:

LinkedList(Data1, LinkedList(Data2, LinkedList(Data3, LinkedList(Data4, LinkedList(Data5, NULL)))))

但你可以简单地认为它:

Data1 -> Data2 -> Data3 -> Data4 -> Data5 -> NULL

那么,我们如何找到这个结局呢?好吧,我们知道 NULL 是结束所以:

public void append(LinkedList myNextNode) 
  LinkedList current = this; //Make a variable to store a pointer to this LinkedList
  while (current.next != NULL)  //While we're not at the last node of the LinkedList
    current = current.next; //Go further down the rabbit hole.
  
  current.next = myNextNode; //Now we're at the end, so simply replace the NULL with another Linked List!
  return; //and we're done!

这当然是非常简单的代码,如果你给它一个循环链表,它无限循环!但这是基础。

【讨论】:

【参考方案11】:

我是如何创建这样的链表的。这是如何工作的? 这就是一个链表。带有指向列表中下一项的链接的项。只要您在列表的开头保留对项目的引用,就可以使用对下一个值的每个后续引用来遍历整个事物。

要追加,您需要做的就是找到列表的末尾,并将下一项设置为您想要追加的值,因此如果下一项非空,您必须在下一项上调用 append 直到你找到了列表的结尾。

this.next.Append(word);

【讨论】:

等等..什么?所以我会设置 next=word?如何使最后一项等于我的单词项?这让我很困惑。这是怎么规定的? 不,您会发现最后一项定义为next == null 所在的位置,并在该对象上设置next = new LinkedList(word, null); 哦,好吧,我明白了。但是在创建追加方法的方法的描述下,它说“递归地找到最后一个条目,然后在末尾添加一个新链接”。当我可以说if (next==null)时,为什么我需要递归查找它? 因为如果它不为空,那么你调用 next.Append(word); 这是一个递归调用(从 Append 调用 Append)。 但是在 next 上调用 append 是如何工作的呢?下一步是什么? next 是一个 LinkedList 对象,所以 next,当使用构造函数创建时,有一个 String 和一个 LinkedList 对象。那么接下来是一个链表吗?所以如果我在 next 上调用 append,它会检查 this.next,这意味着它检查 next.next?我说得通吗?

以上是关于从头开始创建 LinkedList 类的主要内容,如果未能解决你的问题,请参考以下文章

18 linkedList

源码详解数据结构Linked List

Reverse Linked List(反转单向链表)

LeetCode 234. Palindrome Linked List (回文链表)

自定义的Node类和集合类linkedList<Item>的区别?

linked-list-cycle-ii——链表,找出开始循环节点