《算法之美》の链表问题の单向链表的反转

题目:输入一个链表的头节点,反转这个链表,并返回反转后链表的头节点,链表定义如下:

struct ListNode
{
        
int
       m_nKey;
         ListNode* m_pNext;
};

解答:

算法一:我们需要额外的两个变量来存储当前节点pCurrent的上一个节点pPrev和下一个节点pNext。假设经过若干次操作,我们将当前节点pCurrent之前的指针都反转完成,这些节点的m_pNext指针都指向前面的一个节点。现在我们遍历到pCurrent,这时需要调整该节点的m_pNext指针使其指向pPrev节点。但要注意调整了m_pNext指针的指向后,后面的链表就会断开,因此我们需要在调整pCurrentm_pNext指针之前先将pNext节点保存下来。反转后的头节点就是原来的尾节点。

核心代码如下:

//反转链表核心算法

ListNode* ReverseList(ListNode* pHead)

{

    ListNode* pReverseHead = NULL;

    ListNode* pNode = pHead->m_pNext;

    ListNode* pPrev = NULL;

   

    while(pNode != NULL)

    {

        //存储当前节点pNode的下一个节点

        ListNode* pNext = pNode->m_pNext;

       

        //如果下一个节点为空,那么当前节点pNode就是反转后的头指针了

        if(pNext == NULL)

        {

            pReverseHead = pNode;        

        }

       

        //将当前节点改为指向pPrev节点

        pNode->m_pNext = pPrev;

       

        //移动两个指针

        pPrev = pNode;

        pNode = pNext;

    }

    //添加头指针

    ListNode* pReturn = (ListNode*)malloc(sizeof(ListNode));

    pReturn->m_pNext = pReverseHead;

    return pReturn;

}

 

 

算法二:递归法,基本思想是在反转当前节点之前先调用递归函数反转后续节点,该方法在反转后的最后一个节点会形成一个环,所以必须将函数的返回节点的m_pNext域置为NULL

ListNode* ReverseLink(ListNode* pHead)

{

    if(pHead->m_pNext == NULL)

        return pHead;

    ListNode* pReturn = ReverseLink(pHead->m_pNext);

    pHead->m_pNext->m_pNext = pHead;

    pHead->m_pNext = NULL;

    return pReturn;

}

 

//反转链表的递归算法

ListNode* ReverseList2(ListNode* pHead)

{

    ListNode* pReverseHead = pHead;

    //考虑只有0个或1个节点

    if(pHead->m_pNext == NULL || pHead->m_pNext->m_pNext == NULL)

    {

        return pHead;                 

    }         

    pReverseHead->m_pNext = ReverseLink(pReverseHead->m_pNext);

    return pReverseHead;

}

 

完整测试代码如下:

#include <iostream>

 

struct ListNode

{

    int m_nKey;

    ListNode* m_pNext;      

};

 

void InitList(ListNode** head)

{

    *head = (ListNode*)malloc(sizeof(ListNode));

    (*head)->m_pNext = NULL;    

}

 

void InsertList(ListNode* head, int data)

{

   assert(head != NULL);

   ListNode* pNewNode = (ListNode*)malloc(sizeof(ListNode));

   pNewNode->m_nKey = data;

   pNewNode->m_pNext = head->m_pNext;

   head->m_pNext = pNewNode;     

}

 

void PrintList(ListNode* pHead)

{

   if(pHead == NULL)    

   {

       return;        

   }

  

   ListNode* pTempNode = pHead->m_pNext;

   while(pTempNode != NULL)

   {

       std::cout<<pTempNode->m_nKey<<std::endl;

       pTempNode = pTempNode->m_pNext;                    

   }

}

 

//反转链表核心算法

ListNode* ReverseList(ListNode* pHead)

{

    ListNode* pReverseHead = NULL;

    ListNode* pNode = pHead->m_pNext;

    ListNode* pPrev = NULL;

   

    while(pNode != NULL)

    {

        //存储当前节点pNode的下一个节点

        ListNode* pNext = pNode->m_pNext;

       

        //如果下一个节点为空,那么当前节点pNode就是反转后的头指针了

        if(pNext == NULL)

        {

            pReverseHead = pNode;        

        }

       

        //将当前节点改为指向pPrev节点

        pNode->m_pNext = pPrev;

       

        //移动两个指针

        pPrev = pNode;

        pNode = pNext;

    }

    //添加头指针

    ListNode* pReturn = (ListNode*)malloc(sizeof(ListNode));

    pReturn->m_pNext = pReverseHead;

    return pReturn;

}

 

ListNode* ReverseLink(ListNode* pHead)

{

    if(pHead->m_pNext == NULL)

        return pHead;

    ListNode* pReturn = ReverseLink(pHead->m_pNext);

    pHead->m_pNext->m_pNext = pHead;

    pHead->m_pNext = NULL;

    return pReturn;

}

 

//反转链表的递归算法

ListNode* ReverseList2(ListNode* pHead)

{

    ListNode* pReverseHead = pHead;

    //考虑只有0个或1个节点

    if(pHead->m_pNext == NULL || pHead->m_pNext->m_pNext == NULL)

    {

        return pHead;                 

    }         

    pReverseHead->m_pNext = ReverseLink(pReverseHead->m_pNext);

    return pReverseHead;

}

 

 

int main()

{

    ListNode* pListHead = NULL;

    InitList(&pListHead);

   

    //建立两个链表

    for(int i=9; i>=0; i--)

    {

        InsertList(pListHead, i);       

    }

   

    std::cout<<"链表反转之前:"<<std::endl;

    PrintList(pListHead);

   

    //ListNode* pReverseHead = ReverseList(pListHead);

    ListNode* pReverseHead = ReverseList2(pListHead);

   

    std::cout<<"链表反转之后:"<<std::endl;

    PrintList(pReverseHead);

    system("pause");

    return 0;

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值