这一章节开始介绍一个数据结构中的一个基本概念——树。

我们从数据结构的解读来解释树结构的重要性,现实世界的数据除了最基本的线性结构(我们常用队列、数组和链表等结构表征),还有一个重要的特性——层级结构需要我们去表征,例如世界杯的对阵表、遗传系谱图等等,这时候我们基于对现实世界的抽象,会很自然的理解为什么会有树这样一个数据结构。

而树这种数据结构也是能够分类的,我们将每个节点记录某种抽象的概念或者具象的事物,这样用来表征一种从属关系,我们称其为抽象型数据结构的树。或者将每个节点储存一些数据,基于这棵树我们能够完成检索查找之类的操作,我们称其为检索型数据结构的树。

关于树的基本的术语和其中的基本概念,这里不再累述,读者可以通过查找离散数学或者图论的资料了解。

树的实现:

既然了解到了树存在的必要性和重要性,下面我们就应该去关注怎样实现一棵树了。在《啊哈算法》中,作者介绍了用一维数组实现的二叉树,这是基于二叉树一些非常特殊的形式,但是对于更加一般的情况的多叉树呢?我们需要采用更加一般的方法。对于树中的每一个节点,我们很关注如下集合很有价值的数据:它的父节点?它的子节点?存在该节点的数据?关于它的父节点和子节点,其实就是需要我们表征一种“联系”,即通过该节点,我们能够轻松的找到和它关联的父节点和子节点,我们很容易便可以想到指针。而基于一维数组实现的二叉树,就是二叉树的基本性质,通过为节点标号从而实现了指针的作用。

通过上面的分析,我们能够定义树节点的结构体。

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-树的实现和遍历的更多相关文章

  1. 算法问题实战策略 PICNIC

    下面是另一道搜索题目的解答过程题目是<算法问题实战策略>中的一题oj地址是韩国网站 连接比较慢 https://algospot.com/judge/problem/read/PICNIC ...

  2. 《算法问题实战策略》-chaper7-穷举法

    关于这一章节<算法实战策略>有一段概述问题,我认为对于编程人员来说非常有价值,故在这里进行如下的摘抄: 构想算法是很艰难的工作.相比大家都经历过,面对复杂的要求只是傻乎乎地盯着显示器,或者 ...

  3. 《算法问题实战策略》-chaper13-数值分析

    这一章节主要介绍我们在进行数值分析常用的二分.三分和一个近似求解区间积分的辛普森法. 首先介绍二分. 其实二分的思想很好理解并且笔者在之前的一些文章中也有所渗透,对于二次函数甚至单元高次函数的零点求解 ...

  4. 《算法问题实战策略》-chaper32-网络流

    基本的网络流模型: 在图论这一块初步的应用领域中,两个最常见的关注点,其一时图中的路径长度,也就是我们常说的的最短路径问题,另一个则是所谓的“流问题”. 流问题的基本概念: 首先给出一张图. 其实所谓 ...

  5. 算法问题实战策略 MEETINGROOM 附一份tarjan模板

    地址 https://algospot.com/judge/problem/read/MEETINGROOM 解答  2-sat 代码样例过了 没有ac. 我又没有正确代码对拍..... 已确认是输出 ...

  6. 《算法问题实战策略》——chaper9——动态规划法技巧

    Q1: 数字游戏: 两个人(A.B)用n个整数排成的一排棋盘玩游戏,游戏从A开始,每个人有如下操作: (1)    拿走棋盘最右侧或者最左侧的棋子,被拿走的数字从棋盘中抹掉. (2)    棋盘中还剩 ...

  7. 《算法问题实战策略》-chaper8-动态规划法

    Q1:偶尔在电视上看到一些被称为“神童”的孩子们背诵小数点以后几万位的圆周率.背诵这么长的数字,可利用分割数字的方法.我们用这种方法将数字按照位数不等的大小分割后再背诵. 分割形式如下: 所有数字都相 ...

  8. 《算法问题实战策略》-chaper14-整数论

    Lucas定理: 在组合计数问题中,我们常面临组合数C(n,m)过大而无法直接计算的困境,那么这里的Lucas定理给出了一个较大组合数进行取余运算的一种递归算法. 什么是Lucas定理? Lucas定 ...

  9. 算法问题实战策略 QUADTREE

    地址 https://algospot.com/judge/problem/read/QUADTREE 将压缩字符串还原后翻转再次压缩的朴素做法 在数据量庞大的情况下是不可取的 所以需要在压缩的情况下 ...

随机推荐

  1. 记一次网站服务器迁移(my)

    遇到的难题: 基本没有遇到太大的问题,因为服务器环境是配好的阿里云环境,最后再nginx的rewrite配置遇到了一点问题,最后也算解决. 收获小点: 1) vim替换命令: 利用 :s 命令可以实现 ...

  2. 类 Array Arraylist List Hashtable Dictionary

    总结C# 集合类 Array Arraylist List Hashtable Dictionary Stack Queue  我们用的比较多的非泛型集合类主要有 ArrayList类 和 HashT ...

  3. CentOS 7重装mysql编译过程报错解决方法

    错误记录: [ 82%] Building C object libmysql/CMakeFiles/clientlib.dir/__/sql-common/client.c.o/usr/local/ ...

  4. 文字排版--删除线(text-decoration:line-through)

    如果想在网页上设置删除线怎么办,这个样式在电商网站上常会见到: 上图中的原价上的删除线使用下面代码就可以实现: .oldPrice{text-decoration:line-through;}

  5. Linux抓包工具tcpdump详解

    tcpdump是一个用于截取网络分组,并输出分组内容的工具,简单说就是数据包抓包工具.tcpdump凭借强大的功能和灵活的截取策略,使其成为Linux系统下用于网络分析和问题排查的首选工具. tcpd ...

  6. WebDriverWait 中 and, or, not用法

    1. And 用法 wait.until(ExpectedConditions.and( ExpectedConditions.visibilityOfAllElementsLocatedBy(By. ...

  7. [Windows] php开发工具,zendstudio13使用方法补丁

    官网原版下载 http://downloads.zend.com/studio ... win32.win32.x86.exe 破解补丁: 链接:http://pan.baidu.com/s/1gdi ...

  8. WAMP学习日记之:Apache发布php网站

    1.修改httpd.conf 文件,以便让Apache和php模块建立关联 2.配置php.ini文件 修改httpd.conf 文件,以便让Apache和php模块建立关联 如何让apache和ph ...

  9. Unix/Linux 'dirctory tree' command.

    ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/' It se ...

  10. Android 之夜间模式(多主题)的实现

    引言 夜间模式其实属于多主题切换的一种,不过是最麻烦的一种.因为在夜间模式下不仅要切换主色调,次要色调等等,还要覆盖一些特殊的颜色,因为在夜间模式下总不能什么都是黑的把,那不得丑死-.-,所以当你夜间 ...