链表反转和找出链表中间节点

typedef struct _list_node
{
    double
 keyVal;
    struct _list_node *
next;
 }ListNode;

Q1 单链表的反序


  ListNode* reverseList(ListNode* head)
 {
     ListNode *p1, *p2 , *p3;
     //链表为空,或是单结点链表直接返回头结点
     if (head == NULL || head->next == NULL)
      {
          return head;
      }
      p1 = head;
     p2 = head->next;
     while (p2 != NULL)
     {
         p3 = p2->next;
         p2->next = p1;
         p1 = p2;
         p2 = p3;
     }
     head->next = NULL;
     head = p1;
 
     return head;
 }

Q2 找出链表的中间元素


 1 ListNode* find_midlist(ListNode* head)
 2 
{
 3     ListNode *p1, *
p2;
 4 
    
 5     if (head == NULL || head->next ==
 NULL)
 6 
    {
 7         return
 head;
 8 
    }
 9     p1 = p2 =
 head;
10     while (1
)
11 
    {
12         if (p2->next != NULL && p2->next->next !=
 NULL)
13 
        {
14             p2 = p2->next->
next;
15             p1 = p1->
next;
16 
        }
17         else

18         {
19             break
;
20 
        }
21 
    }
22     return
 p1;
23 }

思路分析:

 链表的一个比较大的特点用一句广告语来说就是“不走回头路”,不能实现随机存取(random access)。如果我们想要找一个数组a的中间元素,直接a[len/2]就可以了,但是链表不行,因为只有a[len/2 - 1] 知道a[len/2]在哪儿,其他人不知道。因此,如果按照数组的做法依样画葫芦,要找到链表的中点,我们需要做两步(1)知道链表有多长(2)从头结点开始顺序遍历到链表长度的一半的位置。这就需要1.5n(n为链表的长度)的时间复杂度了。有没有更好的办法呢?有的。想法很简单:两个人赛跑,如果A的速度是B的两倍的话,当A到终点的时候,B应该刚到中点。这只需要遍历一遍链表就行了,还不用计算链表的长度。

 上面的代码就体现了这个想法。

原文地址:https://www.cnblogs.com/yitianke/p/3031646.html