单链表的反转

链表是数据结构中比较重要的一段内容,面试中也很多关于链表的问题。今天学习了链表的反转,总结一下,大致有5个方法。

结构体声明如下

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/

1.将旧链表内容存进数组,再倒序的方式存入链表

比较浪费空间,需要多次遍历,但是比较容易。这里不再赘述。


2.从p->next开始遍历,不断把节点插到head的后面

      head

         ↓

比如 1——2——3——4——5

         1——3——2——4——5

         1——4——3——2——5

         1——5——4——3——2

最后通过首尾相连,再断链的方法就完成了。 如果你的链表是有空链表头的,那么则可以省去最后的连接步骤。

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode* p = pHead->next;
        ListNode* q;
        while(p->next != NULL){ //把P的后面一个节点插入头部后面
            q = p->next;
            p->next = q->next;
            q->next = pHead->next;
            pHead->next = q;
        }
        p->next = pHead;        //成环
        pHead = p->next->next;  //头部向后移一个
        p->next->next = NULL;   //断链
        
        return pHead;
    }
};


3.创建一个新表,遍历旧表,把节点依次插入新表的头部

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode* oldList = pHead;
        ListNode* newList = NULL;
        ListNode* tmp;
        while(oldList != NULL){
            tmp = oldList;         // 得到要插入的节点
            oldList = tmp->next;   // oldList 向后移
            tmp->next = newList;   // 把新表插入 tmp 后面
            newList = tmp;         // 新表此时 head 为tmp
        }
        return newList;
    }
};

4.用三个指针,遍历一次链表,完成每个节点都指向前面节点的工作

即 从                  A > B > C > D > E > NULL

     到   NULL < A < B < C < D < E      的过程

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == NULL) 
            return NULL;
        ListNode* pre = NULL;
        ListNode* next = NULL;
        ListNode* head = pHead;
        while(head != NULL){
            next = head->next;
            head->next = pre;
            pre = head;
            head = next;
        }
        return pre;
    }
};


5.递归方法。

递归的方法相对来说就很巧妙了,用递归一直移动到链表的最后,返回一个newHead,这是我们的新头节点

从递归结束的时候开始分析,过程大概是这样的:节点从最后(newHead)遍历到pHead,除了newHead,其他任何节点都作为后一个节点的后续节点,并指向NULL

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == NULL) // 鲁棒性
            return NULL;
        if(pHead->next == NULL){ //当找到最后一个节点,返回这个节点作为newHead
            return pHead;
        }
        ListNode* newHead = ReverseList(pHead->next);  //保存newHead
        pHead->next->next = pHead;                     //作为后一个节点的后续节点
        pHead->next = NULL;
        return newHead;
    }
};

总结:

1.对链表的操作要非常仔细,有些操作调换一下上下位置,含义可能是完全不一样的。要想清楚逻辑以后再动手

2.什么问题其实都不妨尝试想一想递归操作能否实现。


留个问题:这是最基本的单链表的反转,那么其他链表呢?


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值