王道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 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;
}