1.單鏈表逆序
實現1:
遍歷:
1: /*
2: * 遍歷鏈表, 將每個結點的next置為其前驅
3: * 遍歷過程中需要額外的指針來記錄結點的前驅和后繼
4: */
5: LinkList ReverseList(LinkList L)
6: {
7: if (!L || !L->next) {
8: return L;
9: }
10:
11: Node *pre, *cur, *next;
12:
13: pre = next = NULL;
14: cur = L->next;
15: while (cur) {
16: next = cur->next;
17: cur->next = pre;
18: pre = cur;
19: cur = next;
20: }
21: L->next = pre;
22:
23: return L;
24: }
實現2:
遞歸:
1: /*
2: * 采用遞歸,每次遞歸返回子鏈表反轉后的頭指針
3: */
4: Node * ReverseList(Node *node)
5: {
6: if (!node || !node->next) {
7: return node;
8: }
9:
10: Node *next = node->next;
11: Node *head = ReverseList(next);
12: next->next = node;
13: node->next = NULL;
14:
15: return head;
16: }
2.合並有序鏈表
實現1:
遍歷, 遍歷兩個鏈表,每次將較小的結點插入到合並后的新鏈表。
1: Node *Merge(Node *head1, Node *head2)
2: {
3: /* 如果一個鏈表為空, 則直接返回另一個 */
4: if (!head1) {
5: return head2;
6: }
7: if (!head2) {
8: return head1;
9: }
10:
11: /* head為合並后的頭指針, p1 p2分別用來遍歷兩個鏈表 */
12: Node *head, *p1, *p2;
13: head = p1 = p2 = NULL;
14: if (head1->data < head2->data) {
15: head = head1;
16: p1 = head1->next;
17: p2 = head2;
18: } else {
19: head = head2;
20: p2 = head2->next;
21: p1 = head1;
22: }
23:
24: /* cur為合並后鏈表的當前結點, 從p1和p2從選出較小的作為其后繼 */
25: Node *cur = head;
26: while (!p1 && !p2) {
27: if (p1->data <= p2->data) {
28: cur->next = p1;
29: cur = p1;
30: p1 = p1->next;
31: } else {
32: cur->next= p2;
33: cur = p2;
34: p2 = p2->next;
35: }
36: }
37:
38: /* 遍歷完一個鏈表后,將另一鏈表剩余結點插入到新鏈表中 */
39: if (!p1) {
40: cur->next= p1;
41: } else {
42: cur->next= p2;
43: }
44:
45: return head;
46: }
實現2:
遞歸,每次遞歸返回合並后新鏈表的頭結點。
1: Node *MergeRecursive(Node *head1, Node *head2)
2: {
3: if (!head1 || !head2) {
4: return head1 ? head1 : head2;
5: }
6:
7: Node *head;
8: if (head1->data < head2->data) {
9: head = head1;
10: head->next = MergeRecursive(head1->next, head2);
11: } else {
12: head = head2;
13: head->next = MergeRecursive(head1, head2->next);
14: }
15:
16: return head;
17: }
3.判斷兩個無環單鏈表是否交叉,如果是則返回交點
實現1:
判斷是否交叉:因為無環單鏈表只可能是Y型交叉,所以遍歷兩個鏈表至最后一個結點,判斷最后一個結點是否相等即可。
1: bool IsCross(Node *head1, Node *head2)
2: {
3: if (!head1 || !head2) {
4: return false;
5: }
6:
7: Node *p1 = head1;
8: Node *p2 = head2;
9: while (p1->next) {
10: p1 = p1->next;
11: }
12: while (p2->next) {
13: p2 = p2->next;
14: }
15:
16: return (p1 == p2);
17: }
找出交點:遍歷兩個鏈表,記錄長度分別為L1和L2,先讓長的鏈表向后移動abs(L1-L2),然后在逐個比較結點,第一個相等的結點即為交點。
1: Node *FindCross(Node *head1, Node *head2)
2: {
3: if (!head1 || !head2) {
4: return NULL;
5: }
6:
7: /* 求出兩個鏈表的長度 */
8: Node *p1, *p2;
9: p1 = head1;
10: p2 = head2;
11: int len1, len2, len;
12: len1 = len2 = 0;
13: while (p1) {
14: len1++;
15: p1 = p1->next;
16: }
17: while (p2) {
18: len2++;
19: p2 = p2->next;
20: }
21:
22: /* 將長鏈表先移動len個結點 */
23: int i;
24: len = abs(len1 - len2);
25: p1 = head1;
26: p2 = head2;
27: if (len1 > len2) {
28: for (i = 0; i < len; ++i) {
29: p1 = p1->next;
30: }
31: } else {
32: for (i = 0; i < len; ++i) {
33: p2 = p2->next;
34: }
35: }
36:
37: /* 遍歷 找到第一個相等的結點即為交點 */
38: while (!p1) {
39: p1 = p1->next;
40: p2 = p2->next;
41: if (p1 == p2) {
42: return p1;
43: }
44: }
45:
46: return NULL;
47: }
實現2:
將其中一個鏈表首尾相連,這樣就轉換成為判斷另一個鏈表是否有環即求進入環的結點的問題。
4.判斷單鏈表是否有環, 如果有環則返回進入環的第一個結點.
實現1:
設置快慢指針,初始都指向鏈表頭,快指針每次前進兩步,慢指針每次前進一步,如果有環則兩個指針必定相遇。
判讀是否有環:
1: bool HaveCircle(Node *head)
2: {
3: if (!head) {
4: return false;
5: }
6:
7: Node *fast, *slow;
8: fast = slow = head;
9:
10: while (fast && fast->next) {
11: slow = slow->next;
12: fast = fast->next->next;
13: if (fast == slow) {
14: return true;
15: }
16: }
17:
18: return false;
19: }
實現2:
將結點的地址做hash,遍歷鏈表,檢測是否有地址相等的結點。
5.找出單鏈表的中間元素
實現:
設置快慢指針,初始都指向鏈表頭,快指針每次前進兩步,慢指針每次前進一步,當快指針到達鏈表末尾時,慢指針所指即為單鏈表的中間元素。
1: Node *FindMid(Node *head)
2: {
3: if (!head) {
4: return NULL;
5: }
6:
7: Node *fast, *slow;
8: fast = slow = head;
9: while (fast && fast->next) {
10: slow = slow->next;
11: fast = fast->next->next;
12: }
13: /* 如果是fast為NULL, 則鏈表長度為奇數, slow為中間結點
14: * 如果是fast->next為NULL, 則鏈表長度為偶數, slow 和 slow->next 為中間結點
15: */
16: return slow;
17: }
6.刪除單鏈表中倒數第k個結點
實現:
設置兩個指針p1和p2,p1指向鏈表第一個結點,p2指向第k+1個結點,兩個指針同時前進,當p2到達鏈表尾時,p1指向倒數第k+1個結點,刪除p1后面的一個結點即可。
1: Node *DeleteK(Node *head, int k) {
2: if (!head) {
3: return NULL;
4: }
5:
6: int i;
7: Node *p1, *p2;
8: p1 = p2 = head;
9: for (i = 0; i <= k; ++i) {
10: if (p2) {
11: p2 = p2->next;
12: } else {
13: return NULL;
14: }
15: }
16:
17: while (p2) {
18: p1 = p1->next;
19: p2 = p2->next;
20: }
21: p2 = p1->next;
22: p1->next = p2->next;
23:
24: return p2;
25: }
7.從單鏈表中刪除指定的中間結點
實現:
將指定結點的后繼的值賦值給指定結點,然后刪除其后繼即可。
1: void DeleteMidNode(Node *del)
2: {
3: if (!del) {
4: return;
5: }
6:
7: Node *next = del->next;
8: if (next) {
9: del->data= next->data;
10: del->next= next->next;
11: free(next);
12: }
13: }
8.在單鏈表的指定結點前插入一個結點
實現:
將結點插入到指定結點后,然后交換兩節點的值即可。
1: int InsertBeforeNode(Node *node, Node *insert)
2: {
3: if (!node || !insert) {
4: return -1;
5: }
6:
7: Node temp = *node;
8: node->data = insert->data;
9: node->next= insert;
10: *insert = temp;
11:
12: return 0;
13: }