链表介绍
链表优劣势:插入和删除速度快,查询速度慢
链表分类:
单向链表:只有头结点,每个节点可以指向下一个节点
双向链表:有头结点和尾结点,每个节点不仅可以指向下一个节点,还可以指向上一个节点
单向链表
1、node节点
package com.springboot.demo.linked;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 节点
*
* @author supu
* @create 2018-05-11 16:59
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Node<T> {
/**
* 数据
*/
private T data;
/**
* 指针
*/
private Node next;
public Node(T data) {
this.data = data;
}
}
2、单向链表
package com.springboot.demo.linked;
/**
* 单向链表
*
* @author supu
* @create 2018-06-04 10:41
**/
public class LinkedList {
/**
* 头结点
*/
private Node head;
/**
* 节点长度
*/
private int count;
public LinkedList() {
//构造函数用来初始化
this.head = null;
count = 0;
}
// 添加节点
public void addNode(Node node) {
Node temp = null;
if (head != null) {
temp = head;
while (temp.getNext() != null) {
temp = temp.getNext();
}
temp.setNext(node);
} else {
head = node;
}
count++;
}
// 删除节点
public void removeNode(Node node) {
Node temp = head;
Node front = null;
while (temp != null) {
if (node.getData() == temp.getData()) {
break;
}
front = temp;
temp = temp.getNext();
}
if (temp != null) {
if (front != null) {
if (temp.getNext() == null) {
front.setNext(null);
} else {
front.setNext(temp.getNext());
}
} else {
head = head.getNext();
}
count--;
}
}
// 更新节点
public <T> void updateNode(Node node, T data) {
Node temp = head;
while (temp != null) {
if (node.getData() == temp.getData()) {
temp.setData(data);
break;
}
temp = temp.getNext();
}
}
// 打印节点信息
public void printNode() {
Node temp = head;
StringBuilder stringBuilder = new StringBuilder();
while (temp != null) {
stringBuilder.append(temp.getData()).append(",");
temp = temp.getNext();
}
System.out.println("链表总结点数:" + count + ", 链表数据:" + stringBuilder.toString());
System.out.println("*************************************");
}
}
3、单向链接测试类
package com.springboot.demo.linked;
/**
* 单向链接测试类
*
* @author supu
* @date 2019-06-19 10:48
**/
public class SimpleLinkedDemo {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
Node node5 = new Node();
node5.setData("five");
Node node4 = new Node("four");
Node node3 = new Node("three");
Node node2 = new Node("two");
Node node1 = new Node("one");
linkedList.addNode(node1);
linkedList.addNode(node2);
linkedList.addNode(node3);
linkedList.addNode(node4);
linkedList.printNode();
linkedList.removeNode(node2);
linkedList.printNode();
linkedList.addNode(node5);
linkedList.printNode();
linkedList.updateNode(node4, "newFour");
linkedList.printNode();
}
}
4、运行结果
双向链表
1、双向节点
package com.springboot.demo.linked;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* 双向节点
*
* @author supu
* @create 2018-06-04 14:12
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class DoubleNode<T> {
/**
* 数据
*/
private T data;
/**
* 上一个节点指针
* @ToString.Exclude 注解为了解决lombok下循环依赖toString方法报java.lang.StackOverflowError异常,此异常在debug模式下才能看到
*/
@ToString.Exclude
private DoubleNode previous;
/**
* 下一个指针节点
* @ToString.Exclude 注解为了解决lombok下循环依赖toString方法报java.lang.StackOverflowError异常,此异常在debug模式下才能看到
*/
@ToString.Exclude
private DoubleNode next;
public DoubleNode(T data) {
this.data = data;
}
}
2、双向链表
package com.springboot.demo.linked;
/**
* 双向链表
*
* @author supu
* @create 2018-06-04 14:01
**/
public class DoubleLinkedList {
/**
* 头结点
*/
private DoubleNode head;
/**
* 尾结点
*/
private DoubleNode tail;
public DoubleLinkedList() {
head = null;
tail = null;
}
/**
* 头部插入数据
*/
public void insertFirst(DoubleNode node) {
if (head == null) {
tail = node;
} else {
head.setPrevious(node);
node.setNext(head);
}
// 插入的节点作为头结点
head = node;
}
/**
* 尾部插入数据
*/
public void insertLast(DoubleNode node) {
if (head == null) {
head = node;
} else {
tail.setNext(node);
node.setPrevious(tail);
}
// 最后的节点设置为最新的节点
tail = node;
}
/**
* 删除头结点
*/
public DoubleNode removeHead() {
if (head == null) {
throw new RuntimeException("链表数据不存在");
}
DoubleNode temp = head;
if (head.getNext() == null) {
tail = null;
} else {
head.getNext().setPrevious(null);
}
head = temp.getNext();
return temp;
}
/**
* 删除尾结点
*/
public DoubleNode removeTail() {
if (head == null) {
throw new RuntimeException("链表数据不存在");
}
DoubleNode temp = tail;
if (head.getNext() == null) {
head = null;
tail = null;
} else {
tail.getPrevious().setNext(null);
}
tail = temp.getPrevious();
return temp;
}
/**
* 删除指定的结点
*/
public DoubleNode removeNode(DoubleNode node) {
if (head == null) {
throw new RuntimeException("链表数据不存在");
}
DoubleNode current = head;
while (current.getData() != node.getData()) {
if (current.getNext() == null) {
System.out.println("没有找到该节点");
return null;
}
current = current.getNext();
}
if (current == head) {
return removeHead();
} else {
current.getPrevious().setNext(current.getNext());
current.getNext().setPrevious(current.getPrevious());
}
return current;
}
/**
* 打印链表
*/
public void printDoubleLinkList() {
if (head == null) {
System.out.println("双向链表数据不存在");
}
DoubleNode node = head;
StringBuilder stringBuilder = new StringBuilder();
while (node != null) {
stringBuilder.append(node.getData()).append(",");
node = node.getNext();
}
System.out.println(stringBuilder.toString());
System.out.println("******************");
}
}
3、双向链表测试
package com.springboot.demo.linked;
/**
* 双向链表测试
*
* @author supu
* @date 2019-06-19 14:20
**/
public class DoubleLinkedDemo {
public static void main(String[] args) {
DoubleNode node1 = new DoubleNode("one");
DoubleNode node2 = new DoubleNode("two");
DoubleNode node3 = new DoubleNode("three");
DoubleLinkedList linkedList = new DoubleLinkedList();
linkedList.insertLast(node1);
linkedList.insertLast(node2);
linkedList.insertLast(node3);
linkedList.printDoubleLinkList();
linkedList.removeNode(node2);
linkedList.printDoubleLinkList();
linkedList.insertFirst(new DoubleNode("zero"));
linkedList.printDoubleLinkList();
linkedList.removeTail();
linkedList.printDoubleLinkList();
linkedList.removeHead();
linkedList.printDoubleLinkList();
}
}
4、运行结果