链表的逆置(非递归和非递归)

本文深入探讨单链表逆序操作,包括一般逆序输出、不破坏结构的逆序输出及递归实现。通过实例解析,帮助读者理解链表操作的核心逻辑与递归技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2013年03月01日

今天上午在写《编程之美》上面的的链表的逆序的一个思考题,后来在网上无意间发现还有多种解法和变形,比如让你逆序输出这个链表,或者使用递归的方法逆序输出这个链表:

我定义的链表:

Link.h

#pragma once

class Link
{
public:
	Link(void);
	~Link(void);

	struct Node   //节点nonde的结构(struct有一个构造函数)
	{
		Node *next;
		int mark;
		/*
		 * pointer:给数据成员next赋值
		 * append:给数据成员mark赋值
		 */
		Node(Node *pointer, int append)
		{
			next = pointer;
			mark = append;
		}
	};

	Node *pHeader;  //链表的头指针

	/*
	 * 向链表尾部中插入数据
     * @param int append:链表中节点的数据
	 */
	void insertNodeTail(int append);

	/*
	 * 向链表头部插入数据
	 * @param int append:链表节点中的数据
	 */
	void insertNodeHead(int append);

	/*
	 * 根据指定的数据查找阶段并返回指向该节点的指针
	 * @param append:数据
	 * @return Node * :返回的指针
	 */
	Node * searchNode(int append);

	/*
	 * 从无头单链表中删除节点
	 * 假设有一个没有头指针的单链表。一个指针指向此单链表中间的一个结点
	 *(不是第一个也不是最后一个,请将该节点从单链表中删除)
	 * @param pCurrent :指向要删除节点的指针
	 * 采用狸猫换太子的方法来做的!
	 */
	void deleteRandomNode(Node *pCurrent);

	/*
	 * 编写一个函数,给定一个链表的头指针,要求只遍历一次,
	 * 将单链表中的元素顺序反转过来
	 * @param pHeader :头指针的引用
	 */
	void reverseLink(Node * &pHeader);

	/*
	 * 给单链表中的元素顺序反转过来
	 */
	void reverseLink();

	/*
	 * 对于这个题目:有另外一种问法:将这个链表逆序输出
	 * 这个时候递归自然是很简单的,在递归函数之后输出当前元素,这样能确保输出第N个元素语句永远在第N+1个递归函数之后执行,
     * 也就是说第N个元素永远在第N+1给元素之后输出,最终我们先输出最后一个元素,然后是倒数第2个、倒数第3个、直到输出第1个
	 * @param pHeader : 头指针
	 */
	void reverseLinkRecurPrint(Node *pHeader);

	/*
	 * 但是在现实应用中,往往不是要求我们逆序输出(不损坏原有的单链表),而是把这个单链表逆序(破坏性)。这就要求
	 * 我们在递归的时候,还要处理递归后的逻辑
	 */
	void reverseLinkRecur();

	Node * recur(Node *pHeader);


	/*
	 * 打印链表
	 */
	void print();
	
};
具体实现我就不上代码了;

1、先来看看一般的单链表逆序并输出(这时链表的结构要被破坏)

/*
 * 只遍历一次,将单链表中的元素顺序反转过来
 */
void Link::reverseLink()
{
	if(pHeader == NULL || pHeader->next == NULL)  //判断链表时候为空,或者链表中只有一个元素
	{
		cout<<"该链表为空,或者该链表只有一个元素不能实施反转程序"<<endl;
	}
	else
	{
		Node * q = pHeader;
		Node * p = pHeader->next;
		q->next = NULL;
		pHeader = NULL;
		while(p)
		{
			Node * temp = p->next;
			p->next = q;
			q = p;
			p = temp;
		}
		pHeader = q;	
	}
}
这个很简单,我就不详细多说了,我在Link.h文件中(上面),还写可一个函数
void reverseLink(Node * &pHeader);

这就是我一篇博客中反思指针用法时所遇到的问题,我在这里就不解释了;

2、其次再来逆序输出链表中的数据(这时链表的结构并没有被破坏)

/*
 * 逆序输出数组中的数据
 */
void Link::reverseLinkRecurPrint(Node * pHeader)
{
	if (pHeader!= NULL)
	{
		reverseLinkRecurPrint(pHeader->next);
		cout<<pHeader->mark<<" ";
	}
		
}

3、使用递归的方法将链表逆序,并输出(这里要破坏链表的结构,使链表真正逆序了)

Link::Node *Link::recur(Node *pHeader)
{
	if(pHeader->next == NULL)
	{
		return pHeader;
	}
	else
	{
		Node *head = recur(pHeader->next);
		pHeader->next->next = pHeader;   //很重要
		pHeader->next = NULL;          //很重要
                cout<<head<<endl;           //我的测试(每次返回的head的指向都是相同的,都是指向第一个元素)
                return head;
	}	
}

/*
 * 递归反转链表
 */
void Link::reverseLinkRecur()
{
	if(pHeader == NULL || pHeader->next == NULL)
	{
		cout<<"链表为空元素或者只有一个元素"<<endl;	
	}
	else
	{
		pHeader = recur(pHeader);
	}
}

在分析递归调用是,我真是头大了,画了好多递归树,终于搞懂了一点点:使用链表pHeader->A->B->C->D->NULL;



根据自己画的图,终于明白了一些:

结果:

参考文献http://www.mianwww.com/html/2011/03/8215.html

在参考文献中,文献中写的是:pHeader->next = recur(pHeader->next);按照我自己的结构 ,这样输出来的结果是1 10  9 8 7 6 5 4 3 2 1 ;

我猜想他的链表是有头结点的,而我的没有!所以他这样写也是对的!

总结:在遇到递归问题时,如果弄不明白,就画图画图画图!!!!!!

转载于:https://my.oschina.net/eillenme/blog/111053

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值