一、迭代实现
思路:
通过每次遍历,修改当前结点与上一结点指向,遍历到最后一个结点,链表也就实现了反转
首先我们定义三个指针,分别指向当前节点cur、前一结点pre、下一节点next,并且pre和next为null
起始状态为:
//第一次代码执行代码:
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
经过一次访问后:
继续上面的思想,每次将cur->next指向pre, 通过next保存原链表下一结点使 依次修改结点指向,再画出一次修改过程,其他不再赘述:
具体代码:
ListNode* reverseList(ListNode* head) {
//定义三个指针 pre cur next
//思路:直接将指向方向改变 时间复杂度O(n)
if(head == NULL) return NULL;
if(head->next == NULL) return head;
ListNode* Rev_head = NULL; //翻转后的链表头节点
ListNode* pre = NULL; //定义前一个当前结点(当前结点为头节点是pre是NULL)
ListNode* cur = head;
ListNode* next = NULL;
while(cur != NULL){ //遍历到最后一个结点
next = cur->next;
if(cur->next == NULL) Rev_head = cur; //当遍历到最后一个结点时,将该节点赋值为翻转后的头节点
cur->next = pre; //调节结点指向
pre = cur; //向下遍历之前记录上一个结点,保存其下一结点指向该节点的地址
cur = next; //
}
return Rev_head;
}
二、递归实现
递归实现思路与迭代实现思路类似,也是修改指针指向,只是递归改变顺序是从后向前修改,还是继续画图吧
省略了初始图:
这是递归压栈到最后一个元素,设置一个存储变量,记录新链表的头节点(原链表的尾节点。。。)Rev_head
然后将4弹出,现在head指向3, 代码是:head->next->next = head; head->next = NULL;
该节点head为3 head->next->next = head将4的next指向3,这里要注意,修改了指向后,原链表指向还存在,需要删除,所以有head->next = NULL; 依照这样的思路一直递归到1,返回之前记录的Rev_head
明白了上面迭代的思路,迭代思路也很容易理解,这里不再赘述,下面是实现代码:
ListNode* reverseList(struct ListNode* head) {
if(head == NULL || head->next == NULL)
return head;
ListNode* Rev_head = reverseList(head->next); //记录尾节点
head->next->next = head; //将该结点的下一节点 下一节点向指向当前结点
head->next =NULL; //将原链表指向下一节点 删除
return Rev_head;
}