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