反转一个单链表。链表为无头结点、单向、不循环。(由于涉及到结构体,所以写不了完整的测试代码,下面展示的代码为LeetCode中写的代码)

//第一次尝试:
//本题我写了三种解题方法
//三种方法之外的方法:动态申请能装下链表数据的空间,然后将链表数据存放到数组中,在数组中将数据逆转,再存放到链表中,不过这种方法太麻烦了,浪费时间空间,不推荐
//方法一:头插法,再创建一个链表_head,然后从头遍历原链表head,再将head中的数据以头插法插入到_head链表中,这样就完成了链表的逆转
//方法二:三指针法,前提是至少有两个数据,设置三个结构体指针p1、p2、p3,一开始p1指向头结点,p2指向第二个节点,p3指向p2->next,此时对于我们来说,需要修改指向的是p2,
// p1是保留的上一个节点,p3是保留的下一个数据;在循环中,先判断p2是否为空,不为空就让p3=p2->next,然后修改p2指向为p1,更新p1、p2指向相对位置的下一个节点
//方法三:递归法,假设链表为:n1nk1nknk+1nm∅,现在需要修改nk+1的指向,我们可以不用管nk+1后面的指向,假设他们已经逆转了,如n1nk1nknk+1nm
// 此时我们只需将nk+1的指向为nk,所以在进行递归时,需要先保留前一个节点nk,然后调用递归,等递归return之后,修改nk+1->next=nk;
// 递归的结束条件就是当前节点的next指向为空,就返回当前节点,注意,这个节点就将是逆置之后链表的头结点,
// 需要注意的是,等递归完成之后,需要将head->next=NULL,否则链表将无法结束
//递归的函数 struct ListNode* func(struct ListNode* node){ if(node->next == NULL){ return node;//这里返回的节点就是最终逆置好了的链表的头结点 }
//保留当前节点
struct ListNode* cur = node; node = node->next; struct ListNode* ret = func(node); node->next = cur; return ret; } struct ListNode* reverseList(struct ListNode* head){ //递归的方法 if(head == NULL||head->next == NULL){ return head; } struct ListNode* ret = func(head); head->next = NULL; return ret; //头插法 if(head == NULL||head->next ==NULL){ return head; }
//重新创建一个头结点,用来头插入数据
struct ListNode list; list.next = NULL; struct ListNode* node = head; while(node){ struct ListNode* next = node->next; node->next = list.next; list.next = node; node = next; } return list.next; //三指针法 if(head == NULL||head->next ==NULL){ return head; } struct ListNode* p1 = head; struct ListNode* p2 = p1->next; struct ListNode* p3 = p2->next;
//将原来的头结点指向NULL,就可将其作为尾结点 p1->next = NULL; while(p2){
//更新指针 p3
= p2->next; p2->next = p1; p1 = p2; p2 = p3; } return p1; }