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: }