c语言面试题重点整理·单链表操作


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 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值