问题描述:将一个单链表逆序排列,逆序不使用额外的辅助空间。
方法:
先让两个指针i , j 指向链表开头的两个相邻的结点,用递归方法,然后不断使 i = j, j = j->next, 从而让这两个指针一直向链表的尾部方向滑动。直到当j->next == NULL时,说明递归到了最深一层,链表的尾结点就是当前的 j 所指向的结点;
然后就是往回递归了,每返回一层,都让 j 指向它前面的结点 i ,即令j->next = i,形成链表的反转。而前面的 结点 i 的下一个结点也不再是 j 了,先让它的next指针的值为空。一直往回重复这两步,直到 i 指向原来的头结点head,即返回到第一层。这样链表就完成了逆序。
/*
Name: Reverse list link
Author: leeoo
Date: 11/03/19 01:10
Description: 把链表各结点的指向调转
*/
#include<stdio.h>
#include<stdlib.h>
/* 链表*/
typedef struct LNode{
int data;
struct LNode *next;
}Link;
/*链表头结点初始化*/
void init_link(Link* &head){
head = (Link*)malloc(sizeof(Link));//给新定义的头结点分配内存空间
head->data = 0;
head->next = NULL;
}
/*给链表赋值*/
void assignment(Link *L , int N[], int n){
for(int i = 0; i < n; i++){
Link *p;
p = (Link *)malloc(sizeof(Link));
p->data = N[i];
L->next = p;
L = p;
}
L->next = NULL;
}
/* 将一个链表逆序排列*/
void reverse(Link *&L, Link *&p, Link *&q, Link *&newhead){
static int end = 1; //用来找链表尾结点用的标志
Link *i = p, *j = q; //i指向p, j指向q,它们是指向两个相邻的结点
if(j->next != NULL){
reverse(L, j, j->next, newhead); //递归 ,使指针i = j, j = j->next, 使两个指针一直向链表的尾部方向移动
}
if(end == 1){
newhead = j; //当j->next == NULL,说明递归到了最深一层,链表的尾结点就是当前的j所指向的结点
end = -1; //找到尾结点后,修改标志 ,使得后面递归回来时不再改变newhead的值
}
j->next = i; //往回递归,每返回一层,都让 j 指向它前面的结点 i ,形成链表的反转
// printf("j: %d ",j->data);
i->next = NULL; //而前面的 i 的下一个结点就不再是 j 了,先让它的值为空
// printf("i: %d\n",i->data);
}
int main(){
Link *head; //链栈的头结点
Link *newhead = head; //newhead后面用来指向反转链表后的头结点
int Id[10] = {1,2,3,4,5,6,7,8,9};
init_link(head); //初始化链栈
assignment(head, Id, 9); //赋初值
Link *i; //先打印出原来的链表
i = head;
while(i!=NULL){
printf("%d ",i->data);
i = i->next;
}
printf("\n");
reverse(head, head, head->next, newhead); //将链表顺序反转
i = newhead; //打印出反转的链表
while(i!= NULL){
printf("%d ",i->data);
i = i->next;
}
printf("\n");
return 0;
}