1、找中间结点方法:定义两个指针pcur、ppre,开始时同时指向L->next,之后向后遍历,让pcur每走两步,ppre走一步,当pcur为空时,结束循环,此时ppre指向中间结点
2、L2原地逆置方法:定义三个指针r、s、t,使它们分别指向链表开始的三个结点,先让s->next=r,则a2指向a1,之后r、s、t依次后移,依次完成a3指向a2,a4指向a3,再后移发现t为空,此时结束循环,但最后的a5还没指向,所以在循环外要再执行依次s->next=r。
最后需要让L2->next->next=NULL(此时L2->next->next拿到的是a1),因为原有链表的头结点变成最后一个结点,需要让最后一个结点的next为NULL,再让L2->next=s,使s成为逆置后的链表的第一个结点。
3、轮流合并方法:定义三个指针pcur、p、q,让pcur始终指向合并后的新链表的尾部,初始化为p=L->next,让p始终指向L待插入的结点,初始化为p=L->next,q始终指向L2待插入的结点,初始化为q=L2->next
循环到最后,L或L2总会有一个链表剩一个结点没放进去,此时判断p不为NULL或者q不为NULL,再将p或q放进去即可
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
void list_tail_insert(LinkList &L)
{
L=(LinkList)malloc(sizeof(LNode));
ElemType x;
L->next=NULL;
scanf("%d",&x);
LNode *s,*r;
r=L;
while (x!=9999)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
}
//找到中间结点
void find_middle(LinkList L,LinkList &L2)
{
L2=(LinkList)malloc(sizeof(LNode));
LinkList pcur,ppre;//双指针法遍历链表
ppre=pcur=L->next;
while(pcur)
{
pcur=pcur->next;
if(NULL==pcur)//让pcur先走一步,看看是否为空,不然如果为空再继续走,程序会崩溃
{
break;
}
pcur=pcur->next;
if(NULL==pcur)//为了使得偶数个,ppre依然指向a1,a2,到a6中的a3结点
{
break;
}
ppre=ppre->next;
}
L2->next=ppre->next;//由L2头结点指向后面一半链表
ppre->next=NULL;//前面一半链表的最后一个结点,next要为NULL
}
//逆置
void reverse(LinkList L2)//逆转时不会改变L2,不用带引用
{
LinkList r,s,t;
r=L2->next;
if(NULL==r)
{
return;//链表中没有结点,只有头结点
}
s=r->next;
if(NULL==s)
{
return;//链表只有一个结点
}
t=s->next;
while (t)
{
s->next=r;//链表开始逆置
r=s;
s=t;
t=t->next;
}
s->next=r;
L2->next->next=NULL;//逆置后,链表第一个结点的next要为NULL
L2->next=s;//s为链表的第一个结点,L2指向它
}
//合并链表
void merge(LinkList L,LinkList L2)
{
LinkList pcur,p,q;
pcur=L->next;//pcur始终指向组合后链表的链表尾,pcur一开始指向a1
p=pcur->next;//这里p获取到的是L->next->next,p一开始指向a2
q=L2->next;//q指向L2第一个结点
while(p!=NULL&&q!=NULL)
{
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;
}
}
void print_list(LinkList L)
{
L=L->next;
while(L!=NULL)
{
printf("%d",L->data);
L=L->next;
if(L)
{
printf(" ");
}
}
printf("\n");
}
int main()
{
LinkList L;
list_tail_insert(L);
print_list(L);
LinkList L2=NULL;
find_middle(L,L2);//寻找中间结点,并返回第二条链表,只有一个结点时,L2中是没有结点的
printf("-----------------------\n");
print_list(L);
print_list(L2);
printf("-----------------------\n");
reverse(L2);
print_list((L2));
printf("-----------------------\n");
merge(L,L2);
free(L2);
print_list(L);
return 0;
}
运行结果:头插法创建链表
找中间结点后分成两个链表
逆序后的L2
最终插入结果