Description
输入多个整数,以-1作为结束标志,顺序建立一个带头结点的单链表,之后对该单链表的数据进行逆置,并输出逆置后的单链表数据。
Input
输入多个整数,以-1作为结束标志。
Output
输出逆置后的单链表数据。
Sample
Input
12 56 4 6 55 15 33 62 -1
Output
62 33 15 55 6 4 56 12
链表的逆置呢一般有三种常见的方法,普通循环(头插法,就地逆置)和递归,下面的这段代码呢,是我第一次写的时候,写的,相当于,直接新建了的带头结点的链表,然后把数据倒序复制过去了。
#include<iostream>
using namespace std;
struct node
{
int data;
struct node *next;
};
int main()
{
struct node *head,*tail,*p,*q,*k;
head=new struct node();
head->next=NULL;
tail=head;
while(1)
{
p=new struct node();
p->next=NULL;
cin>>p->data;
if(p->data==-1)
break;
tail->next=p;
tail=p;
}
//——————————逆置过程——————————
p=head->next;
q=new struct node(); //新链表的头结点
q->next=NULL;
while(p)
{
k=new struct node();
k->data=p->data;
k->next=q->next;
q->next=k;
p=p->next;
}
//———————————————————————————
for(p=q->next;p!=NULL;p=p->next)
cout<<p->data<<" ";
return 0;
}
下面是头插法的代码,凭空想象比较费劲,大家可以拿纸演示一下循环过程
重点是循环开始之前的这两句,顺序不能反了,循环里面就是用p进行遍历,然后用q进行插入
p=head->next; //重点用p指向第一个元素
head->next=NULL; //将头结点与后面断开,防止成环
while(p)
{
q=p; //q和p总是指向相邻的两个结点
p=p->next;
q->next=head->next; //这两句是标准的插入语句,将q插入到头结点后面
head->next=q;
}
这是就地逆置的代码块,因为指针的方向改变了;这个也是要注意强两句的顺序
就地逆置一般用于没有头指针的链表,我这里是用p指向第一个元素后,直接把head赋值为NULL;
也可以在引入一个值为NULL的变量;
就地逆置的精髓是:
head,q, p这三个是指向顺序相邻的三个结点,利用q来改变结点的指向
p=head->next;
head=NULL;
while(p!=NULL)
{
q=p;
p=p->next;
q->next=head; //直接改变结点的指向,指向前面的前面的结点
head=q;
}
下面是递归的解法:
递归总是比较难以理解的:
先遍历找到对后一个结点,然后再回溯
node* newList(node *head)
{
if (head == NULL || head->next == NULL)
return head;
node *newhead = newList(head->next);
head->next->next = head;
head->next = NULL;
return newhead;
}
头插法和就地逆置代码将其放到第一个完整的程序的对应位置即可
因篇幅问题不能全部显示,请点此查看更多更全内容