王道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;
}
相关推荐
爱吃喵的鲤鱼1 分钟前
linux进程的状态之环境变量
linux·运维·服务器·开发语言·c++
DARLING Zero two♡27 分钟前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
7年老菜鸡28 分钟前
策略模式(C++)三分钟读懂
c++·qt·策略模式
Gu Gu Study30 分钟前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言
Ni-Guvara37 分钟前
函数对象笔记
c++·算法
似霰41 分钟前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder
芊寻(嵌入式)1 小时前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
獨枭1 小时前
C++ 项目中使用 .dll 和 .def 文件的操作指南
c++
霁月风1 小时前
设计模式——观察者模式
c++·观察者模式·设计模式
橘色的喵1 小时前
C++编程:避免因编译优化引发的多线程死锁问题
c++·多线程·memory·死锁·内存屏障·内存栅栏·memory barrier