《算法问题实战策略》-chaper21-树的实现和遍历
这一章节开始介绍一个数据结构中的一个基本概念——树。
我们从数据结构的解读来解释树结构的重要性,现实世界的数据除了最基本的线性结构(我们常用队列、数组和链表等结构表征),还有一个重要的特性——层级结构需要我们去表征,例如世界杯的对阵表、遗传系谱图等等,这时候我们基于对现实世界的抽象,会很自然的理解为什么会有树这样一个数据结构。
而树这种数据结构也是能够分类的,我们将每个节点记录某种抽象的概念或者具象的事物,这样用来表征一种从属关系,我们称其为抽象型数据结构的树。或者将每个节点储存一些数据,基于这棵树我们能够完成检索查找之类的操作,我们称其为检索型数据结构的树。
关于树的基本的术语和其中的基本概念,这里不再累述,读者可以通过查找离散数学或者图论的资料了解。
树的实现:
既然了解到了树存在的必要性和重要性,下面我们就应该去关注怎样实现一棵树了。在《啊哈算法》中,作者介绍了用一维数组实现的二叉树,这是基于二叉树一些非常特殊的形式,但是对于更加一般的情况的多叉树呢?我们需要采用更加一般的方法。对于树中的每一个节点,我们很关注如下集合很有价值的数据:它的父节点?它的子节点?存在该节点的数据?关于它的父节点和子节点,其实就是需要我们表征一种“联系”,即通过该节点,我们能够轻松的找到和它关联的父节点和子节点,我们很容易便可以想到指针。而基于一维数组实现的二叉树,就是二叉树的基本性质,通过为节点标号从而实现了指针的作用。
通过上面的分析,我们能够定义树节点的结构体。
struct Treenode
{
<data>
TreeNode* parent;
vector<TreeNode*> children;
};
树的遍历:
树本质上也是一种图,因此这里采用基本的深搜就可以完成对树的遍历。
void printLabels(TreeNode* root)
{
cout<< root-> <data><<endl;
for(int i = ;i < root->chilren.size();i++)
printLabels(root->children[i]);
}
基于对树的遍历,我们同时可以完成对树的高度的计算。
int height(TreeNode* root)
{
int h = ;
for(int i = ;i < root->children.size();i++)
h = max(h,+height(root->children[i]));
return h;
}
关于一个树结构的一个简单建模:
Q:中世纪时,为了更好的首尾保护更多领地,城市和要塞之间都具有多层城墙。偏执狂领主建筑的Strawgoh要塞达到了这中间城模式的极致。下图是这种要塞的结构图。那么现在给出一个要塞的图,两个城市之间没有门只能通过梯子翻越城墙,请问再给出的城墙图中,从一个城市到另一个城市最多翻阅多少城墙?
Input:
将每个城市看成一个圆,然后程序会给出n个圆的圆心和半径用来表示这个城墙结构。
用树建立起来的解题模型:这道问题从原始的图上来看并不好直观的得到它会与树联系起来,但是我们进一步的看这个图,是否像集合论当中的维恩图,而维恩图就是典型的层级结构,这正与树结构能够表征的东西呼应起来。如果基于树结构看这个问题,我们就能够将问题化约成,求解树结构的最长路径,也就是树的深度。这个在前面介绍“树的实现和遍历”当中曾经简单的介绍过它的实现方法。
显然整体的思路有了,下面我们面临的最大问题就是,如何基于题目给出的数据,建立这样一棵树结构?
建树的方法:首先基于一个基本的递归过程,也可以说成一个深度优先建树的过程。我们从根节点开始,假设我们已经有了一个判断两个城市是否是父子关系的函数,我们能够写出如下的过程:
TreeNode* getTree(int root)
{
TreeNode* ret = new TreeNode();//指向该节点的指针
for(int i = ;i < n;i++)
if(isChild(root,i))
ret -> children.push_bcak(getTree(ch));//树节点数据中储存儿子结点的向量表
return ret;
}
那么好了,下面我们面临的问题就变成了如何设计判断两个城市之间是否是父子关系的isChild()函数了。如何判断两个点在树结构中是否是父子关系呢?通过观察我们能够发现,必须两个区域是直接的包含关系,即对于圆B,A,如果B内含与A并且不存在这样一个圆C使得圆C内含与A且B内含于C。清楚了这一点,在拿到两个区域判断其双方是否是父子关系的时候,首先我们当然要利用简单的几何知识要判断他们是否是包含关系,随后我们通过穷举的方法来遍历剩下的所有区域由此来判断是否存着这样一个上文中提到的区域C,即我们能够写出如下的简单代码。
int n , y[],x[],radius[];
bool inclose(int a , int b)//判断圆b是否在圆a的内部
{
double dis;//圆心距
dis = sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
if(radius[b]-radius[a] >= dis)
return true;
else
return false;
}
bool isChild(int parent , int child)
{
if(!inclose(parent,child)) return false;
int flag = ;
for(int i = ;i < n;i++)
{
if(i == parent || i == child) continue;
if(inclose(parent,i) && inclose(i,child)) {flag = ;break;}
}
if(flag) return true;
else return false;
}
《算法问题实战策略》-chaper21-树的实现和遍历的更多相关文章
- 算法问题实战策略 PICNIC
下面是另一道搜索题目的解答过程题目是<算法问题实战策略>中的一题oj地址是韩国网站 连接比较慢 https://algospot.com/judge/problem/read/PICNIC ...
- 《算法问题实战策略》-chaper7-穷举法
关于这一章节<算法实战策略>有一段概述问题,我认为对于编程人员来说非常有价值,故在这里进行如下的摘抄: 构想算法是很艰难的工作.相比大家都经历过,面对复杂的要求只是傻乎乎地盯着显示器,或者 ...
- 《算法问题实战策略》-chaper13-数值分析
这一章节主要介绍我们在进行数值分析常用的二分.三分和一个近似求解区间积分的辛普森法. 首先介绍二分. 其实二分的思想很好理解并且笔者在之前的一些文章中也有所渗透,对于二次函数甚至单元高次函数的零点求解 ...
- 《算法问题实战策略》-chaper32-网络流
基本的网络流模型: 在图论这一块初步的应用领域中,两个最常见的关注点,其一时图中的路径长度,也就是我们常说的的最短路径问题,另一个则是所谓的“流问题”. 流问题的基本概念: 首先给出一张图. 其实所谓 ...
- 算法问题实战策略 MEETINGROOM 附一份tarjan模板
地址 https://algospot.com/judge/problem/read/MEETINGROOM 解答 2-sat 代码样例过了 没有ac. 我又没有正确代码对拍..... 已确认是输出 ...
- 《算法问题实战策略》——chaper9——动态规划法技巧
Q1: 数字游戏: 两个人(A.B)用n个整数排成的一排棋盘玩游戏,游戏从A开始,每个人有如下操作: (1) 拿走棋盘最右侧或者最左侧的棋子,被拿走的数字从棋盘中抹掉. (2) 棋盘中还剩 ...
- 《算法问题实战策略》-chaper8-动态规划法
Q1:偶尔在电视上看到一些被称为“神童”的孩子们背诵小数点以后几万位的圆周率.背诵这么长的数字,可利用分割数字的方法.我们用这种方法将数字按照位数不等的大小分割后再背诵. 分割形式如下: 所有数字都相 ...
- 《算法问题实战策略》-chaper14-整数论
Lucas定理: 在组合计数问题中,我们常面临组合数C(n,m)过大而无法直接计算的困境,那么这里的Lucas定理给出了一个较大组合数进行取余运算的一种递归算法. 什么是Lucas定理? Lucas定 ...
- 算法问题实战策略 QUADTREE
地址 https://algospot.com/judge/problem/read/QUADTREE 将压缩字符串还原后翻转再次压缩的朴素做法 在数据量庞大的情况下是不可取的 所以需要在压缩的情况下 ...
随机推荐
- 推荐Asp.net WebApi入门教程
Web API 强势入门指南; Web API 入门指南 - 闲话安全; 实例快速上手 -ASP.NET 4.5新特性WebAPI从入门到精通; Asp.net WebApi 项目示例(增删改查).
- http错误代码含义大全详解
http 错误代码表 所有 HTTP 状态代码及其定义. 代码 指示 2xx 成功 200 正常:请求已完成. 201 正常:紧接 POST 命令. 202 正常:已接受用于处理, ...
- 【转】iOS8 推送 获取 devicetoken
标签:推送 push ios8 devicetoken token xcode6 原文:http://roybaby.blog.51cto.com/1508945/1557854 打开AppDeleg ...
- OpenCart本地调试环境搭建
OpenCart简介: 免费开源网络版电子商务系统,是建立在线商务网站首选之一.有众多用户和开发基础,结合其丰富特性与模板插件,可最大化定制在线商店.(也就是用来方便开网店的) 本地调试准备: Fir ...
- C++ STL的基本基本原理
STL都是在内存的堆区分配的,但是其析构也是STL帮我们做好的,不用手动去delete. 1.vector 逻辑地址连续的一片内存空间,当空间不足,重新申请新的地址空间,将原有的数据复制过去,而新的地 ...
- Java学习----一个对象怎么调用另一个对象呢?
打包 jar cvfm test1.jar manifmest.mf teacher.class student.class test1.class 运行 java -jar test1.jar pu ...
- 使用Thinkphp框架开发移动端接口
本文给大家分享的是使用thinkphp框架开发移动端接口的2种方法,一种是开发API,另外一种是实现移动端访问自动切换移动主题模板,从而实现伪app访问,下面我们就来详细看下如何实现吧. 方案一:给 ...
- YII 验证功能
YII 表单的验证可以在module目录下的xxx.php里面定义验证方法,设定需要验证的字段就行 //用户表单验证,在模型里面设置一个方法,具体表单验证规则 public functi ...
- launchpad bzr
在lp注册 一个 lp ID, 比如 alangwansui 然后添加 SSH keys.为自己的管理添加权限. 注册一个项目的 比如 melody. 然后就可以开始使用bzr 在这个项目下建 ...
- 如何使用ASP.NET Web API OData在Oracle中使用Entity Framework 6.x Code-First方式开发 OData V4 Service
环境: Visual Studio 2013 + .Net Framework 4.5.2 1.新建项目 2.安装OData,ODP.NET 安装的包: 下面是部分代码: using System; ...