史上最全的反转链表

史上最全的反转链表!!!

**震惊!!!**一个小小的反转链表,竟然有好几种方法,还要看好几篇文章,更要命的是观看需要money!!!!哎,气不过,我就给你整合到一起,我就写 保姆级别教程+源代码,纯干货,全免费,都公开!
放在电脑上就能整!!!!

开整:

/***********************************************************
*版权所有:© 2021.8.5 烽火编程(第八方面军)
*文件名称:递归解决翻转单链表
*内容摘要:递归 ,循环,三指针
*当前版本:1-1
*文件作者:帅子牛
*完成日期:2021.8.5
*修改记录:暂无
***********************************************************/

#include <stdio.h>
#include <malloc.h>
typedef struct list{
    
    
	int data;
	struct list* next;
}List,*list;	//这里不懂的话,可以翻我的 "单链表" 进一步了解 

list InitList(){
    
    //初始化有头结点的链表 
	list head = (list)malloc(sizeof(List));
	head->next = NULL;
	return head;
}
void CreatList(list head,int n){
    
    //头插法建立单链表 
	list s;
	int i;
	for(i=0;i<n;i++){
    
    
		s = (list)malloc(sizeof(List));
		scanf("%d",&s->data);
		s->next = head->next;
		head->next = s;
	}
	printf("单链表建立完毕\n"); 
}
/*反转链表的输出*/ 
int DisPlay_1(list head){
    
    	//代码反转后结构发生轻微变化,需要读者思考与原链表的不同之处 
	list s = head;
	if(head == NULL){
    
    
		return 0;
	}
	while(s->next != NULL){
    
    
		printf("%d ",s->data);
		s = s->next;
	}
	return 1;
}
/*递归输出单链表(我自码的,读者可自行递归探索是否正确)*/ 
int DisPlay(list head,list s){
    
     
	if(head == NULL || s == NULL){
    
    
		return 0;
	}else{
    
    
		printf("%d ",s->data);
		DisPlay(head,s->next);	
	}
}
/*
//一般单链表输出 
void DisPlay(list head){
	list s = head->next;
	while(s){
		printf("%d\t",s->data);
		s = s->next;
	}
	printf("\n");
}
*/

/*
	*三指针法,反转单链表
	*a,b,c三个指针分别指向三个位置
	*a和b指针用来反转两个结点
	*c指针指向下一个结点用来标记和前移 
*/ 
list reverList(list head){
    
    //单链表反转函数-1 
	list a,b,c; 
	a = head;
	b = a->next;
	c = b;
	a->next = NULL;
	while(b != NULL){
    
    
		c = c->next;
		b->next = a;
		a = b;
		b = c; 
	}
	return a;
}
/*
	*三指针法优化,但是他们大概的思路是一致的 
	*a,b,head三个指针分别指向三个位置
	*a和 head指针用来反转两个结点
	*b指针指向下一个结点用来标记和前移 
*/ 
list reverList_1(list head){
    
    //单链表反转函数-2
	list a=NULL,b=NULL;
	while(head != NULL){
    
    
		b = head->next;
		head->next = a;
		a = head;
		head = b;
	}
	return a;
}
//递归法
/*
	*按照之前的递归按要素走:寻找等价关系:想最简单的一种情况:即只有两个结点时之接进行翻转
	*那接下来该怎么如何把这两个结点翻转呢?其实就是如下 
	*p->next->next = p;原第二个指向第一个 ,第一个指向空 
	*p->next = NULL;	
	* 也就是说:reverList_2(list head)等价于reverList_2(head->next) 改变一下最后两个的结点就行
	*至此递归的等价关系就找了出来 
*/
list reverList_2(list head){
    
    
	list p;
	p = head;
	if(p->next == NULL || p == NULL){
    
    	//出口:当链表只有一个结点或者是空表的话之接返回就行 
		return head;
	}
	if(p->next->next == NULL){
    
    	//只有两个结点的情况之接翻转 
		head = p->next;
		p->next->next = p;
		p->next = NULL;	
	}else{
    
    
		head = reverList_2(p->next);
		/*超过两个的话,指针向后遍历,将最后两个翻转,
		翻转完了之后当前结点 和后一个结点可以看做是最后两个结点*/ 
		p->next->next = p;
		p->next = NULL;
	}
	return head;
}
int main() {
    
    
	list head = NULL;
	head = InitList();
	CreatList(head,5);
	printf("正常单链表的顺序为:"); 
	DisPlay(head,head->next);
	
//	printf("\n三指针法翻转后的单链表:");
//	list font = reverList(head);
//	DisPlay_1(font);
//	printf("\n三指针法(优化)翻转后的单链表:");
//	list font = reverList_1(head);
//	DisPlay_1(font);
	printf("\n递归翻转后的单链表:");
	list font = reverList_2(head);
	DisPlay_1(font);
	return 0;
}

结果演示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_46672781/article/details/119425369
今日推荐