寻找单链表的中间节点

思路:
(1)首先求解单链表的长度length,然后遍历 length / 2 的距离即可查到单链表的中间节点,但一般此种方法需要遍历两次链表,第一次遍历求解单链表的长度,第二次遍历根据索引获取中间节点。
(2)如果是双向链表,可以首尾并行,利用两个指针一个从头到尾,一个从尾到头,当两个指针相遇的时候,就找到中间元素。以此思想为基础,进一步思考,单链表也可以采用双指针的方式来实现中间节点的快速查找。但双指针的使用和双向链表不同,具体如下:
<1> 有2个指针同时从头开始遍历;
<2> 一个快指针一次走2步,一个慢指针一次走一步。
<3> 快指针先到链表尾部,而慢指针则恰好到达链表中部;
快指针到达链表尾部,当链表长度为奇数时,慢指针指向的就是链表中间节点。当链表长度为偶数时,慢指针指向的节点和慢指针指向节点的下一个节点都是链表的中间节点。

具体实现见代码:

#include <iostream>

typedef struct node
{
    int data;
    struct node *next;
} NODE;


NODE *create_end(int arr[], int len)
{
    NODE *head = (NODE *)malloc(sizeof(NODE *));
    head->next = NULL;
    NODE *end = head;


    for (int i = 0; i < len; i++) {
        NODE *p =  (NODE *)malloc(sizeof(NODE *)); // 也可用 new NODE();
        p->data = arr[i];

        end->next = p;
        end = p;
    }
    end->next = NULL;

    return head;
}

// 此方法适用于不带头节点的单链表的打印,对于带头节点的单链表要稍作处理。
void print(NODE *head)
{
    if (head == NULL) return;

    while (head != NULL) {
        printf("%d  ",head->data);
        head = head->next;
    }
}


// 寻找单链表的中间节点
// 当链表中有偶数个元素时,最中间的两个节点都可以算作中间节点;
// 但通过该方法查找到的是前面那个节点;如{123456},通过该方法查找到的中间节点是3。
NODE *searchMid1(NODE *head)
{
    NODE *temp = head;
    NODE *mid = head;

    while (head != NULL && head->next != NULL && head->next->next != NULL)
    {
        head = head->next->next;
        temp = temp->next;
        mid = temp;
    }

    return mid;
}


// 寻找单链表的中间节点(对searchMid1略作修改)
// 当链表中有偶数个元素时,最中间的两个节点都可以算作中间节点;
// 但通过该方法查找到的是后面那个节点;如{123456},通过该方法查找到的中间节点是4。
NODE *searchMid2(NODE *head)
{
    NODE *temp = head;
    NODE *mid = head;

    while (head != NULL && head->next != NULL)
    {
        head = head->next->next;
        temp = temp->next;
        mid = temp;
    }

    return mid;
}


// 寻找单链表的中间节点(length)
// 当链表中有偶数个元素时,最中间的两个节点都可以算作中间节点;
// 但通过该方法查找到的是后面那个节点;如{123456},通过该方法查找到的中间节点是4。
NODE *searchMid3(NODE *head,int len)
{

    NODE *p = NULL;
    for (int i = 0; i < len / 2; i++) {
        p = head->next;
        head= head->next;
    }

    return p;

}


int main(int argc, const char * argv[]) {

    int arr[] = {1,2,3,4,5,6,7,8};
    int len = sizeof(arr)/sizeof(int);
    NODE *head = create_end(arr, len);

    // 因为创建的链表是带头节点的,所以此处打印要稍作处理;
    NODE *first = head->next;
    print(first);
    printf("\n");

    NODE *p1 = searchMid1(head->next);
    printf("%d\n",p1->data);

    NODE *p2 = searchMid2(head->next);
    printf("%d\n",p2->data);

    NODE *p3 = searchMid3(head->next, len);
    printf("%d\n",p3->data);

    return 0;
}

输出如下:
这里写图片描述

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值