倒序输出链表

本文介绍了如何倒序输出链表,首先通过遍历链表将节点值存入数组,然后反转数组。讨论了不同反转数组的方法,包括自定义反转、使用库函数以及利用vector的特性。还分享了在线编程题的注意事项,如边界情况和逻辑错误,并提到了vector的push_back和insert方法在处理顺序上的差异。文章最后总结了编程中的一些实用技巧和知识点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 思路:先遍历链表,用一个数组存储链表的值。然后反转该数组,返回该数组即可。
2 核心模块
①遍历链表
我的误区:head是虚拟头结点,不存放有意义的链表数据。
按照题目意思:head中存放链表的第一个数据。
遍历链表:定义指向ListNode类型的指针p,使其指向头结点。仅当p不为空的时候,将p的数据域存入数组,并且将p指向下一个节点。最后返回数组。对应代码:

ListNode * p=head;
 while(p!=NULL) 
        {
            Ldata.push_back(p->val);
            p=p->next;
            
        }

极端情况说明:如果传入的链表为空,则不进行任何操作,直接返回数组。因为数组仅声明,所以输出为空。

②反转数组
反转数组有三种实现方式:
方式一:自定义实现反转,注意千万不要在数组本身上反转,会覆盖会出错,再定义一个新的数组,将反转后的结果存入新数组。

for(int i=0;i<Ldata.size();i++)
   res.push_back(Ldata[Ldata.size()-1-i]);
  return res;

方式二:使用algorithm中的reverse()函数,注意reverse函数传入的参数

reverse(Ldata.begin(),Ldata.end());
 return Ldata;

方式三:使用vector中的反转迭代器

vector <int> ::reverse_iterator rit=Ldata.rbegin();
 for(;rit!=Ldata.rend();rit++)
       res.push_back(*rit);
 return res;

3 完整代码

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector <int> Ldata,res;
        
        ListNode * p=head;
       
        while(p!=NULL) //对于头指针的理解有问题,头指针也可以存放链表的有效数据
        {
            Ldata.push_back(p->val);
            p=p->next;
            
        }
        
        //法一:自定义自己实现反转的时候千万不要在数组本身上反转,会覆盖会出错
        //for(int i=0;i<Ldata.size();i++)
          // res.push_back(Ldata[Ldata.size()-1-i]);
        // return res;
        //法二:使用algorithm中的reverse()函数
       //reverse(Ldata.begin(),Ldata.end());
         // return Ldata;
         //法三:使用vector中的反转迭代器
        vector <int> ::reverse_iterator rit=Ldata.rbegin();
        for(;rit!=Ldata.rend();rit++)
            res.push_back(*rit);
         return res;
    }
};

4 收获:
在线编程题如果只有一部分通过率,不一定是没考虑到边界情况,还有可能是逻辑上存在错误。

5 新思路:
vector的成员函数push_back和insert插入方式的差异:push_back()在数组尾部插入元素 & insert()在某个位置前插入某个或者某区间元素。push_back对应尾插法,最后得到的是相同顺序序列,insert选择每次在首元素前面插入新元素,对应头插法,最后得到的相反顺序的序列。所以本题可以用insert每次在首元素前面插入元素直接得到相反顺序的序列。

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector <int> Ldata,res;
        
        ListNode * p=head;
        while(p!=NULL) 
        {
            Ldata.insert(Ldata.begin(),p->val);
            p=p->next;
        }
        return Ldata;
    }
};

6 收获
①声明类和结构体 后面不需要加(),但是末尾需要加;
②对于<剑指Offer>这种有函数定义的题目,你只要完成函数,返回相关的值就可以,不需要处理任何输入输出,不要在函数里输出任何东西。用好传给你的参数,返回指定类型的返回值就好,不要有多余的输入输出。这也体现了“封装”的思想。
③vector不能直接用cout输出,需要迭代器或者循环。
vector只声明,没有添加任何元素,迭代器输出的结果为空。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值