定义单链表节点
力扣上单链表节点定义是:
package com.wang.base.linkedList;
public class Demo01 {
class ListNode{
int val;
ListNode next;
ListNode(int x){
val=x;
}
}
}
但在实际的编程语言中,使用的节点会稍微复杂一些:
package com.wang.base.linkedList;
public class Demo01 {
class Node<E>{
E val;
Node<E> next;
Node<E> prev;
Node(Node<E> prev,E element,Node<E> next){
this.val=element;
this.next=next;
this.prev=prev;
}
}
}
主要区别:
-
编程语言标准库一般会提供泛型,即可以指定val字段为任何类型,而力扣的单链表节点的val字段只有int型
-
编程语言标准库一般使用双链表而不是单链表:单链表只有next一个指针,指向下一个节点,而双链表节点有两个指针,prev指向前一个节点,next指向下一个节点
为什么需要链表
一条链表不需要一整块连续的内存空间,链表的元素可以分散在内存空间的不同地方,通过节点上next和prev指针将零散的内存块串联起来形成一个链式结构。理论上链表是没有容量限制的。
但是链表不能通过索引快速访问元素,只能从头节点开始顺着next指针往后找
单链表的基本操作
创建一条单链表
package com.wang.base.linkedList;
public class Demo02 {
//定义单链表
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
//输入一个数组,转换成一条单链条
ListNode createLinkedList(int[]arr){
//如果数组为空,报错
if (arr==null||arr.length==0){
return null;
}
ListNode head=new ListNode(arr[0]);
ListNode cur=head;
for (int i = 0; i < arr.length; i++) {
cur.next=new ListNode(arr[i]);
cur=cur.next;
}
return head;
}
}
}
查/改
package com.wang.base.linkedList;
public class Demo02 {
//定义单链表
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
//输入一个数组,转换成一条单链条
ListNode createLinkedList(int[]arr){
//如果数组为空,报错
if (arr==null||arr.length==0){
return null;
}
//创建一条单链表
ListNode head=createLinkedList(new int[]{1,2,3,4,5});
//遍历单链表
for(ListNode p=head;p!=null;p=p.next){
System.out.println(p.val);
}
return head;
}
}
}
增加
在头部插入新元素
package com.wang.base.linkedList;
public class Demo02 {
//定义单链表
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
//输入一个数组,转换成一条单链条
ListNode createLinkedList(int[]arr){
//如果数组为空,报错
if (arr==null||arr.length==0){
return null;
}
//创建一条单链表
ListNode head=createLinkedList(new int[]{1,2,3,4,5});
//在单链表头部插入一个新节点0
ListNode newHead=new ListNode(0);
newHead.next=head;
head=newHead;
return head;
}
}
}
在尾部插入新元素
package com.wang.base.linkedList;
public class Demo02 {
//定义单链表
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
//输入一个数组,转换成一条单链条
ListNode createLinkedList(int[]arr){
//如果数组为空,报错
if (arr==null||arr.length==0){
return null;
}
//创建一条单链表
ListNode head=createLinkedList(new int[]{1,2,3,4,5});
//在单链表尾部插入一个新节点6
ListNode p=head;
//先走到链表的最后一个节点
while (p.next!=null){
p=p.next;
}
//现在p就是链表的最后一个节点
//在p后面插入新节点6
p.next=new ListNode(6);
return head;
}
}
}
在中间插入新元素
package com.wang.base.linkedList;
public class Demo02 {
//定义单链表
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
//输入一个数组,转换成一条单链条
ListNode createLinkedList(int[] arr) {
//如果数组为空,报错
if (arr == null || arr.length == 0) {
return null;
}
//创建一条单链表
ListNode head = createLinkedList(new int[]{1, 2, 3, 4, 5});
//想在第三个节点后面插入新节点66
//找到第三个节点
ListNode p=head;
for (int i = 0; i < 2; i++) {
p=p.next;
}
//此时p指向第三个节点
//组装新节点后的后驱指针
ListNode newNode=new ListNode(66);
newNode.next=p.next;
//插入新节点
p.next=newNode;
return head;
}
}
}
删除
在头部删除元素
package com.wang.base.linkedList;
public class Demo02 {
//定义单链表
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
//输入一个数组,转换成一条单链条
ListNode createLinkedList(int[] arr) {
//如果数组为空,报错
if (arr == null || arr.length == 0) {
return null;
}
//创建一条单链表
ListNode head = createLinkedList(new int[]{1, 2, 3, 4, 5});
//删除头节点
head=head.next;
return head;
}
}
}
在尾部删除元素
package com.wang.base.linkedList;
public class Demo02 {
//定义单链表
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
//输入一个数组,转换成一条单链条
ListNode createLinkedList(int[] arr) {
//如果数组为空,报错
if (arr == null || arr.length == 0) {
return null;
}
//创建一条单链表
ListNode head = createLinkedList(new int[]{1, 2, 3, 4, 5});
//删除尾节点
ListNode p=head;
//找到倒数第二个节点
while (p.next.next!=null){
p=p.next;
}
//此时p指向倒数第二个节点
//把尾节点从链表中摘除
p.next=null;//把节点变为null就是删除
return head;
}
}
}
在中间删除元素
package com.wang.base.linkedList;
public class Demo02 {
//定义单链表
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
//输入一个数组,转换成一条单链条
ListNode createLinkedList(int[] arr) {
//如果数组为空,报错
if (arr == null || arr.length == 0) {
return null;
}
//创建一条单链表
ListNode head = createLinkedList(new int[]{1, 2, 3, 4, 5});
//删除第四个节点,要操作前驱节点
ListNode p=head;
for (int i = 0; i < 2; i++) {
p=p.next;
}
//此时p指向第三个节点
p.next=p.next.next;//第四个节点等于第五个节点,认为是删掉第四个节点
return head;
}
}
}
双链表的基本操作
双链表是有两条链子,所以断掉或者连接时要有两步
创建一条双链表
package com.wang.base.linkedList;
public class Demo03 {
class DoublyListNode{
int val;
DoublyListNode next,prev;
DoublyListNode(int x){val =x;}
}
DoublyListNode createDoublyLinkedList(int[]arr){
if (arr==null||arr.length==0){
return null;
}
DoublyListNode head=new DoublyListNode(arr[0]);
DoublyListNode cur=head;
//for循环迭代创建双链表
for (int i = 1; i < arr.length; i++) {
DoublyListNode newNode=new DoublyListNode(arr[i]);
cur.next=newNode;
newNode.prev=cur;
cur=cur.next;
}
return head;
}
}
查/改
package com.wang.base.linkedList;
public class Demo03 {
class DoublyListNode{
int val;
DoublyListNode next,prev;
DoublyListNode(int x){val =x;}
}
DoublyListNode createDoublyLinkedList(int[]arr){
if (arr==null||arr.length==0){
return null;
}
//创建一条双链表
DoublyListNode head=createDoublyLinkedList(new int[]{1,2,3,4,5});
DoublyListNode tail=null;
//从头节点向后遍历双链表
for (DoublyListNode p=head;p!=null;p=p.next){
System.out.println(p.val);
tail=p;
}
//从尾节点向前遍历双链表
for (DoublyListNode p=tail;p!=null;p=p.prev){
System.out.println(p.val);
}
return head;
}
}
在实际应用中,可以根据索引是靠近头部还是尾部来选择合适的方向遍历,可以一定程度上提高效率
增加
在头部插入新元素
package com.wang.base.linkedList;
public class Demo03 {
class DoublyListNode{
int val;
DoublyListNode next,prev;
DoublyListNode(int x){val =x;}
}
DoublyListNode createDoublyLinkedList(int[]arr){
if (arr==null||arr.length==0){
return null;
}
//创建一条双链表
DoublyListNode head=createDoublyLinkedList(new int[]{1,2,3,4,5});
//想在头部插入0
DoublyListNode newHead=new DoublyListNode(0);
newHead.next=head;//这两个式子形成双链表
head.prev=newHead;//这两个式子形成双链表
head=newHead;//之前head=1,相等后head=0
return head;
}
}
在尾部插入新元素
package com.wang.base.linkedList;
public class Demo03 {
class DoublyListNode{
int val;
DoublyListNode next,prev;
DoublyListNode(int x){val =x;}
}
DoublyListNode createDoublyLinkedList(int[]arr){
if (arr==null||arr.length==0){
return null;
}
//创建一条双链表
DoublyListNode head=createDoublyLinkedList(new int[]{1,2,3,4,5});
DoublyListNode tail=head;//tail=1
//先走到链表的最后一个节点
while (tail.next!=null){
tail=tail.next;
}//tail=5
//在尾部插入6
DoublyListNode newNode=new DoublyListNode(6);
tail.next=newNode;
newNode.prev=tail;
//更新尾节点引用
tail=newNode;
return head;
}
}
在中间插入新元素
package com.wang.base.linkedList;
public class Demo03 {
class DoublyListNode{
int val;
DoublyListNode next,prev;
DoublyListNode(int x){val =x;}
}
DoublyListNode createDoublyLinkedList(int[]arr){
if (arr==null||arr.length==0){
return null;
}
//创建一条双链表
DoublyListNode head=createDoublyLinkedList(new int[]{1,2,3,4,5});
//想在第三个节点后插入新节点66
DoublyListNode p=head;
for (int i = 0; i < 2; i++) {
p=p.next;//p=3
}
//组装新节点
DoublyListNode newNode=new DoublyListNode(66);
newNode.next=p.next;//66的后面是4
newNode.prev=p;//66的前面是3
//插入新节点
p.next.prev=newNode;//3的后面是4,4的前面变成66
p.next=newNode;//最终结果是3的后面是4
return head;
}
}
删除
在头部删除元素
package com.wang.base.linkedList;
public class Demo03 {
class DoublyListNode{
int val;
DoublyListNode next,prev;
DoublyListNode(int x){val =x;}
}
DoublyListNode createDoublyLinkedList(int[]arr){
if (arr==null||arr.length==0){
return null;
}
//创建一条双链表
DoublyListNode head=createDoublyLinkedList(new int[]{1,2,3,4,5});
//删除头部节点
DoublyListNode toDelete=head;
head=head.next;//head原本是1,现在是2
head.prev=null;//2的前面变成null
//清理已经删除节点的指针
toDelete.next=null;
return head;
}
}
在尾部删除元素
package com.wang.base.linkedList;
public class Demo03 {
class DoublyListNode{
int val;
DoublyListNode next,prev;
DoublyListNode(int x){val =x;}
}
DoublyListNode createDoublyLinkedList(int[]arr){
if (arr==null||arr.length==0){
return null;
}
//创建一条双链表
DoublyListNode head=createDoublyLinkedList(new int[]{1,2,3,4,5});
//删除尾部节点
DoublyListNode p=head;
//找到尾部节点
while (p.next!=null){
p=p.next;
}//现在p指向尾部节点,p=5
//把尾部节点从链表中摘除
p.prev.next=null;//5的前面是4,4的后面变成null
//把被删的节点的指针都断掉
p.prev=null;//经过上步,尾部节点已经去掉了一条,再说清楚它前面是null,可以把另外一条也去掉
return head;
}
}
在中间删除元素
package com.wang.base.linkedList;
public class Demo03 {
class DoublyListNode{
int val;
DoublyListNode next,prev;
DoublyListNode(int x){val =x;}
}
DoublyListNode createDoublyLinkedList(int[]arr){
if (arr==null||arr.length==0){
return null;
}
//创建一条双链表
DoublyListNode head=createDoublyLinkedList(new int[]{1,2,3,4,5});
//想要删除第四个节点
//先找到第三个节点
DoublyListNode p=head;
for (int i = 0; i < 2; i++) {
p=p.next;//p=3
}
DoublyListNode toDelete=p.next;//to=4
//把to从链表中摘出去
p.next=toDelete.next;//第四节点=5
toDelete.next.prev=p;//4后面是5,5的前面变成3
//把to前后指针都设置为null是个好习惯(可选)
toDelete.next=null;
toDelete.prev=null;
return head;
}
}
浙公网安备 33010602011771号