史上最全的反转链表

Posted 勇敢*牛牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了史上最全的反转链表相关的知识,希望对你有一定的参考价值。

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

**震惊!!!**一个小小的反转链表,竟然有好几种方法,还要看好几篇文章,更要命的是观看需要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;
}

结果演示:

以上是关于史上最全的反转链表的主要内容,如果未能解决你的问题,请参考以下文章

史上最全Spring面试71题与答案

史上最全Hashmap面试总结,51道附带答案,持续更新中...

史上最全Hashmap面试总结,51道附带答案,持续更新中...

C语言反转单向链表的代码

号称史上最全Java多线程与并发面试题总结—基础篇

javascript 代码技巧 —— 史上最全类型判断