求单链表的中间节点

来源:互联网 发布:淘宝网导航条在线制作 编辑:程序博客网 时间:2024/04/27 14:08

            偶数个节点时返回中间两个节点的前一个

我们可以这样考虑,设想两个人跑步,一个人的速度是另外一个人的两倍,当速度快的人到达了终点,速度慢的人就在赛程的正中间。同样地,我们设置两个游动的指针,慢的指针移动步长为1,快的指针移动的步长为2。一开始都指向链表的头部,当遍历开始时,进行这样的操作:如果快的指针可以向前移动两步并且没有到达链表的尾部的话,快指针就向前移动2个节点,同时慢的指针向前移动1个节点;否则退出,返回慢指针。该算法的实现如下,注意区别链表长度为偶数和奇数的情况:

#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <iostream.h>struct ListNode{int data;ListNode* next;};void InitList(ListNode** head){*head = (ListNode*)malloc(sizeof(ListNode));(*head)->next = NULL;}void InsertList(ListNode* head,int d){assert(head!=NULL);ListNode* pNewNode = (ListNode*)malloc(sizeof(ListNode));pNewNode->data = d;pNewNode->next = head->next;head->next = pNewNode;}void PrintList(ListNode* head){if(head == NULL){return ;}ListNode* Next = head->next;while(Next!=NULL){cout<<Next->data<<endl;Next = Next->next;}}/*查找中间结点核心代码*/ListNode* FindMidFront(ListNode* head){if(NULL == head || NULL == head->next)        return head;    //ListNode* p1 = head;    //ListNode* p2 = head;/*因为我自己实现的链表,头结点没有放数据,所以要从下一个开始。如果,头结点有数据,则直接从头结点开始就可以。*/    ListNode* p1 = head->next;    ListNode* p2 = head->next;    while(NULL != p2->next && NULL != p2->next->next)    {        p1 = p1->next;        p2 = p2->next->next;//cout<<"p1->data="<<p1->data<<endl;仅仅是为了测试//cout<<"p2->data="<<p2->data<<endl;    }    return p1;}int main(){ListNode* pListHead = NULL;InitList(&pListHead);for(int i=8;i>=0;i--){InsertList(pListHead,i);}ListNode* mid= FindMidFront(pListHead);cout<<"链表中的元素为:"<<endl;PrintList(pListHead);cout<<"中间结间是"<<mid->data<<endl;return 0;}


           偶数个节点时返回中间两个节点的后一个

上面的算法中的循环需要稍微调整一下。前面的算法中,快指针p2每次都移动2步,而本问题中,我们需要改变下策略,变成:只要快指针p2能向前移动一步,那么快指针和慢指针就都同时向前移动一步,再看看快指针是否还能补上一步,如果能补上一步,那么就补上,然后进行下一轮循环,否则就表示到达了链表尾部,返回慢指针即可。实现如下

ListNode* FindMidAfter(ListNode* head){    if(NULL == head || NULL == head->next)        return head;    //ListNode* p1 = head;    //ListNode* p2 = head;ListNode* p1 = head->next;    ListNode* p2 = head->next;    while(NULL != p2->next)    {        p2 = p2->next;        p1 = p1->next;        if(NULL == p2->next)            return p1;        else            p2 = p2->next;    }    return p1;}