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 ;
我猜想他的链表是有头结点的,而我的没有!所以他这样写也是对的!
总结:在遇到递归问题时,如果弄不明白,就画图画图画图!!!!!!