class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
1、创建链表
(1)从头到尾建立
让当前指针 cur 指向链表的尾结点,每增加一个结点 p,都将 cur.next 指向 p, 并将当前指针 cur 前移至 p, 保证在插入新结点之前当前指针 cur 都指向链表的尾结点。
ListNode create(int[] vals) {
ListNode result = new ListNode(-1);
ListNode cur = result;
for(int val: vals) {
ListNode p = new ListNode(val);
cur.next = p;
cur = p;
}
return result.next;
}
(2)从尾到头建立
让当前指针 cur 指向链表头,每增加一个节点 p,都将 p.next 指向 cur.next,然后将 cur.next 指向 p,每次新增节点 p 插入的位置都是在头结点之后。
ListNode createReverse(int[] vals) {
ListNode result = new ListNode(-1);
for(int val: vals) {
ListNode p = new ListNode(val);
p.next = result.next;
result.next = p;
}
return result.next;
}
2、链表逆序
(1)无头结点的链表
创建 next 为空的头结点,每次将要插入的节点从原链表中分离出来,插入新链表的头结点之后,要保证链表不断节。
ListNode reverse(ListNode list) {
ListNode head = new ListNode(-1);
while(list!=null) {
ListNode q = list.next;
list.next = head.next;
head.next = list;
list = q;
}
return head.next;
}
(2)带头结点的链表
将链表分成 next 为空的头结点和子链表两部分,每次将要插入的节点从子链表中分离出来,插入新链表的头结点之后,要保证链表不断节。
ListNode reverse(ListNode list) {
ListNode p = list.next;
list.next = null;
while(p!=null) {
ListNode q = p.next;
p.next = list.next;
list.next = p;
list = q;
}
}
(3)将无头结点的链表中第 m ~ n 个结点逆序
创建头结点,使其 next 指向链表;设置两个指针 cur, pre,分别指向当前结点及其前驱结点;遍历并统计结点个数,直到找到第 m 个结点 cur 为逆序起始结点,pre 为第 m-1 个结点;保存逆序起始结点,即第 m 个结点,逆序之后会成为第 n 个结点,以保证链表不断节;每次将逆序部分的结点从链表中分离出来,插到 pre 之后;最后将逆序起始结点的 next 指向第 n+1 个结点 cur。
ListNode reverseMN(ListNode list, int m, int n) {
ListNode head = new ListNode(-1);
head.next = list;
int count = 0; // 结点个数,包括头结点
ListNode cur = head, pre = cur; // cur 为逆序起始结点; pre 为 cur 的前驱结点
for(; cur!=null && count < m; count++) {
pre = cur;
cur = cur.next;
}
ListNode last = cur; // 保存逆序起始结点
for(; cur!=null && count<=n; count++) {
ListNode p = cur.next;
cur.next = pre.next;
pre.next = cur; // 每次都将结点插入到第 m-1 个结点之后
cur = p;
}
last.next = cur; // cur 指向的是第 n+1 个结点
return head.next;
}
(4)将带头结点的链表第 m~n 个结点逆序
设置两个指针 cur, pre 分别指向当前结点及其前驱结点,遍历链表并统计个数,直到找到第 m 个结点 cur 为逆序起始结点, pre 为第 m-1 个结点;保存逆序起始结点,以保证链表不断节;每次都将逆序部分的结点从链表中分离出来,插到 pre 之后;最后将逆序起始结点的 next 指向第 n+1 个结点 cur。
ListNode reverseMN(ListNode list, int m, int n) {
ListNode cur = list, pre = list;
int count = 0;
for(; cur!=null && count
pre = cur;
cur = cur.next;
}
ListNode last = cur;
for(; cur!=null && count<=n; count++) {
ListNode temp = cur.next;
cur.next = pre.next;
pre.next = cur;
cur = temp;
}
last.next = cur;
return list;
}
3、插入排序
(1)无头结点的链表
创建一个头结点,使其 next 为空,作为新链表的头结点;每次将链表的首结点插入到新链表的正确位置:先保存剩余子链表,然后在新链表中从头查找,设置两个指针 cur, pre,分别指向当前结点及其前驱结点,直到找到一个结点的值大于待插入结点的值,即为插入的位置,再将结点插入该位置:将 pre 的 next 指向待插入结点,待插入结点的 next 指向原结点。
ListNode insertionSort(ListNode head) {
ListNode result = new ListNode(-1);
while(head!=null) {
ListNode temp = head.next;
ListNode cur = result.next, pre = result;
while(cur!=null && head.val<cur.val) {
pre = cur;
cur = cur.next;
}
pre.next = head;
head.next = cur;
head = temp;
}
return result;
}
(2)带头结点的链表
将链表分离成头结点和子链表两部分,并将头结点的 next 设为空;每次都将子链表的首结点插到新链表的正确位置:先保存子链表的剩余部分,然后在新链表中从头查找,设置两个指针 cur, pre 分别指向新链表的当前结点及其前驱结点,直到找到一个结点的值大于首结点的值,即为插入的位置;再将结点插入该位置:将 pre 的 next 指向待插入结点,将待插入结点的 next 指向原结点。
ListNode insertionSort(ListNode list) {
ListNode head = list.next;
list.next = null;
while(head!=null) {
ListNode temp = head.next;
ListNode cur = list.next, pre = list;
while(cur!=null && head.val<cur.next) {
pre = cur;
cur = cur.next;
}
pre.next = head;
head.next = cur;
head = temp;
}
return list;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。