面试题6:从尾到头打印链表
题目描述
输入一个链表的头节点,从尾到头反过来打印出每个节点的值。链表节点定义如下:
struct ListNode{
int m_nValue;
struct ListNode* m_pNext;
ListNode(int x):m_nValue(x),m_pNext(NULL){
}
};
思路:
从尾到头打印,能否改变原来的链表?(是否允许修改输入数据)
1.能改变原来的链表,将链表的指针反过来。
2.使用栈(递归)
链表的基本操作
插入节点
//在链表的尾端插入一个节点 若链表为空,则头指针的值会改变 所以要使用指向指针的指针作为函数参数
void AddToTail(ListNode** pHead, int value){
//1.构造节点
ListNode* pNew = new ListNode();//new 的用法 struct 和 class
pNew->m_nValue = value;
pNew->m_pNext = NULL;
//2.当链表为空 头指针指向新节点
if(*pHead == NULL){
*pHead = pNew;
}
//3.链表不为空
else{
ListNode* pCur = *pHead;//定义一个临时指针 用于找到链表的最后一个节点。
while(pCur->m_pNext){
pCur = pCur->m_pNext;
}
pCur->m_pNext = pNew;//节点插入链表末端
}
return;
}
删除节点
//删除链表中第一个与给定值相同的节点 当删除的是头节点 头指针的值会改变 所以要使用指向指针的指针作为函数参数
void RemoveNode(ListNode** pHead, int value){
//1.若链表为空 直接返回
if(pHead == NULL || *pHead == NULL)
return;
//2.定义指针释放被删除节点的内存
ListNode* pToBeDeleted = NULL;
//3.删除的是头节点
if(*pHead->m_nValue == value){
pToBeDeleted = *pHead;
*pHead = *pHead->m_pNext;
}
//4.删除的不是头节点
else{
ListNode* pCur = *pHead;//定义一个临时指针 去寻找节点
while(pCur->m_pNext && pCur->m_pNext->m_nValue!=value){//注意是判断pCur的下一个节点
pCur = pCur->m_pNext;
}
if(pCur->m_nValue == value){//找到第一个节点
pToBeDeleted = pCur->m_pNext;
pCur->m_pNext = pCur->m_pNext->m_pNext;
}
else{//说明到达尾端没有找到
}
}
//5.释放节点内存
if(pToBeDeleted){
delete pToBeDeleted;//删除pToBeDeleted指向的内存
pToBeDeleted = NULL;//?
}
return;
}
实现代码
//一、使用C++中的容器stack
void PrintListReversingly_Iteratively(ListNode* pHead){
//1.定义一个栈
std::stack<ListNode*> nodes;
//2.将所有的节点入栈
ListNode* pCur = pHead;
while(pCur){
nodes.push(pCur);
pCur = pCur->m_pNext;
}
//3.出栈打印
while(!nodes.empty()){
printf("%d\t",nodes.top()->m_nValue);
nodes.pop();
}
return;
}
//二、递归在本质上是一个栈 递归实现
void PrintListReversingly_Recursively(ListNode* pHead){
//先打印后面的部分 再打印当前节点
if(pHead == NULL)
return;
if(pHead->m_pNext ==NULL){
printf("%d\t",pHead->m_nValue);
return;
}
PrintListReversingly_Recursively(pHead->m_pNext);
printf("%d\t",pHead->m_nValue);
return;
}
//当链表很长,递归写法会导致函数调用层数过深,可能导致函数调用栈溢出
//用栈基于循环的实现代码鲁棒性好。
考点
-
链表
-
循环、递归、栈
Note
-
C++中,struct关键字与Class关键字基本是一样的,但是,有两点不同
1 struct里面所有成员默认级别都是共有的,而class里面所有成员默认级别都是私有的
2 在模板定义中,只能用class 或者typename 而不能用struct -
递归在本质上是一个栈。