【数据结构】单链表逆置(详解)————四种方法

链表逆置就是把最后一个数据提到最前面,倒数第二个放到第二个……依次类推,直到第一个到最后一个。
由于链表没有下标,所以不能借助下标来实行数据的逆置,要靠空间的转移来完成链表的逆置,这里采用没有头节点的链表来实现逆置。

0.链表结构:

struct ListNode {
    int val;
    struct ListNode* next;
};

 

1.头插法:

算法思想:逆置链表(新链表)初始为空,表中节点从原链表中依次“删除”,再逐个插入逆置链表的表头(即“头插”到逆置链表中),使它成为逆置链表的“新”的第一个结点,如此循环,直至原链表为空。

struct ListNode* reverseList1(struct ListNode* head) {
    struct ListNode* tmp = NULL, * cur = NULL;
    tmp = head;
//判空或单结点
    if (tmp == NULL || tmp->next == NULL) {
        return head;
    }
    head = head->next;
    tmp->next = NULL;
//tmp为新链表
    while (head) {
        cur = head;
        head = head->next;
        cur->next = tmp;
        tmp = cur;
    }
    head = tmp;
    return head;
}

2.就地逆置:

算法思想:就地逆置法和头插法的实现思想类似,唯一的区别在于,头插法是通过建立一个新链表实现的,而就地逆置法则是直接对原链表做修改,从而实现将原链表反转。在原链表的基础上做修改,需要额外借助 2 个指针(假设分别为 p和 q)。

struct ListNode* reverseList2(struct ListNode* head) {
    struct ListNode* tmp = NULL, * cur = NULL;
    tmp = head;
//判空或单结点
    if (tmp == NULL || tmp->next == NULL) {
        return tmp;
    }
    cur = tmp->next;
    head->next = NULL;
    head = tmp;
//就地逆置
    while (cur) {
        tmp = cur;
        cur = cur->next;
        tmp->next = head;
        head = tmp;
    }
    return head;
}

3.迭代: 

在遍历链表时,将当前节点的next指针改为指向前一个节点。由于节点没有引用其前一个节点,因此必须事先存储其前一个节点。在更改引用之前,还需要存储后一个节点。最后返回新的头引用。

struct ListNode* reverseList3(struct ListNode* head) {
    struct ListNode* tmp = NULL, * cur = head;
    while (cur) {
        struct ListNode* next = cur->next;
        cur->next = tmp;
        tmp = cur;
        cur = next;
    }
    return tmp;
}

4.递归:

递归版本稍微复杂一些,其关键在于反向工作;若结点head->next及以后结点都已经逆置,我们希望head->next下一个指向的结点是head,所以:head->next->next=head;head->next=NULL;

struct ListNode* reverseList4(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    }
    struct ListNode* tmp = reverseList(head->next);
    head->next->next = head;
    head->next = NULL;
    return tmp;
}

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值