从头开始创建 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-next
的append
方法中。所以我们现在称之为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
有一个成员字段用于其包含的数据,LinkNode
对LinkedList
中的下一个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 类的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 234. Palindrome Linked List (回文链表)