剑指offer面试题5
来源:互联网 发布:食品行业数据 编辑:程序博客网 时间:2024/05/29 19:31
面试题5: 从尾到头打印链表
题目: 输入一个链表的头结点,从尾到头反过来打印出每个结点的值
预备知识:
链表结点定义:
struct ListNode{ int m_nValue; ListNode* m_pNext;};
链表的操作有:创建结点,插入结点,删除结点,遍历结点等
//创建链表结点ListNode* CreateListNode(int value){ ListNode* pNode = new ListNode(); //结构体起始指针(头指针) pNode->m_nValue = value; pNode->m_pNext = NULL; return pNode;}//连接链表结点void ConnectListNodes(ListNode* pCurrent, ListNode* pNext){ if(pCurrent == NULL) { printf("Error to connect two nodes.\n"); exit(1); } pCurrent->m_pNext = pNext;}//输出链表结点void PrintListNode(ListNode* pNode){ if(pNode == NULL) { printf("The node is NULL\n"); } else { printf("The key in node is %d.\n", pNode->m_nValue); }}//遍历链表并打印void PrintList(ListNode* pHead){ printf("PrintList starts.\n"); ListNode* pNode = pHead; while(pNode != NULL) { printf("%d\t", pNode->m_nValue); pNode = pNode->m_pNext; } printf("\nPrintList ends.\n");}//销毁链表(每一个结点都要销毁)void DestroyList(ListNode* pHead){ ListNode* pNode = pHead; while(pNode != NULL) { pHead = pHead->m_pNext; //一个一个结点的销毁 delete pNode; pNode = pHead; }}//向链表尾部添加结点void AddToTail(ListNode** pHead, int value){ ListNode* pNew = new ListNode(); pNew->m_nValue = value; //初始化 pNew->m_pNext = NULL; if(*pHead == NULL) { *pHead = pNew; } else { //在结点的尾部添加 ListNode* pNode = *pHead; while(pNode->m_pNext != NULL) pNode = pNode->m_pNext; pNode->m_pNext = pNew; }}//移去结点void RemoveNode(ListNode** pHead, int value){ if(pHead == NULL || *pHead == NULL) return; ListNode* pToBeDeleted = NULL; if((*pHead)->m_nValue == value) //刚好等于这个值 { pToBeDeleted = *pHead; *pHead = (*pHead)->m_pNext; //指针改变 } else { ListNode* pNode = *pHead; while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value) pNode = pNode->m_pNext; //遍历 if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value) //遍历找到了这个值 { pToBeDeleted = pNode->m_pNext; pNode->m_pNext = pNode->m_pNext->m_pNext; //指针改变 } } if(pToBeDeleted != NULL) { delete pToBeDeleted; //销毁 pToBeDeleted = NULL; }}
思路:1. 把链表中结点的指针反过来,改变链表的反向,然后就可以从头到尾输出,但是该方法会改变原来链表的结果
2.根据题目的要求遍历顺序是从头到尾,而输出是从尾到头,因此可以使用栈来实现这种顺序,即通过构建一个栈(后入向出)来实现,STL中有一个stack。(显栈)
3.由于递归本质上是一个栈结构,因此可以使用递归来实现,但是当链表非常长的时候,可能导致调用栈溢出。(隐栈)
代码:
List.h
struct ListNode{ int m_nValue; ListNode* m_pNext;};//使用标识符:_declspec(dllimport)表明函数是从动态库中引入的 (孙鑫VC++ 712)__declspec( dllexport ) ListNode* CreateListNode(int value);__declspec( dllexport ) void ConnectListNodes(ListNode* pCurrent, ListNode* pNext);__declspec( dllexport ) void PrintListNode(ListNode* pNode);__declspec( dllexport ) void PrintList(ListNode* pHead);__declspec( dllexport ) void DestroyList(ListNode* pHead);__declspec( dllexport ) void AddToTail(ListNode** pHead, int value);__declspec( dllexport ) void RemoveNode(ListNode** pHead, int value);
List.cpp
#include "stdafx.h"#include "list.h"#include <stdio.h>#include <stdlib.h>//创建链表结点ListNode* CreateListNode(int value){ ListNode* pNode = new ListNode(); //结构体起始指针(头指针) pNode->m_nValue = value; pNode->m_pNext = NULL; return pNode;}//连接链表结点void ConnectListNodes(ListNode* pCurrent, ListNode* pNext){ if(pCurrent == NULL) { printf("Error to connect two nodes.\n"); exit(1); } pCurrent->m_pNext = pNext;}//输出链表结点void PrintListNode(ListNode* pNode){ if(pNode == NULL) { printf("The node is NULL\n"); } else { printf("The key in node is %d.\n", pNode->m_nValue); }}//遍历链表并打印void PrintList(ListNode* pHead){ printf("PrintList starts.\n"); ListNode* pNode = pHead; while(pNode != NULL) { printf("%d\t", pNode->m_nValue); pNode = pNode->m_pNext; } printf("\nPrintList ends.\n");}//销毁链表(每一个结点都要销毁)void DestroyList(ListNode* pHead){ ListNode* pNode = pHead; while(pNode != NULL) { pHead = pHead->m_pNext; //一个一个结点的销毁 delete pNode; pNode = pHead; }}//向链表尾部添加结点void AddToTail(ListNode** pHead, int value){ ListNode* pNew = new ListNode(); pNew->m_nValue = value; //初始化 pNew->m_pNext = NULL; if(*pHead == NULL) { *pHead = pNew; } else { //在结点的尾部添加 ListNode* pNode = *pHead; while(pNode->m_pNext != NULL) pNode = pNode->m_pNext; pNode->m_pNext = pNew; }}//移去结点void RemoveNode(ListNode** pHead, int value){ if(pHead == NULL || *pHead == NULL) return; ListNode* pToBeDeleted = NULL; if((*pHead)->m_nValue == value) //刚好等于这个值 { pToBeDeleted = *pHead; *pHead = (*pHead)->m_pNext; //指针改变 } else { ListNode* pNode = *pHead; while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value) pNode = pNode->m_pNext; //遍历 if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value) //遍历找到了这个值 { pToBeDeleted = pNode->m_pNext; pNode->m_pNext = pNode->m_pNext->m_pNext; //指针改变 } } if(pToBeDeleted != NULL) { delete pToBeDeleted; //销毁 pToBeDeleted = NULL; }}
main.cpp
#include "stdafx.h"#include "..\Utilities\List.h"#include <stack> //STL: push,pop//方法1:构建一个栈(后进先出)来实现void PrintListReversingly_Iteratively(ListNode* pHead){ std::stack<ListNode*> nodes; ListNode* pNode = pHead; //栈顶 while(pNode != NULL) { nodes.push(pNode); //先入栈 pNode = pNode->m_pNext; //指针向上移到 } while(!nodes.empty()) { pNode = nodes.top(); //栈顶 printf("%d\t", pNode->m_nValue);//先输出值 nodes.pop(); //结点出栈,同时栈顶改变 }}//方法2:递归本质上是一个栈结构,因此可以使用递归来实现void PrintListReversingly_Recursively(ListNode* pHead) //层级过深,可能导致调用栈溢出{ if(pHead != NULL) { if (pHead->m_pNext != NULL) { PrintListReversingly_Recursively(pHead->m_pNext); } printf("%d\t", pHead->m_nValue); }}void Test(ListNode* pHead){ PrintList(pHead); PrintListReversingly_Iteratively(pHead); //显示栈实现 printf("\n"); PrintListReversingly_Recursively(pHead); //隐式栈实现}// 1->2->3->4->5void Test1(){ printf("\nTest1 begins.\n");//创建单个结点 ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5);//连接链表结点 ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode5); //测试Test(pNode1);//销毁栈 DestroyList(pNode1);}// 只有一个结点的链表: 1void Test2(){ printf("\nTest2 begins.\n"); ListNode* pNode1 = CreateListNode(1); Test(pNode1); DestroyList(pNode1);}// 空链表void Test3(){ printf("\nTest3 begins.\n"); Test(NULL);}int _tmain(int argc, _TCHAR* argv[]){ Test1(); Test2(); Test3(); return 0;}
/********************7月15日********************************/
// 面试题5.cpp : 定义控制台应用程序的入口点。////面试题5:从尾到头打印链表#include "stdafx.h"#include <stack>struct ListNode{intm_nKey;ListNode*m_pNext;};/********链表的基本操作*************///创建结点ListNode* CreateListNode(int value){ListNode* pNode = new ListNode();pNode->m_nKey = value;pNode->m_pNext= NULL;return pNode;}//链接结点void ConnectListNode(ListNode* pNode1, ListNode* pNode2){if(pNode1 == NULL)return;pNode1->m_pNext = pNode2;}//遍历链表 void PrintListNode(ListNode* pHead){if(pHead == NULL)return;ListNode* pNode = pHead;while(pNode != NULL){printf("%d ", pNode->m_nKey);pNode = pNode->m_pNext;}printf("\n");}//销毁链表void DestroyListNode(ListNode* pHead){ListNode* pNode = pHead;while(pNode != NULL){pNode = pNode->m_pNext;delete pHead;pHead = pNode;}}/************面试题5的功能****/void PrintListReversingly_Iteratively(ListNode* pHead){std::stack<ListNode*> nodes;ListNode* pNode = pHead;while(pNode != NULL){nodes.push(pNode); //结点入栈pNode = pNode->m_pNext;}while(!nodes.empty()){pNode = nodes.top(); //栈顶元素printf("%d ", pNode->m_nKey);nodes.pop(); //出栈}printf("\n");}void PrintListReversingly_Recursively(ListNode* pHead){if(pHead != NULL){if(pHead->m_pNext != NULL)PrintListReversingly_Recursively(pHead->m_pNext);printf("%d ", pHead->m_nKey);}}/***********测试链表基本功能*****************/void Test1(){//创建链表结点ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ListNode* pNode6 = CreateListNode(6);//连接链表结点ConnectListNode(pNode1,pNode2);ConnectListNode(pNode2,pNode3);ConnectListNode(pNode3,pNode4);ConnectListNode(pNode4,pNode5);ConnectListNode(pNode5,pNode6);//打印链表PrintListNode(pNode1);//销毁链表DestroyListNode(pNode1);}void Test2(){//创建链表结点ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ListNode* pNode6 = CreateListNode(6);//连接链表结点ConnectListNode(pNode1,pNode2);ConnectListNode(pNode2,pNode3);ConnectListNode(pNode3,pNode4);ConnectListNode(pNode4,pNode5);ConnectListNode(pNode5,pNode6);//打印链表PrintListReversingly_Iteratively(pNode1);//销毁链表DestroyListNode(pNode1);}void Test3(){//创建链表结点ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ListNode* pNode6 = CreateListNode(6);//连接链表结点ConnectListNode(pNode1,pNode2);ConnectListNode(pNode2,pNode3);ConnectListNode(pNode3,pNode4);ConnectListNode(pNode4,pNode5);ConnectListNode(pNode5,pNode6);//打印链表PrintListReversingly_Recursively(pNode1);printf("\n");//销毁链表DestroyListNode(pNode1);}void Test4(){//创建链表结点ListNode* pNode1 = CreateListNode(1);//打印链表//PrintListReversingly_Iteratively(pNode1);PrintListNode(pNode1);//销毁链表DestroyListNode(pNode1);}int _tmain(int argc, _TCHAR* argv[]){Test1();Test2();Test3();Test4();return 0;}
0 0
- 剑指offer面试题5
- 剑指offer 面试题5
- 剑指offer-面试题5
- 【面试题】剑指offer 5
- 剑指offer 面试题
- 剑指offer面试题
- 剑指Offer面试题5 Java解法
- 剑指Offer(面试题3~5)
- 剑指offer--面试题5:替换空格
- 【剑指offer】面试题 5:替换空格
- 【剑指offer】面试题5:替换空格
- 剑指offer 面试题5: 替换空格
- 剑指offer面试题总结
- 剑指offer面试题06
- 剑指offer面试题 04
- 剑指offer 面试题07
- 剑指offer面试题08
- 剑指offer面试题42
- Android特效开发(可伸缩View带互相挤压效果 )
- 如何设置ESXi的SNMP
- C++中的智能指针
- UVa_644 - Immediate Decodability
- css ISO风格 按钮和Table 兼容IE
- 剑指offer面试题5
- KMP algorithm ---C++
- 队列的数组实现
- java中split()方法的特殊分割符"|"和"."
- 弱性能穿戴设备App化之Lua For STM32
- THE DRUNK JAILER
- 个人重构机房收费系统——配置文件
- ubuntu安装netbeans方法及解决netbeans乱码方法
- 超级楼梯