1. 求单链表中结点的个数
// 求单链表中结点的个数
2 unsigned int GetListLength(ListNode * pHead)
3 {
4 if(pHead == NULL)
5 return 0;
6
7 unsigned int nLength = 0;
8 ListNode * pCurrent = pHead;
9 while(pCurrent != NULL)
10 {
11 nLength++;
12 pCurrent = pCurrent->m_pNext;
13 }
14 return nLength;
15 }
2. 将单链表反转
1 // 反转单链表
2 ListNode * ReverseList(ListNode * pHead)
3 {
4 // 如果链表为空或只有一个结点,无需反转,直接返回原链表头指针
5 if(pHead == NULL || pHead->m_pNext == NULL)
6 return pHead;
7
8 ListNode * pReversedHead = NULL; // 反转后的新链表头指针,初始为NULL
9 ListNode * pCurrent = pHead;
10 while(pCurrent != NULL)
11 {
12 ListNode * pTemp = pCurrent;
13 pCurrent = pCurrent->m_pNext;
14 pTemp->m_pNext = pReversedHead; // 将当前结点摘下,插入新链表的最前端
15 pReversedHead = pTemp;
16 }
17 return pReversedHead;
18 }
3. 查找单链表中的倒数第K个结点(k > 0)
1 // 查找单链表中倒数第K个结点
2 ListNode * RGetKthNode(ListNode * pHead, unsigned int k) // 函数名前面的R代表反向
3 {
4 if(k == 0 || pHead == NULL) // 这里k的计数是从1开始的,若k为0或链表为空返回NULL
5 return NULL;
6
7 ListNode * pAhead = pHead;
8 ListNode * pBehind = pHead;
9 while(k > 1 && pAhead != NULL) // 前面的指针先走到正向第k个结点
10 {
11 pAhead = pAhead->m_pNext;
12 k--;
13 }
14 if(k > 1) // 结点个数小于k,返回NULL
15 return NULL;
16 while(pAhead->m_pNext != NULL) // 前后两个指针一起向前走,直到前面的指针指向最后一个结点
17 {
18 pBehind = pBehind->m_pNext;
19 pAhead = pAhead->m_pNext;
20 }
21 return pBehind; // 后面的指针所指结点就是倒数第k个结点
22 }
4. 查找单链表的中间结点
// 获取单链表中间结点,若链表长度为n(n>0),则返回第n/2+1个结点
2 ListNode * GetMiddleNode(ListNode * pHead)
3 {
4 if(pHead == NULL || pHead->m_pNext == NULL) // 链表为空或只有一个结点,返回头指针
5 return pHead;
6
7 ListNode * pAhead = pHead;
8 ListNode * pBehind = pHead;
9 while(pAhead->m_pNext != NULL) // 前面指针每次走两步,直到指向最后一个结点,后面指针每次走一步
10 {
11 pAhead = pAhead->m_pNext;
12 pBehind = pBehind->m_pNext;
13 if(pAhead->m_pNext != NULL)
14 pAhead = pAhead->m_pNext;
15 }
16 return pBehind; // 后面的指针所指结点即为中间结点
17 }
5. 从尾到头打印单链表
1 // 从尾到头打印链表,使用栈
2 void RPrintList(ListNode * pHead)
3 {
4 std::stack<ListNode *> s;
5 ListNode * pNode = pHead;
6 while(pNode != NULL)
7 {
8 s.push(pNode);
9 pNode = pNode->m_pNext;
10 }
11 while(!s.empty())
12 {
13 pNode = s.top();
14 printf("%d\t", pNode->m_nKey);
15 s.pop();
16 }
17 }
6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
// 合并两个有序链表
2 ListNode * MergeSortedList(ListNode * pHead1, ListNode * pHead2)
3 {
4 if(pHead1 == NULL)
5 return pHead2;
6 if(pHead2 == NULL)
7 return pHead1;
8 ListNode * pHeadMerged = NULL;
9 if(pHead1->m_nKey < pHead2->m_nKey)
10 {
11 pHeadMerged = pHead1;
12 pHeadMerged->m_pNext = NULL;
13 pHead1 = pHead1->m_pNext;
14 }
15 else
16 {
17 pHeadMerged = pHead2;
18 pHeadMerged->m_pNext = NULL;
19 pHead2 = pHead2->m_pNext;
20 }
21 ListNode * pTemp = pHeadMerged;
22 while(pHead1 != NULL && pHead2 != NULL)
23 {
24 if(pHead1->m_nKey < pHead2->m_nKey)
25 {
26 pTemp->m_pNext = pHead1;
27 pHead1 = pHead1->m_pNext;
28 pTemp = pTemp->m_pNext;
29 pTemp->m_pNext = NULL;
30 }
31 else
32 {
33 pTemp->m_pNext = pHead2;
34 pHead2 = pHead2->m_pNext;
35 pTemp = pTemp->m_pNext;
36 pTemp->m_pNext = NULL;
37 }
38 }
39 if(pHead1 != NULL)
40 pTemp->m_pNext = pHead1;
41 else if(pHead2 != NULL)
42 pTemp->m_pNext = pHead2;
43 return pHeadMerged;
44 }
7. 判断一个单链表中是否有环
bool HasCircle(ListNode * pHead)
2 {
3 ListNode * pFast = pHead; // 快指针每次前进两步
4 ListNode * pSlow = pHead; // 慢指针每次前进一步
5 while(pFast != NULL && pFast->m_pNext != NULL)
6 {
7 pFast = pFast->m_pNext->m_pNext;
8 pSlow = pSlow->m_pNext;
9 if(pSlow == pFast) // 相遇,存在环
10 return true;
11 }
12 return false;
13 }
8. 判断两个单链表是否相交
bool IsIntersected(ListNode * pHead1, ListNode * pHead2)
2 {
3 if(pHead1 == NULL || pHead2 == NULL)
4 return false;
5
6 ListNode * pTail1 = pHead1;
7 while(pTail1->m_pNext != NULL)
8 pTail1 = pTail1->m_pNext;
9
10 ListNode * pTail2 = pHead2;
11 while(pTail2->m_pNext != NULL)
12 pTail2 = pTail2->m_pNext;
13 return pTail1 == pTail2;
14 }
9. 求两个单链表相交的第一个节点
ListNode* GetFirstCommonNode(ListNode * pHead1, ListNode * pHead2)
2 {
3 if(pHead1 == NULL || pHead2 == NULL)
4 return NULL;
5
6 int len1 = 1;
7 ListNode * pTail1 = pHead1;
8 while(pTail1->m_pNext != NULL)
9 {
10 pTail1 = pTail1->m_pNext;
11 len1++;
12 }
13
14 int len2 = 1;
15 ListNode * pTail2 = pHead2;
16 while(pTail2->m_pNext != NULL)
17 {
18 pTail2 = pTail2->m_pNext;
19 len2++;
20 }
21
22 if(pTail1 != pTail2) // 不相交直接返回NULL
23 return NULL;
24
25 ListNode * pNode1 = pHead1;
26 ListNode * pNode2 = pHead2;
27 // 先对齐两个链表的当前结点,使之到尾节点的距离相等
28 if(len1 > len2)
29 {
30 int k = len1 - len2;
31 while(k--)
32 pNode1 = pNode1->m_pNext;
33 }
34 else
35 {
36 int k = len2 - len1;
37 while(k--)
38 pNode2 = pNode2->m_pNext;
39 }
40 while(pNode1 != pNode2)
41 {
42 pNode1 = pNode1->m_pNext;
43 pNode2 = pNode2->m_pNext;
44 }
45 return pNode1;
46 }
10. 已知一个单链表中存在环,求进入环中的第一个节点
ListNode* GetFirstNodeInCircle(ListNode * pHead)
2 {
3 if(pHead == NULL || pHead->m_pNext == NULL)
4 return NULL;
5
6 ListNode * pFast = pHead;
7 ListNode * pSlow = pHead;
8 while(pFast != NULL && pFast->m_pNext != NULL)
9 {
10 pSlow = pSlow->m_pNext;
11 pFast = pFast->m_pNext->m_pNext;
12 if(pSlow == pFast)
13 break;
14 }
15 if(pFast == NULL || pFast->m_pNext == NULL)
16 return NULL;
17
18 // 将环中的此节点作为假设的尾节点,将它变成两个单链表相交问题
19 ListNode * pAssumedTail = pSlow;
20 ListNode * pHead1 = pHead;
21 ListNode * pHead2 = pAssumedTail->m_pNext;
22
23 ListNode * pNode1, * pNode2;
24 int len1 = 1;
25 ListNode * pNode1 = pHead1;
26 while(pNode1 != pAssumedTail)
27 {
28 pNode1 = pNode1->m_pNext;
29 len1++;
30 }
31
32 int len2 = 1;
33 ListNode * pNode2 = pHead2;
34 while(pNode2 != pAssumedTail)
35 {
36 pNode2 = pNode2->m_pNext;
37 len2++;
38 }
39
40 pNode1 = pHead1;
41 pNode2 = pHead2;
42 // 先对齐两个链表的当前结点,使之到尾节点的距离相等
43 if(len1 > len2)
44 {
45 int k = len1 - len2;
46 while(k--)
47 pNode1 = pNode1->m_pNext;
48 }
49 else
50 {
51 int k = len2 - len1;
52 while(k--)
53 pNode2 = pNode2->m_pNext;
54 }
55 while(pNode1 != pNode2)
56 {
57 pNode1 = pNode1->m_pNext;
58 pNode2 = pNode2->m_pNext;
59 }
60 return pNode1;
61 }
11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted
void Delete(ListNode * pHead, ListNode * pToBeDeleted)
2 {
3 if(pToBeDeleted == NULL)
4 return;
5 if(pToBeDeleted->m_pNext != NULL)
6 {
7 pToBeDeleted->m_nKey = pToBeDeleted->m_pNext->m_nKey; // 将下一个节点的数据复制到本节点,然后删除下一个节点
8 ListNode * temp = pToBeDeleted->m_pNext;
9 pToBeDeleted->m_pNext = pToBeDeleted->m_pNext->m_pNext;
10 delete temp;
11 }
12 else // 要删除的是最后一个节点
13 {
14 if(pHead == pToBeDeleted) // 链表中只有一个节点的情况
15 {
16 pHead = NULL;
17 delete pToBeDeleted;
18 }
19 else
20 {
21 ListNode * pNode = pHead;
22 while(pNode->m_pNext != pToBeDeleted) // 找到倒数第二个节点
23 pNode = pNode->m_pNext;
24 pNode->m_pNext = NULL;
25 delete pToBeDeleted;
26 }
27 }
28 }