数据结构: 反转链表
反转单链表
ListNode* reverseLinkList(ListNode* head) {
// 仅有一个或为空,返回自身
if (head == NULL || head->next == NULL) {
return head;
}
ListNode* pre = head;
ListNode* cur = head->next;
while (cur != NULL) {
if (pre == head) {
pre->next = NULL;
}
ListNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
// 反转链表,逐一节点改变指针指向
ListNode* reverseLinkList2(ListNode* head) {
ListNode* pre = NULL;
ListNode* next = NULL;
while (head!=NULL) {
next = head->next;
head->next = pre;
pre = head;
head = next;
}
return pre;
}
反转双向链表
// 反转双向链表
DoubleLinkNode* reverseDoubleLink(DoubleLinkNode* head) {
DoubleLinkNode* pre = NULL;
DoubleLinkNode* next = NULL;
DoubleLinkNode* cur = head;
while (cur != NULL) {
next = cur->next;
cur->next = pre;
cur->last = next;
pre = cur;
cur = next;
}
return pre;
}
反转部分单向链表
给定一个头结点head,以及两个整数,from和to.
反转第from个节点到第to个节点这一部分.
返回新的链表的头结点
ListNode* reversePart(ListNode* head, int from, int to) {
int len = 0;
ListNode* p = head;
ListNode* fPre = NULL;
ListNode* tPos = NULL;
// 统计长度,同时记录 from的前一个和to的后一个节点
while (p != NULL) {
len++;
fPre = len == from - 1 ? p : fPre;
tPos = len == to + 1 ? p : tPos;
p = p->next;
}
// 不在有效范围内返回空
if (from > to || from<1 || to>len) {
return head;
}
/*
反转之前: fPre f ... t tPos
反转之后: fPre t ... f tPos
若fPre不为空,则fPre->next = t, 返回原来的头结点
若fPre为空,则返回的是 t
*/
p = fPre == NULL ? head : fPre->next;
ListNode* q = p->next;
ListNode* next = NULL;
// p表示的是q的前一个节点
// q表示当前访问的节点,它从 [from ... to] 的第二个节点开始
// next用于链表断开保存q下一个节点
while (q != tPos) {
next = q->next;
q->next = p;
p = q;
q->next;
}
if (fPre != NULL) {
fPre->next = p;
return head;
}
return p;
}
体会
- 链表的反转需要一个节点一个节点的做.
- 注意保存将会被断开的节点