创建链表
在java中一般使用节点的概念表示链表节点,其中包含节点的值以及一点的下一个节点。
public class Node{
private int val;
private Node next;
}
链表添加元素
向链表尾部添加元素
首先遍历找到链表尾部节点,再将尾部节点指向新的节点
/**
* 链表尾部添加节点
* @param head 原始链表头节点
* @param newNode 新增节点
*/
public static void addNodeInEnd(Node head, Node newNode) {
Node node = head;
while (node.next != null) {
node = node.next;
}
node.next = newNode;
}
向链表头部添加元素
/**
* 链表头部添加节点
* @param head 原始链表头节点
* @param newNode 新增节点
*/
public static Node addNodeInHead(Node head, Node newNode) {
newNode.next = head;
head = newNode;
return head;
}
向链表中间添加元素
/**
* 链表中间添加节点
* @param head
* @param val
* @param newNode
* @return
*/
public static Node addNodeInMid(Node head, int val, Node newNode) {
Node node = head;
while (node.val != val) {
node = node.next;
}
/*Node temp = node.next;
node.next = newNode;
newNode.next = temp;*/
newNode.next = node.next;
node.next = newNode;
return head;
}
链表删除元素
遍历找到要删除链表节点的前一个节点
删除头节点时会遇到头节点没有前驱节点的问题,但是删除尾节点和中间节点不存在这样的问题,因为尾节点的下一个节点为null而已。
所以我们在构建链表的时候可以使用一个虚拟头节点来连接真正的头节点,这样就可以将各个位置删除节点的操作合并为一段代码。
然后将节点的下一个指向为节点的下一个的下一个节点
/**
* 链表删除节点
* @param head 原始链表头节点
* @param removeVal 要删除的节点
*/
public static void removeNode(Node head, int removeVal) {
if (head == null) {
return;
}
Node node = head;
while (node.next.val != removeVal) {
node = node.next;
}
node.next = node.next.next;
}
双向链表
构建双向链表
class DoubleNode {
private int val;
private DoubleNode left;
private DoubleNode right;
public DoubleNode(int val) {
this.val = val;
}
public DoubleNode(int val, DoubleNode left, DoubleNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
双向链表头部插入
/**
* 双向链表头部插入
* @param headNode
* @param targetNode
*/
public static void insertDoubleNodeInHead(DoubleNode headNode,
DoubleNode targetNode){
targetNode.next = headNode.next;
headNode.next.pre = targetNode;
targetNode.pre = headNode;
headNode.next = targetNode;
}
双向链表尾部插入
/**
* 双向链表尾部插入
* @param tailNode
* @param targetNode
*/
public static void insertDoubleNodeInTail(DoubleNode tailNode,
DoubleNode targetNode){
targetNode.pre = tailNode.pre;
tailNode.pre.next = targetNode;
targetNode.next = tailNode;
tailNode.pre = targetNode;
}
双向链表中间插入,在值为val的节点后插入
/**
* 双向链表中间插入,在值为val的节点后插入
* @param headNode
* @param val
* @param targetNode
*/
public static void insertDoubleNodeInMid(DoubleNode headNode,
int val,
DoubleNode targetNode){
DoubleNode node = headNode;
while ( node != null && node.val != val ) {
node = node.next;
}
targetNode.next = node.next;
node.next.pre = targetNode;
node.next = targetNode;
targetNode.pre = node;
}
双向链表删除节点
/**
* 双向链表删除节点
* @param headNode
* @param val
* @param targetNode
*/
public static void deleteDoubleNode(DoubleNode headNode,
int val,
DoubleNode targetNode){
DoubleNode node = headNode;
while ( node != null && node.val != val ) {
node = node.next;
}
if (node == null) {
System.out.println("要删除的链表节点不存在");
return;
}
node.pre.next = node.next;
node.next.pre = node.pre;
}