九度OJ-题目1518:反转链表

题目链接地址:

九度OJ-题目1518:反转链表


题目描述:
输入一个链表,反转链表后,输出链表的所有元素。
(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 链表的初始状态


九度OJ-题目1518:反转链表_第1张图片

图2 反转链表中的第1个结点


九度OJ-题目1518:反转链表_第2张图片

图3 反转链表中的第2个结点


九度OJ-题目1518:反转链表_第3张图片

图4 反转链表中的第3个结点


九度OJ-题目1518:反转链表_第4张图片

图5 反转链表中的第4个结点


九度OJ-题目1518:反转链表_第5张图片

图6 反转链表中的第5个结点 将head的next指针指向第5个结点


需要注意的是对于空链表和长度为1的链表,直接返回头指针,不需要进行反转操作。

AC代码如下:

// 反转单链表
#include
#include
#include
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
****************************************************************/


你可能感兴趣的:(九度OJ-剑指Offer)