基本思路:
该变换将L的后半部分倒插进前半部分,为了实现高效,可以将链表后半部分倒置后插入前半部分
- 找到后半部分的开头指针:设置两个指针slow和fast,slow增加一步,fast增加两步,则fast到达表尾时slow刚好为中间的位置。
- 倒置后半部分:可以用头插法或者设置prev,cur,next三个指针直接修改指针指向
使用c语言实现:
void main(){
pList head,tail,slow,fast;
buildListWithHead(&head,12);
slow=head->next;
fast=head->next;
while(fast->next->next){
slow=slow->next;
fast=fast->next->next;
}
transverse(head);
printf("\n中间的点: %d\n",slow->it);
//latter记录后半部分的开头指针,cur和follow为头插法倒置辅助指针
pList latter=slow->next,cur=latter, follow;
slow->next=NULL;
//头插法将后半部分的链表倒置
while(cur){
follow=cur->next;
cur->next=slow->next;
slow->next=cur;
cur=follow;
}
//倒置后需要latter为最后一个指针,需要重新指向为后半部分开头指针
latter=slow->next;
slow->next=NULL;
//遍历前半部分插入倒置后的后半部分
//cur重新指向head,使用tmp作为始终指向后半部分链表的辅助指针
cur=head->next;
follow=latter;
pList tmp=latter->next;
while(cur&&follow){
follow->next=cur->next;
cur->next=follow;
cur=cur->next->next;
follow=tmp;
if(tmp) tmp=tmp->next;//在follow和cur到达null前tmp已经到达NUll
}
//遍历转置后的链表
transverse(head);
}
其他辅助方法和结构体:
typedef struct LinkList
{
int it;
struct LinkList *next;
} LinkList, *pList;
//建立一个带有头结点的单链表,传入二级指针L,在函数中修改指针
void buildListWithHead(pList *L, int len)
{
*L = (pList)malloc(sizeof(LinkList));
pList p1 = *L;
for (int i = 0; i < len; ++i)
{
pList tmp = (pList)malloc(sizeof(LinkList));
tmp->it = rand() % 50;
tmp->next = NULL;
p1->next = tmp;
p1 = tmp;
}
}
//遍历链表
void transverse(pList head){
printf("遍历: ");
pList cur=head->next;
while(cur){
printf("%d,",cur->it);
cur=cur->next;
}
}