王道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,⋯) 。
#include <stdio.h>
#include <stdlib.h>#define END 33typedef 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指向后一半链表L2ppre->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为nullL->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;
}