(弱弱小题,闲的没事你就看看吧)
今天晚上跟老L聊天,看到一个关于逆序链表的题目。两人吃完饭正好练练手,比速度,结果写完之后发现问题不少。
要求:仅仅是实现逆序链表。
先过目一下最初的源码
#include <iostream>
//#include <vld.h>
using namespace std;
//定义ListNode链表数据
typedef struct _ListNode{
int data;
_ListNode* nextNode;
_ListNode(){
nextNode = NULL;
}
}ListNode;
//显示函数 链表函数
void Display (ListNode* pHead)
{
if ( !pHead)
{
printf("空表\n");
return;
}
ListNode* ptmp = pHead;
while(ptmp)
{
printf("%d " ,ptmp->data);
ptmp = ptmp->nextNode;
}
printf("\n");
}
//逆序链表
void ReserveList( ListNode* pPHead)
{
if ( !pHead)
return ;
ListNode* first = pHead->nextNode;
if ( !first )
return ;
ListNode* temp;
pHead->nextNode = NULL ; //先断开父子关系,避免乱了辈分这一说
while(first)
{
temp = first->nextNode; //先把孙子放别人家
first->nextNode = pHead ; //然后儿子在家造反,倒指老爹
pHead = first; //儿子在家变老大
first = temp; //再把孙子抱回家,然后孙子重走儿子的路
}
}
int main()
{
ListNode* pHead = new ListNode;
ListNode* ptmp = pHead;
int iMax = 1;
for (int index = 0 ; index < iMax ; index++)
{
ptmp->data = index + 1 ;
if(index<iMax-1)
ptmp->nextNode = new ListNode;
ptmp = ptmp->nextNode;
}
Display(pHead);
ReserveList(pHead);
Display(pHead);
return 0 ;
}
看上去好像很不错的样子,ctrl+F5:
好嘛,有问题。再跟踪调试,跟踪到Reserve函数中,发现Reserve函数结束完成之后,pHead确实是翻转了,那为什么没显示出来了!
在老L的慧眼下,一下发现了端倪,Reserve的确实有问题,Reserve的参数是个局部变量(多基础、多简单的问题!)。
这里我错误了想当然了:指针的值可改。
虽然这里是指针,但是能该的是指针所指向的地址,而不是指针本身。考虑升级有两种方式:
//逆序链表
void ReserveList( ListNode** pHead)
void ReserveList( ListNode* &pHead)
第二种,看起来怪怪的是吧,还是用第一种吧:二级指针,这样就能改指针本身了。
对比了老L的代码,发现他使用了另一种方式,不该头指针,链表自带头结点(第一个数据不是链表有效数据,仅仅做个链表头)。
这是标准链表么?是我太久没看数据结构了么?应该是兼容各种风格吧,还是看看老严的《数据结构》吧,其中说到:有时,我们会在单链表的第一个节点之前附设一个节点,称为头结点。看来这是部分人使用标志。这样的好处是能保证头结点的稳定性,比如我们要删除第一个节点不需要改变首地址,或者像本程序中这样,不需要变化指针本身的值。
最后记得释放内存,做个优秀的程序编写者,不能内存泄露
//销毁链表
void Destroy(ListNode * pHead)
{
if( !pHead )
return;
if ( pHead->nextNode )
{
Destroy(pHead->nextNode);
}
delete pHead;
pHead = NULL ;
}
最后的代码:
//逆序链表
void ReserveList( ListNode** pPHead)
{
ListNode* pHead = *pPHead;
if ( !pHead)
return ;
ListNode* first = pHead->nextNode;
if ( !first )
return ;
ListNode* temp;
pHead->nextNode = NULL ; //先断开父子关系,避免乱了辈分这一说
while(first)
{
temp = first->nextNode; //先把孙子放别人家
first->nextNode = pHead ; //然后儿子在家造反,倒指老爹
pHead = first; //儿子在家变老大
first = temp; //再把孙子抱回家,然后孙子重走儿子的路
}
*pPHead = pHead;
}
int main()
{
ListNode* pHead = new ListNode;
ListNode* ptmp = pHead;
int iMax = 10;
for (int index = 0 ; index < iMax ; index++)
{
ptmp->data = index + 1 ;
if(index<iMax-1)
ptmp->nextNode = new ListNode;
ptmp = ptmp->nextNode;
}
Display(pHead);
ReserveList(&pHead);
Display(pHead);
Destroy(pHead);
return 0 ;
}
好像还不错的样子
怎么有种像当年较数据结构的作业一样,看官随便看看吧