考研数据结构(每日一题)day23

本文介绍了一种在考研数据结构中,利用单链表实现空间复杂度为O(1)的高效算法,通过找到链表中间节点,原地逆置后半部分并逐个合并节点,重新排列为(an, a1, an-1, a2, ...)的线性表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

考研数据结构(每日一题)

题目:设线性表L=(a1,a2,a3,…,an-2,an-1,an)采用带头结点的单链表保存,请设计一个空间复杂度为O(1)且时间上尽可能高效的算法,重新排列L中的各节点,得到线性表L’=(a1,an,a2,an-1,a3,an-2,…)

算法图解:

在这里插入图片描述

算法思想:

L’是由L取第一个元素,再取倒数第一个元素,以此类推,依次合并而成的。为了方便链表后半段取元素,需要先将L后半段原地逆置(如图红色方框部分),题目中要求空间复杂度为O(1),即不能用栈,否则每取最后一个结点都需要遍历一次链表。
算法详细步骤:
第一步:设置两个指针p、q,找出链表L的中间结点,指针p每次走一步,q每次走两步。当指针q到达链表尾部时,指针p刚好在链表的中间结点
第二步:将L的后半段结点原地逆置
第三步:从单链表前后两段中依次各取一个结点,按题目要求排列

完整代码:

typedef struct node{
    int data;
    struct node*next;
}NODE;
void Change_list(NODE *h){
    NODE *p,*q,*r,*s;     //初始化指针
    p = q = h;     //从头结点开始
    while(q -> next != NULL){     //寻找中间结点
        p = p -> next;    //p走一步
        q = q -> next;
        if(q -> next != NULL){
            q = q -> next;       //q走两步
        }
    }
    q = p -> next;      //p所指结点为中间结点,q为后半段链表的首结点
    p -> next = NULL;
    while(q != NULL){    //逆置链表后半段
        r = q -> next;
        q -> next = p -> next;
        p -> next = q;
        q = r;
    }
    s = h -> next;      //s指向前半段的第一个数据结点,也就是插入点
    q = p -> next;      //q指向后半段的第一个数据结点
    p -> next = NULL;
    while(q != NULL){    //将链表后半段的结点插入到指定位置
        r = q -> next;   //r指向后半段的下一个结点
        q -> next = s -> next;     //将q所指结点插入到s所指结点之后
        s -> next = q;
        s = q -> next;   //s指向前半段的下一个插入点
        q = r;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值