链表由多个节点对象组成,通过第一个节点对象去查找其他的节点
数据存储在节点中
节点的结构:
1
:存储数据的变量
2
:存储下一个节点的变量
3
:设计一些存储其他信息的内容
接下来用一个简单的项目让大家理解一下链表
public class Node {
Object value;//数据变量
Node next;//下一个节点的引用地址
public Node(Object value, Node next){
this.value = value;
this.next = next;
}
public static void main(String[] args){
// 创建节点
Node node1 = new Node ("医生”, null);
Node node2 = new Node ("预言家”, null);
Node node3 = new Node ("狼人”, null);
Node node4 = new Node ("巫师”, null);
Node node5 = new Node ("平民”, null);
Node node6 = new Node ("猎人", null);
Node node7 = new Node ("射手", null);
// 连接节点
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
node6.next = node7;
// 打印链表
Node temp = node1;
while(temp != null){
System.out.print (temp.value + ",");
temp = temp.next;// 将下一个节点取出来 继续循环判断
}
System.out.println ();
// 查找节点 - 查找平民的前一个 与 后一个是谁
String name = "平民";
Node temp1 = node1;
while(temp1 != null){
if(temp1.value.equals (name)){
System.out.println ("查找到了平民");
break;
}
temp1 = temp1.next;// 将下一个节点取出来 继续循环判断
}
System.out.println (temp1.value);
// 删除节点
// 删除最后一个
Node temp2 = node1;
while(temp2 != null){
if(temp2.next.next == null){// 证明temp2是倒数第二个节点
temp2.next = null;
System.out.println ("已经删除最后一个");
}
temp2 = temp2.next;
}
// 打印链表
temp = node1;
while(temp != null){
System.out.print (temp.value + ",");
temp = temp.next; //将下一个节点取出来 继续循环判断
}
System.out.println ();
}
}
运行结果如下
接下来我们进行更深一步的代码
public class MyLinkedList
{
// 头节点
Node head;
Node last;
// 节点数量
int size;
// 通过头节点向下一个个查找 找到最后一个添加数据
// 耗时比较久
public void add(Object e) {
// 将e数据包装成一个节点对象
Node node = new Node(e, null);
// 判断头节点是否为null
if (head == null) {
// 将node赋给 head 作为头节点
head = node;
// size 增加
size++;
return;
}
// 遍历链表的过程
Node temp = head;// 头节点必定不为null
while (temp.next != null) {
// 迭代替换temp节点 知道最后一个节点 (特征 这个节点的下一个为null)
temp = temp.next;
}
// 循环结束 temp 就是最后一个节点
// 将node存储到temp的下一个
temp.next = node;
size++;
}
}
这部分知识理解比较抽象 这个是我的图解理解
temp作为一个临时容器先从头节点 head开始遍历
head因为在第一次被赋值了node的地址所以head.next不为空 然后再迭代替换查找地址 直到对应指向node里的null 便是最后一个节点
但是这个方法由于要从第一个节点开始遍历 所以耗时会长很多 接下来介绍一下尾插法
public void addLast(Object e) {
Node node = new Node(e, null);
if (head == null) {
head = node;
last = node;
size++;
return;
}
// 直接将新节点存入到last的下一个
last.next = node;
// 替换最后一个节点为新的尾节点
last = last.next;
size++;
}
尾插法 即head不变 通过迭代替换最新的last尾象来完成遍历
下面是移除以及打印的代码
public void remove(Object e) {
if (e == null) {
return;
}
// 查找存储e元素的节点是否存在
if (head.value.equals(e)) {
// 更新头节点
head = head.next;
size--;
return;
}
Node temp = head;// 头节点必定不为null
while (temp.next != null) {
// 迭代替换temp节点 知道最后一个节点 (特征 这个节点的下一个为null)
if (temp.next.value.equals(e)) {
//目标节点是 temp.next
// 将 temp.next.next 取出来存入temp.next中
temp.next = temp.next.next;
size--;
return;
}
temp = temp.next;
}
}
public void printLink() {
String str = "{";
Node temp = head;// 头节点必定不为null
while (temp.next != null) {
str += "[" + temp.value + "],";
temp = temp.next;
}
// 添加尾节点
str += "[" + temp.value + "]}";
System.out.println(str);
}
public static void main(String[] args) {
MyLinkedList myLink = new MyLinkedList();
for (int i = 0; i < 10; i++) {
myLink.addLast("hello" + i);
}
myLink.printLink();
myLink.remove("hello5");
myLink.remove("hello9");
myLink.remove("hello0");
myLink.remove("hello1");
myLink.printLink();
}
}
以及运行结果
太晚了 早点睡吧