逆置单链表——递归与非递归

本文详细介绍了单链表逆置的两种实现方法:非递归和递归。非递归方式通过创建新链表并使用头插法完成逆置;递归方式则通过不断缩小链表范围,将节点逐个添加到已逆置部分。文章提供了完整的代码实现及运行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

单链表的逆置图解
单链表逆置图解

方式一:非递归
原理

非递归逆置单链表的本质是创建一个新的链表,遍历原先的链表,利用头插法将节点插入新的链表当中去。

图解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现代码
//链表节点定义
typedef struct link_list{
	int data;
	struct link_list *next;
}singel_link_t;

/*********************************************************************
 * @fn      reversion_head_insert
 *
 * @brief   非递归的方式创建逆置链表 
 *
 * @param   link_head为需要逆置的链表表头 
 *
 * @return  返回逆置链表的头节点 
 */
singel_link_t *reversion_head_insert(singel_link_t *link_head)
{
	singel_link_t *reversion_head=NULL,*node=NULL;
	
	//参数判断
	if(link_head==NULL)
	{
		return NULL;
	}
	
	//遍历整个链表
	while(link_head!=NULL)
	{
		node       = (singel_link_t *)malloc(sizeof(singel_link_t));
		node->data = link_head->data;
		
		if(reversion_head==NULL)//首次添加节点 
		{
			reversion_head = node;
			node->next     = NULL;
		}
		else
		{
			//头插法插入节点
			node->next     = reversion_head;
			reversion_head = node;
		}
		
		link_head = link_head->next;
	}
	
	return reversion_head;
}
方式二:递归
原理

递归的方式是将链表的范围进行缩小,分为已逆置和未逆置两部分,已逆置部分可以看成一个整体,从未逆置的部分中拿出节点,添加到已逆置的部分中去,直至全部逆置完毕。

图解

在这里插入图片描述
将头指针递归到最后一个节点,当头指针在最后一个节点时为递归出口,返回上一层递归

在这里插入图片描述
倒数第二层递归,进行逆置
在这里插入图片描述
逆置过程

node       = head->next;//得到下一个节点
node->next = head;//逆置
head->     = NULL;//置空

在这里插入图片描述
返回倒数第三层递归
在这里插入图片描述
第二个节点逆置
在这里插入图片描述
返回倒数第四层递归

在这里插入图片描述
最后一个节点进行逆置
在这里插入图片描述

实现代码
//链表节点定义
typedef struct link_list{
	int data;
	struct link_list *next;
}singel_link_t;

/*********************************************************************
 * @fn      reversion_recursion
 *
 * @brief   递归的方式创建逆置链表 
 *
 * @param   link_head为需要逆置的链表表头 
 *
 * @return  返回逆置链表的头节点 
 */
singel_link_t *reversion_recursion(singel_link_t *link_head)
{
	singel_link_t *node,*rlink_head;
	
	if(link_head==NULL||link_head->next==NULL)
	{
		return link_head;
	}
	
	rlink_head = reversion_recursion(link_head->next);
	node            = link_head->next;//保存下一个节点 
	node->next      = link_head;//下一个节点的next指向当前节点
	link_head->next = NULL; 
	
	return rlink_head;
}
完整实现
代码
#include <stdio.h>
#include <stdlib.h>

typedef struct link_list{
	int data;
	struct link_list *next;
}singel_link_t;

/*********************************************************************
 * @fn      create_link
 *
 * @brief   创建链表 
 *
 * @param   n为链表长度 
 *
 * @return  返回创建链表的头节点 
 */
singel_link_t *create_link(int n)
{
	int i;
	singel_link_t *link_head=NULL,*node=NULL,*tail=NULL;
	
	for(i=0; i<n; ++i)
	{
		node       = (singel_link_t *)malloc(sizeof(singel_link_t));
		node->data = i;
		
		if(i==0)//首次添加节点 
		{
			link_head  = node;
			tail       = node;
			node->next = NULL; 	
		}
		else
		{
			node->next = tail->next;
			tail->next = node;
			tail       = node;
		}
	}
	
	return link_head;
}

/*********************************************************************
 * @fn      reversion_head_insert
 *
 * @brief   非递归的方式创建逆置链表 
 *
 * @param   link_head为需要逆置的链表表头 
 *
 * @return  返回逆置链表的头节点 
 */
singel_link_t *reversion_head_insert(singel_link_t *link_head)
{
	singel_link_t *reversion_head=NULL,*node=NULL;
	
	if(link_head==NULL)
	{
		return NULL;
	}
	
	while(link_head!=NULL)
	{
		node       = (singel_link_t *)malloc(sizeof(singel_link_t));
		node->data = link_head->data;
		
		if(reversion_head==NULL)//首次添加节点 
		{
			reversion_head = node;
			node->next     = NULL;
		}
		else
		{
			node->next     = reversion_head;
			reversion_head = node;
		}
		
		link_head = link_head->next;
	}
	
	return reversion_head;
}

/*********************************************************************
 * @fn      reversion_recursion
 *
 * @brief   递归的方式创建逆置链表 
 *
 * @param   link_head为需要逆置的链表表头 
 *
 * @return  返回逆置链表的头节点 
 */
singel_link_t *reversion_recursion(singel_link_t *link_head)
{
	singel_link_t *node,*rlink_head;
	
	if(link_head==NULL||link_head->next==NULL)
	{
		return link_head;
	}
	
	rlink_head = reversion_recursion(link_head->next);
	node            = link_head->next;//保存下一个节点 
	node->next      = link_head;//下一个节点的next指向当前节点
	link_head->next = NULL; 
	
	return rlink_head;
}

/*********************************************************************
 * @fn      del_singel_link
 *
 * @brief   销毁链表 
 *
 * @param   link_head为需要销毁的链表表头 
 *
 * @return  none 
 */
void del_singel_link(singel_link_t *link_head)
{
	singel_link_t *node=link_head;
	
	while(link_head!=NULL)
	{
		node      = link_head->next;
		free(link_head);
		link_head = node;
	}
}

/*********************************************************************
 * @fn      print_single_link
 *
 * @brief   输出一条链表 
 *
 * @param   link_head为需要输出的链表表头 
 *
 * @return  none 
 */
void print_singel_link(singel_link_t *link_head)
{
	while(link_head!=NULL)
	{
		printf("%d", link_head->data);
		if(link_head->next!=NULL)
		{
			printf("->");
		}
		else
		{
			printf("\n");
		}
		
		link_head = link_head->next;
	}
}

int main()
{	
	int n;
	singel_link_t *link_head=NULL,*rlink_head=NULL;
	
	scanf("%d", &n);
	
	//创建链表 
	link_head = create_link(n);
	print_singel_link(link_head);
	
	//非递归逆置 
	rlink_head=reversion_head_insert(link_head);
	print_singel_link(rlink_head);
	
	//递归逆置 
	link_head = reversion_recursion(link_head);
	print_singel_link(link_head);
	
	//销毁链表 
	del_singel_link(link_head);
	del_singel_link(rlink_head);
		
	return 0;
}
运行结果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值