题目链接地址:
题目描述:
输入一个链表,反转链表后,输出链表的所有元素。
(hint : 请务必使用链表)
输入:
输入可能包含多个测试样例,输入以EOF结束。
对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000):代表将要输入的链表的个数。
输入的第二行包含n个整数t(0<=t<=1000000):代表链表元素。
输出:
对应每个测试案例,
以此输出链表反转后的元素,如没有元素则输出NULL。
样例输入:
5
1 2 3 4 5
0
样例输出:
5 4 3 2 1
NULL
解题思路:
这道题我参考了网上的解法。反转单链表需要将链表中的每一个结点的next指针指向该结点所对应的前一个结点。这就会出现两个问题:(1) 因为单链表中的结点只有一个指向下一个结点的next指针,没有指向前一个结点的指针,所以需要用一个指针pPre “记录”该结点的前一个结点;(2)当我们把链表结点的next指针改为指向该结点的前一个结点后,该结点与下一个结点的链接就断开了,所以还需要用一个指针pNext“记住”下一个结点的位置。以题目的测试用例为例,将pCur指针指向当前正在反转的链表结点,具体演示一下该算法的流程:
图1 链表的初始状态
图2 反转链表中的第1个结点
图3 反转链表中的第2个结点
图4 反转链表中的第3个结点
图5 反转链表中的第4个结点
图6 反转链表中的第5个结点 将head的next指针指向第5个结点
需要注意的是对于空链表和长度为1的链表,直接返回头指针,不需要进行反转操作。
AC代码如下:
// 反转单链表
#include<stdio.h>
#include<malloc.h>
#include<iostream>
using namespace std;
// 定义链表结点
typedef struct LNode
{
int data; // 数据域
LNode * next; // 指针域
}Linklist;
/**
* 构造长度为n的单链表
* @param n 表示链表有n个结点
* @param head 链表的头指针
*/
Linklist * createLinklist(int n)
{
Linklist * head = (Linklist *)malloc(sizeof(LNode)); // 构造链表头结点
head -> next = NULL;
Linklist * p = head; // p指针始终指向链表的最后一个结点
int i;
int data;
for(i = 1;i <= n;i++)
{
scanf("%d",&data);
Linklist * s = (Linklist *)malloc(sizeof(LNode));
s -> data = data;
s -> next = p -> next; // 将s结点插入到p结点后面
p -> next = s;
p = s; // p始终指向当前链表的最后一个结点
}
return head;
}
/**
* 反转单链表。注意:对于空链表和长度为1的链表,直接返回头指针,不需要进行反转操作
* @param head 链表的头指针
* @param head 返回链表的头指针
*/
Linklist * reverseLinklist(Linklist * head)
{
Linklist *pPre,*pCur,*pNext;
pPre = NULL; // pPre指向当前结点的前一个结点
pCur = head -> next; // pCur指向当前正在被处理的结点
if(NULL == pCur) // 空链表直接返回头指针,不需要反转
{
return head;
}
pNext = pCur -> next; // pNext指向当前结点的下一个结点
if(NULL == pNext) // 对于只有1个元素的链表,直接返回头指针,不需要反转
{
return head;
}
while(pNext -> next != NULL) // 当pNext -> next == NULL 时,表示pNext指向的是链表中的最后一个元素
{
pCur -> next = pPre; // 将当前结点的next指针指向当前结点的前一个结点
pPre = pCur; // pPre,pCur,pNext都向右移一个位置
pCur = pNext;
pNext = pNext -> next;
}
pCur -> next = pPre;
pNext -> next = pCur;
head -> next = pNext; // 将head的next指针指向原链表中的最后一个结点
return head;
}
/**
* 打印单链表
* @param head 单链表的头指针
* @return void
*/
void printLinklist(Linklist * head)
{
Linklist * p = head -> next; // p指向链表的首元结点
if(NULL == p)
{
printf("NULL\n");
}
else
{
while(NULL != (p -> next)) // 输出链表中的前n-1个结点
{
printf("%d ",p -> data);
p = p -> next;
}
printf("%d\n",p -> data); // 输出链表的最后一个结点
}
}
int main()
{
int n;
Linklist * head;
while(EOF != scanf("%d",&n))
{
head = createLinklist(n);
head = reverseLinklist(head); // 反转链表
printLinklist(head);
}
return 0;
}
/**************************************************************
Problem: 1518
User: blueshell
Language: C++
Result: Accepted
Time:150 ms
Memory:2972 kb
****************************************************************/