逆序链表小范例


(弱弱小题,闲的没事你就看看吧)

今天晚上跟老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 ;
}
好像还不错的样子

 怎么有种像当年较数据结构的作业一样尴尬,看官随便看看吧





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值