【补充】递归实现单向链表逆转

同样是单向链表的逆转,换了个方法实现。分别用递推和递归的方式实现,但感觉在这里递归和递推效率上相差不多,要是链表太长的话,递归有可能会引发段错误或者栈溢出(进去就出不来了)。思路比昨天清晰多了,但没事去逆转一个单向链表,还真是有点蛋疼的感觉。


#include <stdio.h>
#include <stdlib.h>


//定义节点的数据类型
typedef struct _node
{
	int data;
	//指向下一个节点
	struct _node* p_next;
}Node;

//定义单链表的数据类型
typedef struct _list
{
	//头指针,记录第一个元素
	Node* p_head;
	int size;
}List;

//创建一个链表
void create_list(List** pp_list)
{
	*pp_list = (List*)malloc(sizeof(List));
	(*pp_list)->p_head = NULL;
	(*pp_list)->size = 0;
}

//创建一个节点
Node* create_node(int data)
{
	Node* p_node = (Node*)malloc(sizeof(Node));
	p_node->p_next = NULL;
	p_node->data = data;
}

//向链表头节点位置插入新节点
void push_head(List* p_list, int data)
{
	//创建新节点
	Node *p_node = create_node(data);
	
	//将新节点插入到头节点位置
	p_node->p_next = p_list->p_head;
	p_list->p_head = p_node;
	p_list->size++;
}
//链表逆序,使用递推实现
void reverse_list(List* p_list)
{
	if (p_list->size <= 1)
	{
		return;
	}
	//提供三个指针分吧记录前三个节点的地址
	Node* p1 = p_list->p_head;
	Node* p2 = p1->p_next;
	Node* p3 = p2->p_next;
	//将原来的头节点的next置为NULL
	p1->p_next = NULL;
	while(NULL != p3)
	{
		//让第二个节点的next指向第一个节点
		p2->p_next = p1;
		//p1指向p2指向的节点
		p1 = p2;
		//p2指向p3指向的节点
		p2 = p3;
		//p3指向下一个节点
		p3 = p3->p_next;
	}
	//特殊处理最后两个节点
	p2->p_next = p1;
	p_list->p_head = p2;
}
//链表逆序,使用递归实现
void reverse_list2(List* p_list)
{
	//判断是否需要逆序
	if (p_list->size <= 1);
	{
		return;
	}
	//头节点指向逆转函数的返回值
	p_list->p_head = reverse_node(&p_list->p_head);
}

//链表逆序的递归操作,返回逆转钱链表的最后一个节点
Node* reverse_node(Node** pp_node)
{
	//找到尾节点,跳出递归
	if (NULL == (*pp_node)->p_next)
	{
		return;
	}
	//准备2个指针,分别记录当前指针,和当前指针的next
	Node *p1 = *pp_node;
	Node *p2 = (*pp_node)->p_next;
	//进入递归
	reverse_node(&(*pp_node)->p_next);
	//递归结束后,p1和p2已经成为当前指针的前面两个指针了
	(*pp_node)->p_next = p2;
	p2->p_next = p1;
	return *pp_node;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值