今天来练习以下单链表的一些操作,以下的操作都是带有头节点的链表。
定义链表节点类
定义了节点中的值,节点的下一个节点,和一些基本的方法。
public static class ListNode{
int val;
ListNode next;
public ListNode() {
}
public ListNode(int val){
this.val=val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
@Override
public String toString() {
return "Node{" +
"val=" + val +
", next=" + next +
'}';
}
}
头插
头插的实现很简单,让想要插入的节点指向头节点指向的第一个节点,再让头节点指向想要插入的节点即可。
public static void headInsert(ListNode root,ListNode node){
node.next = root.next;
root.next = node;
}
尾插
尾插也很简单,直接循环遍历到最后一个节点,让其指向要插入的节点即可。
public static void tailInsert(ListNode root,ListNode node){
while(root.next!=null){
root=root.next;
}
root.next=node;
}
链表反转
链表的反转稍微复杂一点。
我们需要用到三个节点来保存链表中的节点。
定义cur指向当前想要反转的节点。
定义pre指向当前想要反转的节点的前一个结点,初始为null。
定义next指向当前想要反转的节点的下一个结点。
通过循环,先找到next,然后让cur指向pre,实现反转,再将pre和cur整体向后动以便完成下个结点的反转。
例如想要反转链表root->1->2->3,首先选中cur和next
当前pre为空然后让cur指向pre,再整体往后。
随后再走一遍流程
继续再走一遍完成,改变root指向。
public static void reverasl(ListNode root){
ListNode prev = null;
ListNode curr = root.next;
while (curr != null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
root.next = prev;
}