链表
1. 简介
所谓链表,通俗的说就是用一条链把数据都串起来
前面我们提到的数组、栈和队列都是顺序存储结构,这里的链表属于链式存储结构
什么是链表呢,我们直接上图
我们可以看到:每个链表结点至少包含两个元素:数据data、地址next(指向下一个数据)
分类: 最基础的链表就是单链表,在单链表的基础上有循环链表、双向链表、双向循环链表。 下面会分别进行介绍和实现。
2. 单链表
你猜的没错,前面我们看到的链表图,其实就是单链表。 单链表除了最后一个结点以外,其他结点都由数据data和t指向下一结点的nex组成 而最后一个结点的next为null
常见操作(方法): getData()—获取当前结点数据 next()—返回下一个结点 append()—结点追加-追加在链表最后 insertAfter()—结点插入 removeNode()—结点移除 show()—输出当前链表 isLast()—判断是否是最后一个结点
代码:
public class Node {
private int data;
private Node next;
public Node(int data){
this.data=data;
}
public int getData(){
return this.data;
}
public Node append(Node node){
Node currentNode=this;
while(true){
if(currentNode.next==null){
currentNode.next=node;
break;
}
currentNode=currentNode.next;
}
return this;
}
public Node next(){
return this.next;
}
public Boolean isLast(){
return this.next==null;
}
public void show(){
Node CurrentNode=this;
while (true){
System.out.print(CurrentNode.data);
if(CurrentNode.next==null){
System.out.println();
break;
}else{
System.out.print("->");
CurrentNode=CurrentNode.next;
}
}
}
public void removeNode(){
this.next=this.next.next;
}
public void insetAfter(Node node){
Node nextNode=this.next;
this.next=node;
node.next=nextNode;
}
}
测试类
public class TestNode {
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
node1.append(node2).append(node3).append(node4);
System.out.println(node1.next().next().getData());
node1.show();
node1.removeNode();
node1.show();
node1.insetAfter(new Node(100));
node3.insetAfter(new Node(200));
node1.show();
}
}
结果:
3
1->2->3->4
1->3->4
1->100->3->200->4
3. 循环链表
循环链表就是将单链表最后一个结点指向第一个结点,这样让整个链表形成一个循环 循环链表由于没有尾结点,所以不能append结点
注意:循环链表只能插入结点,删除结点
在单链表基础上,我们将结点中的next初始化为this,也就是指向当前结点自己,就变成了循环链表,话不多说,下面直接上代码。
代码:
public class LoopNode {
private int data;
private LoopNode next=this;
public LoopNode(int data){
this.data=data;
}
public int getData(){
return this.data;
}
public LoopNode next(){
return this.next;
}
public void removeNode(){
this.next=this.next.next;
}
public void insetAfter(LoopNode node){
LoopNode nextNode=this.next;
this.next=node;
node.next=nextNode;
}
}
测试类:
public class TestLoopNode {
public static void main(String[] args) {
LoopNode loopNode1 = new LoopNode(1);
LoopNode loopNode2 = new LoopNode(2);
LoopNode loopNode3 = new LoopNode(3);
loopNode1.insetAfter(loopNode2);
loopNode2.insetAfter(loopNode3);
System.out.println(loopNode1.next().getData());
System.out.println(loopNode2.next().getData());
System.out.println(loopNode3.next().getData());
}
}
运行结果
2
3
1
4. 双向循环链表
双向循环链表:顾名思义就是每一个结点都可以访问其前后两个结点,并且是循环链表 特点:每一个结点都有pre和next分别指向相邻结点 特别的:第一个结点的pre指向最后一个结点,而最后一个结点的next指向第一个结点
每一个结点都可以访问到其前后两个结点所我们需要增加一个pre指向上一个结点 同时插入操作相比于单链表较为复杂,需要修改四个指向,见代码
代码:
public class DoubleNode {
private int data;
private DoubleNode pre=this;
private DoubleNode next=this;
public DoubleNode(int data){
this.data=data;
}
public DoubleNode pre(){
return this.pre;
}
public DoubleNode next(){
return this.next;
}
public int getData(){
return this.data;
}
public void insertAfter(DoubleNode doubleNode){
DoubleNode nextDoubleNode=this.next;
this.next=doubleNode;
doubleNode.pre=this;
doubleNode.next=nextDoubleNode;
nextDoubleNode.pre=doubleNode;
}
}
测试类:
public class TestDoubleNode {
public static void main(String[] args) {
DoubleNode doubleNode1 = new DoubleNode(1);
DoubleNode doubleNode2 = new DoubleNode(2);
DoubleNode doubleNode3 = new DoubleNode(3);
doubleNode1.insertAfter(doubleNode2);
doubleNode2.insertAfter(doubleNode3);
System.out.println(doubleNode1.pre().getData());
System.out.println(doubleNode1.next().getData());
System.out.println(doubleNode2.pre().getData());
System.out.println(doubleNode2.next().getData());
System.out.println(doubleNode3.pre().getData());
System.out.println(doubleNode3.next().getData());
}
}
结果:
3
2
1
3
2
1
|