王道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;
}
相关推荐
evans在进步1 小时前
LeetCode 2 两数相加:链表模拟加法,Java 图解进位过程
java·leetcode·链表
Dr.kangder1 小时前
嵌入式总线设备解析——TTE总线应用与实践
开发语言·网络·算法·嵌入式·多任务·同步机制
-银雾鸢尾-1 小时前
C#中的多线程
开发语言·c#
yyy(十一月限定版)1 小时前
016【入门】双端队列
数据结构·c++
2401_858286112 小时前
OS82.【Linux】设计线程池
java·linux·运维·服务器·开发语言·算法·线程池
数据知道2 小时前
IDOR 不安全的直接对象引用:API 越权实战检测
java·开发语言·网络·安全·网络安全
c238562 小时前
# Mini OJ — 项目详解文档
开发语言·数据库·c++
疯狂打码的少年2 小时前
【数据结构】链表变体:双向链表与循环链表
数据结构·笔记·链表
2401_894915532 小时前
Geo 优化源码部署常见报错排查:连接失败、地图加载、地域词失效解决方案
服务器·开发语言·python·安全·php
c238562 小时前
C/C++每日一练20
c语言·开发语言·c++