今天在一本试题书上看到一些特别好的单链表面试题,大家都知道单链表容易在头节点处进行删除,在尾节点处进行插入,下面我们就来讨论一下这些面试题:

  (一)删除一个非尾节点

  题目要求的是要删除一个不是尾节点的节点,要删除一个节点我们首先得知道是那个链表,是哪个节点节点,找到并且删除它。所以我们设计的函数是这样的:

  1. void DelNotTailNode(SListNode* pos)
  2. {
  3. assert(pos);
  4. SListNode* del = pos->next;
  5. pos->data = del->data;
  6. pos->next = del->next;
  7. free(del);
  8. del = NULL;
  9. }

 其实实现起来也很简单,主要思想是删除pos位置的下一个节点,因为单链表只可以找到当前结点的下一个节点。

wKiom1cLABDQfsATAAAkqoxiUV8374.png

(二)找到单链表的中间节点:

  题目要求只遍历一次就找到这个中间节点,可见按照我们的常规思路,先遍历一遍计数节点的总个数,然后二遍遍历直接找到节点是不行的。这就用到了单链表一个重要的概念——快慢指针。定义两个指针slow和fast,slow指针每次往后走一个节点位置,fast指针每次往后走俩个节点位置,当fast指针走到尾节点时,slow指针刚刚好走到中间节点位置;

  1. SListNode* FindMidNode(SListNode* pHead)//pHead是链表的头节点
  2. {
  3. SListNode* fast = pHead;
  4. SListNode* slow = pHead;
  5. while (fast->next)
  6. {
  7. slow = slow->next;
  8. fast = fast->next;
  9. if (fast->next)
  10. {
  11. fast = fast->next;
  12. }
  13. else
  14. {
  15. break;
  16. }
  17. }
  18. return slow;
  19. }

利用快慢指针可以解决很多类似的问题,比如找到单链表的第N个节点,或者判断链表是否带环等等,下面会有列子。

(三)判断一个链表是否带环,若带返回环的入口点(较难)

  上面已经说过,通过快慢指针可以找到单链表中的任何节点,这也是通过验证的。那么原理上也可以判断链表是否带环:

  如果带环,快慢指针一定会在某个节点处相遇。(fast一直在环里转,总有一个时刻,slow追上fast,相遇)

  1. SListNode* WhetherRing(SListNode* pHead)//判断是否带环,若带,返回相遇节点
  2. {
  3. if (pHead == NULL||pHead->next == NULL)
  4. return NULL;
  5. SListNode* fast = pHead;
  6. SListNode* slow = pHead;
  7. while (fast)
  8. {
  9. slow = slow->next;
  10. fast = fast->next;
  11. if (fast)
  12. {
  13. fast = fast->next;
  14. }
  15. else
  16. {
  17. return NULL;//没有环
  18. }
  19. if (fast == slow)
  20. {
  21. return slow;//有环
  22. }
  23. }
  24. return NULL;
  25. }

 

wKioL1cLCqHj9J0ZAAAniQxmoSI321.png

  如果链表带环的话,我们就可以求出相遇的节点。然后从相遇节点处断开带环链表,一个指针从链表投节点处开始往后遍历,一个指针从断开处往后遍历,相遇节点处就是环的入口点

   

wKioL1cLCsSilsa_AAAWbXfqfZg674.png

  1. SListNode* GetEnterNode(SListNode*  pHead)//找到链表环入口节点在哪(重点)
  2. {
  3. SListNode* start = pHead;
  4. SListNode* tmp = WhetherRing(pHead);
  5. while (start != tmp)
  6. {
  7. start = start->next;
  8. tmp = tmp->next;
  9. }
  10. return start;
  11. }

 这就是单链表的一些面试经典题,我通过理解后和大家一起分享,希望对大家有些许帮助。