剑指offer面试题16 反转链表(递归和非递归,主要还是看代码的鲁棒性)

/*
这题早就做过了,但是当时看的书上的代码真的很差,比其这本书差的不少。。剑指offer真是我大学看过的最好的书之一了

反转链表 需要对链表进行遍历 每次对于遍历到的节点,先记录next,再next指向前一个,然后继续遍历 注意不要把链表弄段
还有注意输入 最主要的是输入头节点NULL 的处理 测试数据要想到 只有一个节点怎么办 两个,多个怎么办 输入NULL 怎么办
只要自己想到测试数据都过了 代码才可以提交

*/
#include<iostream>
#include<cstdio>
using namespace std;

struct Node
{
    int data;
    Node * next;
};

void PrintList(Node * head)
{
    if(head==NULL)
    printf("empty List\n");
    Node * p=head;
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    cout<<endl;
}

Node * ReverseList(Node * head)
{
    Node * pre=NULL;//因为头节点的前一个是空的
    Node * p=head;
    Node * newhead=NULL;//如果输入空指针 不进入循环 返回newhead 所以赋初值NULL
    while(p!=NULL)
    {
        Node * p_next=p->next;//先记录下一个
        if(!p_next)
        newhead=p;
        p->next=pre;//再把next指向前一个
        pre=p;
        p=p_next;
    }
    return newhead;
}
// 单链表反序的递归算法,这个相对好理解 想起以前看那本CC++程序员面试宝典,也是在那看的
//递归算法,太尼馬坑了 那本书我还通透的看完了。那个代码本来就有错 还不好理解,看来选经典好书真的太重要了
//这个算法就相对好理解了 一直递归执行这个函数 知道最后一个节点的时候 因为head->next是空了 返回了head
//因为是最后一个节点 这个head就是反转后的头节点 在倒数第二个里面newhead就是新的头节点
//接下来两句很经典 head->next->next=head 这句话把链表的指针到过来了
//这个时候 这个head就是目前链表的末尾 所以next赋值NULL 太经典了 这个算法真好
Node * ReverseListRecursively(Node * head)//递归方法 相对好理解
{
    if(head==NULL || head->next==NULL) return head;
    Node * newhead=ReverseListRecursively(head->next);
    head->next->next=head;
    head->next=NULL;
    return newhead;
}

int main()
{
    //freopen("/home/gl/in","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        Node * head;
        if(!n)
        head=NULL;
        else
        head=new Node();
        Node * p=head;
        for(int i=0;i<n;++i)
        {
            scanf("%d",&p->data);
            if(i==n-1)
            {
                p->next=NULL;
                break;
            }
            p->next=new Node();
            p=p->next;
        }
        PrintList(head);
       // Node * newhead = ReverseList(head);
        Node * newhead=ReverseListRecursively(head);
        PrintList(newhead);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值