16:反转链表

转载 2016年05月31日 16:17:35

http://www.cnblogs.com/xwdreamer/archive/2012/04/26/2472797.html

假设有链表A->B->C->D->E->F->G。在反转链表过程中的某一阶段,其链表指针指向为:A<-B<-C<-D  E->F->G。也就是说在结点D之前的所有结点都已经反转,而结点D后面的结点E开始的所有结点都没有反转。这样D跟E之间存在了断裂。我们如果要实现链表的反转,会有以下几个重要步骤:

  1. D->E变为D->C,指针反转
  2. 指针往后移动一个,操作下一个结点E
  3. 结合1.2我们发现需要操作3个指针,分别是C,D,E。

因此可以考虑存储C/D/E三个结点的指针,通过这三个结点的指针实现反转。

代码实例:

复制代码
#include<iostream>
#include<stdlib.h>
#include<stack>
using namespace std;

//链表结构
struct ListNode
{
    int m_nValue;
    ListNode* m_pNext;
};

//创建一个链表结点
ListNode* CreateListNode(int value)
{
    ListNode *pNode=new ListNode();
    pNode->m_nValue=value;
    pNode->m_pNext=NULL;
    return pNode;

}

//遍历链表中的所有结点
void PrintList(ListNode* pHead)
{
    ListNode *pNode=pHead;
    while(pNode!=NULL)
    {
        cout<<pNode->m_nValue<<" ";
        pNode=pNode->m_pNext;
    }
    cout<<endl;
}

//往链表末尾添加结点
/*
注意这里pHead是一个指向指针的指针,在主函数中一般传递的是引用。
因为如果要为链表添加结点,那么就会修改链表结构,所以必须传递引用才能够保存修改后的结构。
*/
void AddToTail(ListNode** pHead,int value)
{
    ListNode* pNew=new ListNode();//新插入的结点
    pNew->m_nValue=value;
    pNew->m_pNext=NULL;

    if(*pHead==NULL)//空链表
    {
        *pHead=pNew;
    }
    else
    {
        ListNode* pNode=*pHead;
        while(pNode->m_pNext!=NULL)
            pNode=pNode->m_pNext;
        pNode->m_pNext=pNew;
    }

}

ListNode* ReverseList(ListNode* pHead)
{
    ListNode* pNode=pHead;//当前结点
    ListNode* pPrev=NULL;//当前结点的前一个结点
    ListNode* pReversedHead=NULL;//反转链表头结点
    while(pNode!=NULL)
    {
        ListNode* pNext=pNode->m_pNext;
        if(pNext==NULL)//如果当前结点的下一个结点为空,那么反转链表的头结点就是当前结点。
            pReversedHead=pNode;

        pNode->m_pNext=pPrev;//当前结点指向前一个结点

        pPrev=pNode;//pPrev和pNode往前移动。
        pNode=pNext;//这里要使用前面保存下来的pNext,不能使用pNode->m_pNext
    }
    return pReversedHead;//返回反转链表头指针。
}

void main()
{
    //创建结点
    ListNode* pNode1=CreateListNode(1);//创建一个结点
    PrintList(pNode1);//打印
    //往链表中添加新结点
    AddToTail(&pNode1,2);//为链表添加一个结点
    AddToTail(&pNode1,3);//为链表添加一个结点
    AddToTail(&pNode1,4);//为链表添加一个结点
    AddToTail(&pNode1,5);//为链表添加一个结点
    AddToTail(&pNode1,6);//为链表添加一个结点
    AddToTail(&pNode1,7);//为链表添加一个结点
    //打印链表
    PrintList(pNode1);//打印
    //反转链表
    ListNode* pReversedHead=ReverseList(pNode1);
    PrintList(pReversedHead);//打印

    system("pause");

}
复制代码

运行结果:

1
1 2 3 4 5 6 7
7 6 5 4 3 2 1

ps:2012-5-3

发现有一种更加简洁的写法,就是不需要pReversedHead指针,从上述程序我们可以看出来pReversedHead指针只是单纯的用来保存反转链表的头指针,但是pPrev和pNode指针其实就包含反转链表的头指针,因此我们没有必要单独定义一个头指针来保存。修改后的函数如下所示:

复制代码
ListNode* ReverseList2(ListNode* pHead)
{
    ListNode* pNode=pHead;//当前结点
    ListNode* pPrev=NULL;//当前结点的前一个结点
    while(pNode!=NULL)
    {
        ListNode* pNext=pNode->m_pNext;
        pNode->m_pNext=pPrev;//当前结点指向前一个结点

        pPrev=pNode;//pPrev和pNode往前移动。
        pNode=pNext;//这里要使用前面保存下来的pNext,不能使用pNode->m_pNext
    }
    return pPrev;//返回反转链表头指针。
}
复制代码

 


反转单链表 (三种方法整理)

题目:反转单链表 输入一个链表,反转链表后,输出链表的所有元素。 据找工作的师兄说,反转单链表基本各个公司面试都会有,整理出一些写的比较好的code,供我等小白们学习。简洁,清晰,...
  • hyqsong
  • hyqsong
  • 2015年10月26日 21:15
  • 18943

Java单链表反转 详细过程

Java单链表反转 Java实现单链表翻转 使用递归法实现单链表反转,使用遍历反转法:递归反转法是从后往前逆序反转指针域的指向,而遍历反转法是从前往后反转各个结点的指针域的指向。     【尊重原创,...
  • guyuealian
  • guyuealian
  • 2016年04月11日 10:36
  • 28999

反转单向链表

反转单向链表 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。而单向链表就是在每一个结点中除了保存的数据之外只有一个指向下一个节点的指针。双向...
  • iosrookie
  • iosrookie
  • 2015年05月23日 07:46
  • 972

剑指offer_面试题16_反转链表(两种方法)

题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。 在解决问题前,先想好测试用例: 1、功能测试:输入的链表含有多个结点,链表中只有一个结点 2、特殊输入测试:头结点...
  • jwentao01
  • jwentao01
  • 2015年08月10日 11:00
  • 1958

链表翻转的图文讲解(递归与迭代两种实现)

链表的翻转是程序员面试中出现频度最高的问题之一,常见的解决方法分为递归和迭代两种。最近在复习的时候,发现网上的资料都只告诉了怎么做,但是根本没有好好介绍两种方法的实现过程与原理。所以我觉得有必要好好的...
  • FX677588
  • FX677588
  • 2017年05月17日 15:25
  • 1018

递归和非递归实现链表反转

链表反转是面试笔试常考题目,直接贴代码。 反转函数如下://思路为将节点从前到后依次放到表头,最后最后的节点到了最前面,最前面的节点到了最后面 void ReverseList(ListNode * ...
  • yunzhongguwu005
  • yunzhongguwu005
  • 2013年08月26日 16:43
  • 12634

数据结构——反转单链表

最近看了《剑指offer》这本书,遇到了一个问题:反转链表 题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点。 链表结点定义如下:struct ListNode { ...
  • u013271921
  • u013271921
  • 2015年06月05日 22:17
  • 3024

剑指Offer面试题16(Java版):反转链表

题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。 解决与链表相关的问题总是有大量的指针操作,而指针操作的代码总是容易出错的。很多的面试官喜欢出链表相关的问题,就是想通过指...
  • jsqfengbao
  • jsqfengbao
  • 2015年08月01日 16:45
  • 1381

数据结构之Java单链表反转

本文为数据结构基础,研究得不是很深。用Java实现单链表的反转,虽然本文研究得不是很深,但是因为是数据结构,所以必须是在对Java内存比较清楚的情况下才能真正的搞懂吃透,如果对Java内存不够清楚,那...
  • qq_24692041
  • qq_24692041
  • 2017年03月16日 15:44
  • 1226

单链表操作之反转单链表

***单链表操作之反转单链表*** //反转单链表,只能遍历一遍链表 // 定义的结点结构体和头指针结构体: typedef int DataType; t...
  • bitboss
  • bitboss
  • 2016年06月08日 09:46
  • 1665
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:16:反转链表
举报原因:
原因补充:

(最多只允许输入30个字)