链表,认识数据结构:单向链表,双向链表,反转链表
提示:现在开始说链表系列的基础和相应的题目
什么是链表
由带指针的节点串接在一起的数据结构,就是链表,由于指针可以有1个指针,2个指针,将链表分为单向链表和双向链表
单向链表
节点结构:
内部有一个value
还有一个next指针
//单向链表,单个方向,next指针【引用】,每个节点有一个value
public static class Node{
public int value;//链表节点的值
public Node next;//节点指向下一个节点,指针,或者引用
//构造函数
public Node(int value, Node next){
this.next = next;
this.value = value;//初始化定义所需
}
}
构造函数那可以没有next,让next为空
//单向链表,单个方向,next指针【引用】,每个节点有一个value
public static class Node2{
public int value;//链表节点的值
public Node next;//节点指向下一个节点,指针,或者引用
//构造函数
public Node2(int value){
this.next = null;
this.value = value;//初始化定义所需
}
}
这样的话,你后面建链表时,自己去挂接。
//造一个单向链表:
public static Node2 createLinkList(){
Node2 head = new Node2(1);
Node2 n2 = new Node2(2);
Node2 n3 = new Node2(3);
Node2 n4 = new Node2(4);
//挂接
head.next = n2;
n2.next = n3;
n3.next = n4;
//这样1--2--3--4串成了一个链表
return head;
}
双向链表
和单向链表唯一的区别就是双向链表多了一条last指针
双向链表的节点:
//也可以不造直接连接的那种双向链表:
public static class DoubleNode2{
public int value;
public DoubleNode2 last;
public DoubleNode2 next;
public DoubleNode2(int v){
value = v;
last = null;
next = null;
}
}
然后外面造链表,和单向链表一样(开头那个链表就是下面这样生成的)
//造一个双向链表:
public static DoubleNode2 createDoubleLinkList(){
DoubleNode2 head = new DoubleNode2(1);
DoubleNode2 n2 = new DoubleNode2(2);
DoubleNode2 n3 = new DoubleNode2(3);
DoubleNode2 n4 = new DoubleNode2(4);
//挂接
head.next = n2;
head.last = null;
n2.next = n3;
n2.last = head;//这别整错了
n3.next = n4;
n3.last = n2;
n4.last = n3;
//这样1--2--3--4串成了一个链表
return head;
}
这俩就是链表的基础知识
当一个节点,它有3个以上的指针时,就叫多叉树。
当然,将来我们可以看到,如果last改为left,next改为right,那这个双向的链表,可以直接改为二叉树binaryTree!
后面再说……
一、如何反转单向链表
好了,有了链表的知识,我们来反转单向链表
啥叫反转链表呢?就是将链表调换方向
怎么做呢?
这里,必须打牢基础,而且得纯手撕代码!反转链表时最基本的骚操作!不会的话那很多题目不好做。
不管是双向,还是单向的链表,反转3大步骤:
(1)预设head即将要去的下一个指针next=head.next,让pre=null做反转后的末端。
(2)将head的指针掉头:head.next=pre(单向链表和双向链表都有的),head.last=next(这是双向独有的)
(3)挪动pre到head,挪动head到next,回到(1)
!一定谨慎:这里别整错了
先让pre = head;然后才是 head = next;//卧槽,这俩别整反了
直到head=null,停止,返回pre,此时pre也就是反转后的链表的头部。
对于链表1–2–3
我们来反转一下:
(1)
(2)
(3)
(4)
//复习:
public static Node2 reverseSingleLinkList(Node2 head){
if (head == null) return null;
Node2 pre = null;
Node2 next = null;
while (head != null){
//head将来到了null,即没有元素了,停止
next = head.next;//预设next
head.next = pre;
//双向的话,head.last = next;
//然后挪动head和pre
pre = head;
head = next;//卧槽,这俩别整反了
}
//最后pre就是最后一个节点
return pre;
}
二、如何反转双向链表
双向链表一个道理,无非就是将last也反着指,在掉头指针的地方比单向链表多一句:head.last = next;//双向的话,last也要反着指
//复习:
public static DoubleNode2 reverseDoubleLinkList2(DoubleNode2 head){
if (head == null) return null;
DoubleNode2 pre = null;
DoubleNode2 next = null;
while (head != null){
//head将来到了null,即没有元素了,停止
next = head.next;//预设next
head.next = pre;
head.last = next;//双向的话,last也要反着指
//然后挪动head和pre
pre = head;
head = next;//卧槽,这俩别整反了
}
//最后pre就是最后一个节点
return pre;
}
测试一波:
public static void test2(){
Node2 head = createLinkList();
DoubleNode2 head2 = createDoubleLinkList();
Node2 ans1 = reverseSingleLinkList2(head);
DoubleNode2 ans2 = reverseDoubleLinkList2(head2);
//打印验证一波
while (ans1 != null){
System.out.print(ans1.value +" ");
ans1 = ans1.next;
}
System.out.println();
while (ans2 != null){
System.out.print(ans2.value +" ");
ans2 = ans2.next;
}
}
//主函数
public static void main(String[] args) {
//reverseSingle();
//reverseDouble();
test2();
}
结果:
4 3 2 1
4 3 2 1
总结
提示:重要经验:
1)单向链表和双向链表的结构特点记住
2)反转链表的代码,别整错了,一定按照逻辑,先后操作谁,错了不行的。