到现在为止,看过的书+代码有一定量了,并且也参加了个比赛,给自己的总体感觉:编程需要的是灵活的头脑,书里的东西只是讲个规则、思想,其实际实现可以千差万别!   潜在的规则+灵活的思维 = 程序!

在做面试题5时,发现Utilities文件夹下的内容太好了,基本上是那些数据结构的实现:链表、二叉树、树等(缺个图),准备通过学习这些代码来深入理解各个数据结构及其接口/成员函数。

拿该题来说,解决单链表!!!

题目:逆序打印单链表

一、自己写单链表类及其操作

花了一下午时间,无语了。。。

1、List.h

//单链表数据结构及基本操作

//最大节点数
const int MAXLENGTH = ;
//节点
struct ListNode
{
int m_Value;
ListNode* m_pNext;
}; //List类
class List
{
private:
ListNode LNode;
int MaxLength;
public:
//constructor and deconstructor
List();
virtual ~List();
//单链表操作
//1. 创建节点
ListNode* CreateListNode(int value);
//2. 创建链表或者将节点加到链尾
void CreateFrontOrAddToTail(ListNode** pHead, int value);
//3. 在第i个节点之前插入新的节点
void ListInsert(ListNode* pHead, int i, int value);
//4. 删除value=e的节点
void RemoveListNode(ListNode** pHead,int value);
//5. 查找第一个value=e的节点
int FindListNode(ListNode* pHead,int value);
//6. 销毁链表
void DestoryList(ListNode* pHead);
//7. 链表元素个数
int ListLength(ListNode* pHead);
};

2、List.cpp

//List.cpp

#include "List.h"
#include <iostream> List::List()
{
LNode.m_Value = ;
LNode.m_pNext = NULL;
MaxLength = MAXLENGTH;
} List::~List()
{ } //1. 创建节点
ListNode* List::CreateListNode(int value)
{
ListNode* pNew = new ListNode;
pNew->m_Value = value;
pNew->m_pNext = NULL;
}
//2. 创建链表或者将节点加到链尾
void List::CreateFrontOrAddToTail(ListNode** pHead, int value)
{
if(pHead == NULL)
return;
ListNode* pNew = CreateListNode(value);
if(*pHead == NULL) //空链表
*pHead = pNew;
else
{
ListNode* pNode = *pHead;
while(pNode->m_pNext != NULL)
pNode = pNode->m_pNext;
pNode->m_pNext = pNew;
} }
//3. 在第i个节点之前插入新的节点
void List::ListInsert(ListNode* pHead, int i, int value)
{
if(pHead == NULL || i >= MaxLength)
return;
ListNode* pNew = CreateListNode(value);
ListNode* pNode = *pHead;
ListNode* preNode = *pHead;
i--;
while(i && pNode->m_pNext != NULL)
{
preNode = pNode;
pNode = pNode->m_pNext;
i--;
}
if(i == )
{
preNode->m_pNext = pNew;
pNew->m_pNext = pNode;
}
else
cout<<"Failed!"<<endl;
}
//4. 删除value=e的第一个节点
bool List::RemoveListNode(ListNode** pHead,int value)
{
if(pHead == NULL || *pHead == NULL)
return false;
ListNode* pToBeDeleted = NULL;
if((*pHead)->m_Value == value)
{
pToBeDeleted = *pHead;
*pHead = (*pHead)->m_pNext;
}
else
{
ListNode* pNode = *pHead;
while(pNode->m_pNext != NULL && pNode->m_pNext->m_Value != value)
pNode = pNode->m_pNext;
if(pNode->m_pNext != NULL && pNode->m_pNext->m_Value == value)
{
pToBeDeleted = pNode->m_pNext;
pNode->m_pNext = pNode->m_pNext->m_pNext;
}
}
if(pToBeDeleted != NULL)
{
delete pToBeDeleted;
pToBeDeleted = NULL;
return true;
}
return false;
} //5. 查找第一个value=e的节点,返回其位置
int List::FindListNode(ListNode* pHead,int value)
{
int i = ;
ListNode* pNode = pHead;
while(pNode != NULL && pNode->m_Value != value)
{
i++;
pNode = pNode->m_pNext;
}
if(pNode != NULL && pNode->m_Value == value)
return i;
else
return ; }
//6. 销毁链表
void List::DestoryList(ListNode* pHead)
{
ListNode* pNode = pHead;
while(pHead != NULL)
{
pNode = pHead;
pHead = pHead->m_pNext;
delete pNode;
}
}
//7. 链表元素个数
int List::ListLength(ListNode* pHead)
{
ListNode* pNode = pHead;
int i = ;
while(pNode != NULL)
{
i++;
pNode = pNode->m_pNext;
}
return i;
}

未测试过。。。因为想继续做面试题5了,进度太慢了!!!

二、面试题5整理:

逆序打印单链表,首先想到的便是通过扫描链表,并同时用栈存储每个值,最后利用栈的LIFO特点打印即可。但是,鉴于自己的水平,并没有用过C++中stl里的stack,因此想了另一种方法,即将扫描链表时所得到的值存入到一个数组中,最后逆序打印即可。这种方法固然可行,但效率上必然低于栈的。所以综合以上分析,又学习了stl中的stack,具体见上一篇博客。最后,怎么也没想到可以用递归的方式求解。。。

根据作者代码思想,做了如下改动:

void PrintListReversingly_Iteratively(ListNode* pHead)
{
std::stack<int> nodes; ListNode* pNode = pHead;
while(pNode != NULL)
{
nodes.push(pNode->m_nValue);
pNode = pNode->m_pNext;
} int value;
while(!nodes.empty())
{
value = nodes.top();
printf("%d\t", value);
nodes.pop();
}
}

这里将stack的元素设置为了m_nValue的类型,仔细想想后,认为还是原代码更合理,原因如下:

原代码中,节点地址入栈,因此栈中每个元素所占存储是固定的,在32位操作系统下,指针(地址)占4字节;但如果存储的是节点数据元素,那么每个元素所占存储很可能大于4字节;

void PrintListReversingly_Recursively(ListNode* pHead)
{
if(pHead == NULL)
{
return;
}
else
{
PrintListReversingly_Recursively(pHead->m_pNext);
printf("%d\t", pHead->m_nValue);
}
}

剑指offer--面试题5的更多相关文章

  1. 剑指Offer:面试题15——链表中倒数第k个结点(java实现)

    问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...

  2. 剑指offer面试题3 二维数组中的查找(c)

    剑指offer面试题三:

  3. 剑指Offer——笔试题+知识点总结

    剑指Offer--笔试题+知识点总结 情景回顾 时间:2016.9.23 12:00-14:00 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:笔试 注意事项:要有大局观, ...

  4. C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告

    剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...

  5. C++版 - 剑指offer 面试题23:从上往下打印二叉树(二叉树的层次遍历BFS) 题解

    剑指offer  面试题23:从上往下打印二叉树 参与人数:4853  时间限制:1秒  空间限制:32768K 提交网址: http://www.nowcoder.com/practice/7fe2 ...

  6. C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解

    剑指offer 面试题39:判断平衡二叉树 提交网址:  http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...

  7. Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)

    剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...

  8. C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解

    剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...

  9. C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解

    剑指offer 面试题24:二叉搜索树的后序遍历序列(的判断) 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true.否则返回false.假设输入的数组的任意两个 ...

  10. C++版 - 剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题,ZOJ 1088:System Overload类似)题解

    剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题) 原书题目:0, 1, - , n-1 这n个数字排成一个圈圈,从数字0开始每次从圆圏里删除第m个数字.求出这个圈圈里剩下的最后一个数字 ...

随机推荐

  1. C# lock用法

    当我们使用线程的时候,效率最高的方式当然是异步,即各个线程同时运行,其间不相互依赖和等待.但当不同的线程都需要访问某个资源的时候,就需要同步机制了,也就是说当对同一个资源进行读写的时候,我们要使该资源 ...

  2. 微信(一) 获取openid 网页授权 C# WeChatHelper

    用.Net开发微信的时候第一步就是获取微信的网页授权,获取openid. 自己做个总结,以后也好用,这里只提供了获取openid的接口,后续程序有待开发 using System; using Sys ...

  3. (转)手把手教你如何架设VPN

    简介 让远程用户连接Exchange Server的传统解决方案是使用Outlook Web Access.然而,为何不使用虚拟专用网(Virtual Private Network,VPN)让你的远 ...

  4. 7款个性化jQuery/HTML5地图插件

    现在我们经常会用到一些地图应用,无论是在网页上还是手机App中,地图貌似是一个不可或缺的应用.本文将带领大家一起来看看一些基于jQuery和HTML5的个性化地图插件,有几款地图比较实用,有些则是具有 ...

  5. DropDownList另一种写法

    2013-09-29 17:04:47 1.性别: <asp:DropDownList ID="DrpSex" runat ="server"  Widt ...

  6. ADO.NET笔记——存储二进制大对象(BLOB)

    相关知识 上传二进制大对象(Binary Large Object)(如图片.视频等)的基本编程步骤是: 在数据库中使用varbinary(MAX).varchar(MAX)或者nvarchar(MA ...

  7. ADO.NET笔记——将DataReader作为函数返回值

    相关知识: 在很多情况下,可能把数据库的访问封装到一个函数中,通过该函数返回一个DataReader对象给调用者.例如定义函数:SqlDataReader returnDR(),然后再Main函数中调 ...

  8. Bootstrap轮播(carousel)插件中图片变形的终极解决方案——使用jqthumb.js

    在顶求网的首页中我使用了BootStrap的轮播(carousel)插件来展示文章中的图片.我在程序中自动抓取文章的第一张图片作为该轮播控件中要显示的图片,由于文章的图片大小不一,而轮播插件的大小基本 ...

  9. $(document).height()、$("body").height()、$(window).height()区别和联系

    前言:在此以高度为示例,宽度问题可类推.在移动端开发中,经常遇到需要把一块内容定位于底部的情况,当页面内容不满一屏时,需要设为fixed,而超过 一屏时,需要设为static随页面顶到底部,此时就需要 ...

  10. (转)android底部弹出iOS7风格对话选项框(QQ对话框)--第三方开源--IOS_Dialog_Library

    本文转载于:http://blog.csdn.net/zhangphil/article/details/44940339 完成这个效果的是使用了 IOS_Dialog_Library 下载地址:ht ...