参考博文:
Java数据结构和算法(七)——链表
一、链表定义
是一种链式存储结构, 数据在物理空间是分散存储的. 每个节点包含2部分, 存储的数据和指向下一个节点的地址.
二、链表的种类
1.单链表
单链表特点:
1.只能向一个方向遍历
2.添加元素从头部插入, 若想向尾部插入元素, 必须遍历前n-1个节点
通过单向链表可实现栈, 添加节点和删除头节点对应栈的入栈和出栈
新增节点
删除节点
实现思路: 将当前节点的上一个节点指向当前节点的下一个节点
代码实现
public class SinglyLinkedList {
// 指向头结点
private Node head;
// 链表长度
private int size;
public SinglyLinkedList() {
this.size = 0;
this.head = null;
}
// 定义一个内部类Node
private class Node {
private Object data;
private Node next;
public Node(Object data, Node next) {
this.data = data;
this.next = next;
}
}
// 增加节点
public void addNode(Object obj) {
if (size == 0) {
Node newNode = new Node(obj, null);
head = newNode;
size++;
return;
}
Node previous = head;
Node newNode = new Node(obj, previous );
head = newNode; // 将头部地址指向当前节点
size++;
}
// 打印链表
public void display() {
if (size == 0) {
System.out.println("[]");
} else {
Node current = head;
// 遍历前n-1个节点
while (current.next != null) {
Object data = current.data;
System.out.print(data + "==>");
current = current.next;
}
System.out.println(current.data);// 打印最后一个
}
}
// 删除头节点
public Object deleteHeadNode() {
if (size != 0) {
Object obj = head.data;
head = head.next;
size--;
return obj;
}
return null;
}
// 查找链表中的元素
public Object find(Object obj) {
if (size == 0) {
return null;
}
Node current = head;
while (current.next != null) {
if (current.data.equals(obj)) {
return obj;
}
current = current.next;
}
// 最后一个元素
if (current.data.equals(obj)) {
return obj;
}
return null;
}
2.双端链表
双端链表相对于单链表多了一个尾节点的引用, 这样向尾部添加数据就方便多了
双端链表实现队列, 向尾部插入数据对应入队, 删除头部节点对应出队
public class DoublEendedList {
private Node head; // 指向头部节点
private Node tail; // 指向尾部节点
private int size;
public DoublEendedList() {
this.head = null;
this.tail = null;
this.size = 0;
}
// 节点类
private class Node {
private Object data;//节点数据
private Node next;// 节点指向下一节点连接
public Node(Object data, Node next) {
this.data = data;
this.next = next;
}
}
}
// 在头部插入节点
public void addNode(Object data) {
if (size == 0) {
Node node = new Node(data, null);
head = node;
tail = node;
} else {
Node node = new Node(data, head);
head = node;
}
size++;
}
// 在尾部添加节点
public Object addTail(Object obj) {
if (size == 0) {
Node node = new Node(obj, null);
head = node;
tail = node;
} else {
Node node = new Node(obj, null);
tail.next = node;
tail = node;
}
size++;
return tail.data;
}
// 从后往前遍历
public void displayBackword() {
Node last = tail;
if (size == 0) {
System.out.println("[]");
} else {
while (last.previous != null) { // 遍历后n-1个
System.out.print(last.data + "=>");
last = last.previous;
}
System.out.println(last.data);// 遍历至第一个
}
}
// 从前往后遍历
public void displayForword() {
Node current = head;
if (size == 0) {
System.out.println("[]");
} else {
while (current.next != null) {
System.out.print(current.data + "==>");
current = current.next;
}
System.out.println(current.data);// 遍历至最后一个
}
}
// 删除头部节点
public Object deleteHead() {
Object obj = null;
if (size == 0) {
return null;
}
if (size == 1) {
obj = head.data;
head = null;
size--;
} else {
obj = head.data;
Node next = head.next;
head = next;
size--;
}
return obj;
}
// 遍历链表
public void display() {
if (size == 0) {
System.out.println("[]");
} else {
Node current = head;
while (current.next != null) {
Object data = current.data;
System.out.print(data + "==>");
current = current.next;
}
System.out.println(current.data);// 打印最后一个
}
// 删除节点
public Object deletNode(Object obj) {
Object item = null;
if (size == 0) {
return item;
}
if (size == 1) {
if (head.data.equals(obj)) {
head = null;
tail = null;
size--;
item = obj;
}
} else {
Node current = head;
while (current.next != null) {
if (current.previous == null) {// 如果是第一个
if (head.data.equals(obj)) {
head = current.next;
head.previous = null;
current = head;
size--;
item = obj;
continue;
}
current = current.next;
} else {
if (current.data.equals(obj)) {
Node previous = current.previous;
Node next = current.next;
previous.next = next;
next.previous = previous;
current = current.next;
size--;
item = obj;
continue;
}
current = current.next;
}
}
if (current.data.equals(obj)) { // 处理最后一个节点
current.previous.next = null;
tail = current.previous;
size--;
item = obj;
}
}
return item;
}
}
3.双向链表
双向链表相对于双端链表, 节点的结构新增加了指向前一个节点的地址, 这样链表就可以双向遍历了.
新增节点:
public class TwoWayLinkedList {
private Node head;
private Node tail;
private int size;
public TwoWayLinkedList() {
size = 0;
head = null;
tail = null;
}
private class Node {
private Object data;
private Node next;
private Node previous;
public Node(Object data, Node next, Node previous) {
this.data = data;
this.next = next;
this.previous = previous;
}
}
// 向头部插入节点
public Object addNode(Object obj) {
if (size == 0) {
Node node = new Node(obj, null, null);
head = node;
tail = node;
} else {
Node node = new Node(obj, head, null);
head.previous = node;
head = node;
}
size++;
return obj;
}
// 向尾部插入节点
public Object addTailNode(Object obj) {
if (size == 0) {
Node node = new Node(obj, null, null);
head = node;
tail = node;
} else {
Node node = new Node(obj, null, tail);
tail.next = node;
tail = node;
}
size++;
return obj;
}
// 查找节点
public Object find(Object obj) {
Node current = head;
if (size == 0) {
return null;
} else {
while (current.next != null) {
if (current.data.equals(obj)) {
return obj;
}
current = current.next;
}
if (current.data.equals(obj)) {
return obj;
}
}
return null;
}
}
// 删除头部节点
public Object deleteHeadNode() {
Node current = head;
if (size == 0) {
return current;
} else {
head = current.next;
head.previous = null;
}
size--;
return current.data;
}
// 删除尾部节点
public Object deleteTailNode() {
Node last = tail;
if (size == 0) {
return last;
} else {
if (last.previous != null) {
tail = last.previous;
tail.next = null;
size--;
} else {
// 只有一个节点
head = null;
tail = null;
size--;
}
}
return last.data;
}
// 删除节点
public Object deletNode(Object obj) {
Object item = null;
if (size == 0) {
return item;
}
if (size == 1) {
if (head.data.equals(obj)) {
head = null;
tail = null;
size--;
item = obj;
}
} else {
Node current = head;
while (current.next != null) {
if (current.previous == null) {// 如果是第一个
if (head.data.equals(obj)) {
head = current.next;
head.previous = null;
current = head;
size--;
item = obj;
continue;
}
current = current.next;
} else {
if (current.data.equals(obj)) {
Node previous = current.previous;
Node next = current.next;
previous.next = next;
next.previous = previous;
current = current.next;
size--;
item = obj;
continue;
}
current = current.next;
}
}
if (current.data.equals(obj)) { // 处理最后一个节点
current.previous.next = null;
tail = current.previous;
size--;
item = obj;
}
}
return item;
}