C++链表原地反转(链表的逆转)

这也是学校的一道OJ题目,题目如下:

题目描述:

按数字输入顺序创建单链表。不可借助数组、容器,不可开辟新结点空间。编写函数,在原链表上实现单链表的反转。例如单链表10->20->30,反转后变为单链表30->20->10。

注:不符合题目要求,使用上述逆序输出不计分。

输入:

测试次数t

每组测试数据一行,格式如下:

数据个数n,后跟n个整数

输出:

对每组测试数据,输出反转后的单链表。

输入样例:

2
10 1 2 3 4 5 6 7 8 9 10
4 19 20 15 -10

输出样例:

10 9 8 7 6 5 4 3 2 1 
-10 15 20 19 

AC代码:
 

#include <iostream>
using namespace std;
typedef struct node{
    node*before;
    int data;
    node*next;
}node;

node* createlist(node*&head,int n)
{
    head=new node;
    head->before=NULL;
    node*pre=head;
    for(int i=0;i<n;i++)
    {
        node*p=new node;
        cin>>p->data;
        p->next=NULL;
        p->before=pre;
        pre->next=p;
        pre=p;
    }
    return pre;
}

void print(node*&end)
{
    for(node*p=end;p->before;p=p->before)
    {
        cout<<p->data<<" ";
    }
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        node*head;
        node*end;
        end=createlist(head,n);
        print(end);
    }
    return 0;
}

        这道题有许多思路,可以从输出控制的层面解决,也可以从输入层面进行思考,也可能有方法可以先初始化链表再对链表进行反序,在这道题中我用的是从输出的层面来思考的方法。

        这里使用的是创建双头链表的方法,即在原本尾插法创建单链表的方法上加上了一个before结构体指针。

        所以重点就是如何创建并输出链表。

下面是链表的创建:

typedef struct node{
    node*before;//创建指向前一个节点的指针
    int data;
    node*next;
}node;

node* createlist(node*&head,int n)
{
    head=new node;
    head->before=NULL;//头节点的before指针相当于单链表的尾指针
    node*pre=head;//与之前的尾插法创建单链表相同,头节点里面不装载数据
    for(int i=0;i<n;i++)
    {
        node*p=new node;
        cin>>p->data;
        p->next=NULL;
        p->before=pre;//多了一步,新节点的before指针需指向上一个节点,依然只需要定义两个指针即可完成初始化的推进
        pre->next=p;
        pre=p;
    }
    return pre;//返回指向end节点的指针,之后作为初始节点进行输出
}

创建好双向链表之后,就只需选择逆序方式进行输出即可:

void print(node*&end)//初始节点为尾节点
{
    for(node*p=end;p->before;p=p->before)//因为head->before为NULL,所以选取head->before作为跳出的条件
//若选取head作为条件,则此时遍历已经过头节点,而头节点是无数据装载的,所以要选取head->next
    {
        cout<<p->data<<" ";
    }
    cout<<endl;
}

所以最后代码总结为;

#include <iostream>
using namespace std;
typedef struct node{
    node*before;//创建指向前一个节点的指针
    int data;
    node*next;
}node;

node* createlist(node*&head,int n)
{
    head=new node;
    head->before=NULL;//头节点的before指针相当于单链表的尾指针
    node*pre=head;//与之前的尾插法创建单链表相同,头节点里面不装载数据
    for(int i=0;i<n;i++)
    {
        node*p=new node;
        cin>>p->data;
        p->next=NULL;
        p->before=pre;//多了一步,新节点的before指针需指向上一个节点,依然只需要定义两个指针即可完成初始化的推进
        pre->next=p;
        pre=p;
    }
    return pre;//返回指向end节点的指针,之后作为初始节点进行输出
}

void print(node*&end)//初始节点为尾节点
{
    for(node*p=end;p->before;p=p->before)//因为head->before为NULL,所以选取head->before作为跳出的条件
//若选取head作为条件,则此时遍历已经过头节点,而头节点是无数据装载的,所以要选取head->next
    {
        cout<<p->data<<" ";
    }
    cout<<endl;
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        node*head;
        node*end;
        end=createlist(head,n);
        print(end);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值