知识拓展:面向对象的可重用链表
顺序表必须占用一整块事先分配大小的存储空间,这样会使存储空间的利用率降低,为此链表的概念应运而生,它是线性表的链式存储结构,可以实现存储空间的动态管理。
一、单链表
线性表的链式存储结构—链表。链式存储结构可以实现存储空间动态管理。
class Node{
int data;
Node next;
public Node(int data){
this.data=data;
}
//增加节点
public Node append(Node n){
//保存当前节点
Node currentNode = this;
//找到当前节点的最后一个节点
while(currentNode.next!=null){
currentNode = currentNode.next;
}
currentNode.next=n;
return this;
}
//删除下一个节点
public void removeNextNode(){
//取出当前节点的下下一个节点
Node newNode = this.next.next;
this.next=newNode;
}
//插入一个节点
public void insertNode(Node inNode){
//将当前节点的下一个节点存起来,作为下下一个节点
Node nextNextNode = this.next;
//将要插入节点添加到当前节点后面
this.next=inNode;
//将下下一个节点作为新节点的下一个节点
inNode.next=nextNextNode;
}
//获取下一个节点
public Node getNext(){
return this.next;
}
//获取下一个节点的值
public int getData(){
return this.data;
}
//判断当前节点是否为最后一个节点
public boolean isLast(){
return next==null;
}
//显示所有节点内容
public void show(){
Node newNode = this;
while(newNode!=null){
System.out.print(newNode.data+"\t");
newNode = newNode.next;
}
System.out.println();
}
}
public class NodeTest {
public static void main(String[] args) {
Node n1 = new Node(4);
Node n2 = new Node(5);
Node n3 = new Node(6);
Node n4 = new Node(7);
//节点追加
n1.append(n2).append(n3).append(n4);
//获取节点
System.out.print(n1.getNext().getData()+"\t");
System.out.print(n2.getNext().getData()+"\t");
System.out.println(n3.getNext().getData()+"\t");
System.out.println("------------------------");
//判断当前节点的下一个节点是否为空
System.out.print(n1.isLast()+"\t");
System.out.print(n2.isLast()+"\t");
System.out.print(n3.isLast()+"\t");
System.out.println(n4.isLast()+"\t");
System.out.println("------------------------");
n1.show();
System.out.println("------------------------");
n1.removeNextNode();
n1.show();
System.out.println("------------------------");
n1.insertNode(n2);
n1.show();
}
}
二、循环链表
循环链表是在单链表的基础上,让尾结点的下一个节点指向头结点,从而实现循环链表。
//循环链表
class LoopNode {
int data;
LoopNode next = this;
public LoopNode(int data){
this.data = data;
}
//删除下一个节点
public void removeNextNode(){
//取出当前节点的下下一个节点
LoopNode newNode = this.next.next;
this.next=newNode;
}
//插入一个节点
public void insertNode(LoopNode inNode){
//将当前节点的下一个节点存起来,作为下下一个节点
LoopNode nextNextNode = this.next;
//将要插入节点添加到当前节点后面
this.next=inNode;
//将下下一个节点作为新节点的下一个节点
inNode.next=nextNextNode;
}
//获取下一个节点
public LoopNode getNext(){
return this.next;
}
//获取下一个节点的值
public int getData(){
return this.data;
}
//显示所有节点内容
public void show(){
LoopNode newNode = this;
while(newNode!=null){
System.out.print(newNode.data+"\t");
newNode = newNode.next;
}
System.out.println();
}
}
public class LoopNodeTest {
public static void main(String[] args) {
LoopNode l1 = new LoopNode(5);
LoopNode l2 = new LoopNode(6);
LoopNode l3 = new LoopNode(7);
LoopNode l4 = new LoopNode(8);
//增加节点
l1.insertNode(l2);
l2.insertNode(l3);
l3.insertNode(l4);
//显示当前节点的下一个节点的值
System.out.println(l1.getNext().getData());
System.out.println(l2.getNext().getData());
System.out.println(l3.getNext().getData());
System.out.println(l4.getNext().getData());
}
}
三、循环双链表
在双链表中,每个节点包含一个前驱节点和一个后继节点,还有其节点元素值。循环双链表则是让头结点的前驱节点指向尾结点,尾结点的后继节点指向头节点。
//循环双链表
class DoubleNode {
//当前节点的上一个节点
DoubleNode pre = this;
//当前节点的下一个节点
DoubleNode next = this;
int data;
public DoubleNode(int data){
this.data = data;
}
//插入节点
public void insert(DoubleNode node){
//当前节点原来的下一个节点
DoubleNode nextNode =this.next;
//当前节点的下一节点指向插入节点
this.next=node;
//插入节点的上一个节点指向当前节点
node.pre=this;
//插入节点的下一个节点指向当前节点原来的下一个节点
node.next=nextNode;
//当前节点原来下一个节点的上一个节点指向插入节点
nextNode.pre=node;
}
//获取下一个节点
public DoubleNode getNext(){
return this.next;
}
//获取上一个节点
public DoubleNode getPre() {
return this.pre;
}
//获取节点数据
public int getData() {
return this.data;
}
}
public class DoubleNodeTest {
public static void main(String[] args) {
DoubleNode d1 = new DoubleNode(1);
DoubleNode d2 = new DoubleNode(2);
DoubleNode d3 = new DoubleNode(3);
// System.out.println(d1.data);
// System.out.println(d1.getNext().data);
// System.out.println(d1.getPre().data);
//添加节点
d1.insert(d2);
d2.insert(d3);
//查看节点
System.out.println(d2.getPre().getData()); //d2的上一个节点,1
System.out.println(d2.getNext().getData()); //d2的下一个节点,3
System.out.println(d3.getNext().getData()); //d3的下一个节点,1
System.out.println(d1.getPre().getData()); //d1的上一个节点,3
}
}