王道c语言-链表分为两半,逆置后一半,与前一半轮流合并

王道c语言-链表分为两半,逆置后一半,与前一半轮流合并

设线性表 L = ( a 1 , a 2 , a 3 , ⋯   , a n − 2 , a n − 1 , a n ) L=(a_1,a2,a3,\cdots,a_{n-2},a_{n-1},a_{n}) L=(a1,a2,a3,⋯,an−2,an−1,an) 采用带头结点的单链表保存,设计一个空间复杂度为 O ( 1 ) O(1) O(1)且时间上尽可能高效的算法,重新排列 L 中的各结点,

得到线性表 L ′ = ( a 1 , a n , a 2 , a n − 1 , a 3 , a n − 2 , ⋯   ) L'=(a_1,a_n,a_2,a_{n-1},a_3,a_{n-2},\cdots) L′=(a1,an,a2,an−1,a3,an−2,⋯) 。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

#define END 33

typedef int ElemType;

typedef struct LNote {
    ElemType data;
    struct LNote *next;
} LNote, *LinkList;

void list_tail_insert(LinkList &L) {
    ElemType x;
    L = (LinkList) malloc(sizeof(LNote));
    L->next = NULL;
    scanf("%d", &x);
    LinkList s, r = L;
    while (x != END) {
        s = (LinkList) malloc(sizeof(LNote));
        s->data = x;
        r->next = s;
        r = s;
        scanf("%d", &x);
    }
    r->next = NULL;
}

void print_list(LinkList L) {
    L = L->next;
    while (L) {
        printf("%d   ", L->data);
        L = L->next;
    }
    printf("\n");
}

//双指针法遍历链表,找到链表中的中间结点
void find_middle(LinkList L, LinkList &L2) {
    L2 = (LinkList) malloc(sizeof(LNote));
    LinkList ppre, pcur; //pcur走两步,ppre走一步
    ppre = pcur = L->next;
    while (pcur) {
        pcur = pcur->next;//pcur=pcur->next->next;这种写法错误,当pcur->next=NULL,出错
        if (pcur == NULL || pcur->next == NULL) {
            break;
        }
        pcur = pcur->next;
        ppre = ppre->next;
    }
    L2->next = ppre->next; //L2指向后一半链表L2
    ppre->next = NULL;  //前一半链表在中间结点结束,指向NULL
}

//逆置L2
void reverse(LinkList &L) {
    LinkList r, s, t;
    r = L->next;
    if (r == NULL || r->next == NULL) { // L为空或只有一个结点,翻转失败
        return;
    }
    s = r->next;
    t = s->next;
    while (t) {
        s->next = r; //开始逆置
        r = s;
        s = t;
        t=t->next;
    }
    s->next = r;
    L->next->next=NULL;//原第一个结点的next为null
    L->next=s;
}

//将L与L2链表结点,轮流放入合并为新结点
void merge(LinkList L,LinkList L2){
    LinkList p,q,pcur;
    p=L->next; //始终指向L1待处理结点
    p=p->next;
    q=L2->next; //始终指向L2待处理结点
    pcur=L->next;//始终指向组合后链表的最后一个结点

    while (p&&q){ //原列表中至少有三个结点
        pcur->next=q;
        q=q->next;
        pcur=pcur->next;

        pcur->next=p;
        p=p->next;
        pcur=pcur->next;
    }
    if(p!=NULL){
        pcur->next=p;
    }
    if(q!=NULL){
        pcur->next=q;
    }
}
int main() {
    LinkList L;//链表头,是结构体指针类型
    LinkList L2 = NULL;//寻找中间结点,并返回第二条链表;加不加NULL都行
    LinkList search;//用来存储拿到的某一个节点

    list_tail_insert(L);
    printf("------L initialize is-------------------\n");
    print_list(L);

    find_middle(L, L2); //初试试卷只要写明下面三个子函数就行,main上面那几行可不写
    printf("------L1 L2 is-------------------\n");
    print_list(L);
    print_list(L2);

    reverse(L2);
    printf("------ L2 reverse is-------------------\n");
    print_list(L2);

    merge(L,L2);
    printf("------ L merge is-------------------\n");
    print_list(L);
    free(L2);
    return 0;
}
相关推荐
茉莉玫瑰花茶几秒前
GO [ 内存与变量逃逸分析 ]
开发语言·后端·golang
凉茶钱8 分钟前
list:哨兵节点,const_iterator 和 const iterator的区别与迭代器失效
数据结构·c++·list
沫璃染墨17 分钟前
从零入门计算机网络系列(六):TCP套接字编程实战——从listen监听到客户端与服务器通信
linux·服务器·c++·tcp/ip·计算机网络·tcp
lhh_qrsly23 分钟前
OTA 加密完整方案(嵌入式 IoT 常用)
开发语言·物联网·php
Nontee30 分钟前
Quartz 新手入门:定时任务的两个承诺
开发语言·windows·python
\光辉岁月/1 小时前
2.异常类
java·开发语言·异常类
淡海水1 小时前
05-03-源码-Boehm GC分配与碎片管理
开发语言·算法·unity·c#·游戏引擎·gc
努力实干1 小时前
C++ 面向对象与工程架构
开发语言·c++·架构
代钦塔拉1 小时前
【C++/Qt 进阶】设计模式系列(6):桥接模式——把“两个独立变化的维度“拆开
c++·qt·设计模式
十年Java程序媛1 小时前
JVM 基础与 GC 垃圾回收详解|可达性分析、分代模型、垃圾收集器、STW
java·开发语言·jvm·spring boot·后端·面试