【链表】链表逆置/反转链表 如何用递归和非递归实现?

目录

一、思想

1.非递归实现

2.递归思想

二、代码讲解

1.非递归

代码(C语言实现)

运行结果

2.递归代码(C++实现)

执行结果

三、力扣206题(C语言实现)

非递归实现代码

执行结果


一、思想

1.非递归实现

将原链表断开,然后把头结点的下一个结点位置的值依次进行头插在头结点后面,用下图示例:

1.首先把plist断开:plist->next=NULL;

p=plist->next; q=plist->next;

2.把p头插在plist链后面:

p=plist->next; //p=NULL

plist->next=p; //plist->next=500,500是p结点的地址

3.把p重新赋值为q的位置,q后移一个:p=q;  q=p->next;

把p继续进行头插到plist后面:p->next=plist->next; plist->next=p; 

重复操作,一直到最后q=NULL,p=q=NULL时停下。

2.递归思想

        假设是6个节点,节点1调用节点2,节点2调用节点3,....,节点5调用节点6。逆置的思想是把1->2->3->4->5->6改为1<-2<-3<-4<-5<-6,需要把节点的指向颠倒,代码实现就是p->next->next=p (递推的时候5->next=6,回归的时候6->next=5,因此,5->next->next=5)然后断开原来的指向p->next=NULL,避免形成环。

 

 其代码就是:
Node* Reverse(Node* head)
{
    if (head->m_next == NULL)
        return head;//一直往下递归找到head(6)
    Node* newhead = Reverse(head->next); //递推返回head(6),newhead=head(6)
    head->next->next = head;//head=head(5)
    head->next = NULL;
    return newhead;
}

二、代码讲解

1.非递归

1.栈实现:让链表依次进栈、再依次出栈赋值给链表,时间复杂度:O(n),空间O(n)

2.链表实现:将头结点和下一个结点断开,头插法,从后向前遍历插入。

空链表、0个结点和1个结点不需要逆置

代码(C语言实现)

//实现链表逆置
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>

    typedef struct Node
    {
        int data;
        struct Node* next;
    }Node, * List;

    //初始化
    void   InitList(List plist)
    {
        assert(plist != NULL);
        if (plist == NULL)
        {
            return;
        }

        //plist->data;//头节点的data不使用
        plist->next = NULL;
    }
    //尾插
    bool   Insert_tail(List plist, int val)
    {
        assert(plist != NULL);
        if (plist == NULL)
        {
            return false;
        }

        //申请结点
        Node* p = (Node*)malloc(sizeof(Node));
        assert(p != NULL);
        //将数据val放入到新结点;
        p->data = val;
        //找尾巴
        Node* q;
        for (q = plist; q->next != NULL; q = q->next)
        {
            ;
        }
        //插入新结点,把p插入到q的后面
        p->next = q->next;//p->next=NULL;
        q->next = p;
        return true;
    }
    //输出
    void  Show(List plist)
    {
        assert(plist != NULL);
        if (plist == NULL)
        {
            return;
        }
        for (Node* p = plist->next; p != NULL; p = p->next)
        {
            printf("%d   ", p->data);
        }
        printf("\n");
    }
    //链表逆置
    void Reverse(List plist)
    {
        assert(plist != NULL);
        //空链表、0个结点和1个结点不需要逆置
        if (plist == NULL || plist->next == NULL || plist->next->next == NULL)
        {
            return;
        }

        Node* p = plist->next;
        Node* q = p->next;

        plist->next = NULL;//把链表断开

        while (p != NULL)
        {
            q = p->next;//防止链断

            //头插p
            p->next = plist->next;
            plist->next = p;
            p = q;
        }
    }

    int main()
    {
        Node head;
        InitList(&head);
        for (int i = 0; i < 20; i++)
        {
            Insert_tail(&head, i);
        }
        Show(&head);
        Reverse(&head);
        Show(&head);
    }

运行结果

2.递归代码(C++实现)

class Node
{
public:
	Node(int v) :m_value(v), m_next(NULL) {}
	Node() :m_next(NULL) {}
	int m_value;
	Node* m_next;
};
Node* Reverse(Node* head)
{
	if (head->m_next == NULL)
		return head;
	Node* newhead = Reverse(head->m_next);
	head->m_next->m_next = head;
	head->m_next = NULL;
	return newhead;
}

void Print(Node* head)
{
	Node* p = head;
	while (p)
	{
		cout << p->m_value << " ";
		p = p->m_next;
	}
	cout << endl;
}
void main()
{
	Node* head = NULL;
	Node a(1), b(2), c(3), d(4), e(5), f(6);
	head = &a;
	a.m_next = &b;
	b.m_next = &c;
	c.m_next = &d;
	d.m_next = &e;
	e.m_next = &f;
	Print(head);
	head = Reverse(head);
	Print(head);
}

执行结果

 

三、力扣206题(C语言实现)

非递归实现代码

struct ListNode* reverseList(struct ListNode* head){
    
    if(head==NULL)//对[]的情况进行处理
        return NULL;
    struct ListNode plist;
    plist.next=head;//力扣的链表都不带头节点,自定义一个头结点:plist
    //struct ListNode *p=plist.next; head->p //慢指针
    struct ListNode*q;
    q=head->next;//快指针
    plist.next=NULL;//链表断开
    //p头插到plist后
    while(head!=NULL)
    {
        q=head->next;
        head->next=plist.next;
        plist.next=head;
        head=q;
    }
    return plist.next;//返回head
}

执行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值