C++ Tree

树是一种十分重要, 应用十分广范的数据结构。 下面我们介绍Tree。

Data structures 大致可以分为线性数据结构(Linear data structures)和非线性的数据结构。

线性数据结构主要有: 数组(Array), 链表(linked list), 栈(stack, 即LIFO), 队列(queue, 即FIFO)。

 

首先需要明确为什么上述的数据结构成为线性的(Linear)?  因为data is arranged in a sequential  manner。 上述的所有的几种data structures均有一个logical start和一个logical end, 然后其中的collections  中的element均有一个next  element和一个previous element。 故而我们说我们的数据结构是Linear的或者sequential的arrangement.

但是如何决定选择一个data structure 去使用呢? 通常要选择合适的data structure 需要考虑(权衡)如下几个因素:

(1) What needs to be stored?

(2) cost of operations

(3) memory storage

(4)ease of implementations

 

树(tree)代表着第二种类型的数据结构, 即非线性的数据结构(NoneLinear data structures)。 其他的非线性的数据结构还有图(graph)等。

tree 是用于represent  hierarchical data(层次数据) 的一种非线性的数据结构。 例如我们用树去表示一个organization 中的employees的层次(职位)。

如上图, John是CEO, 他有两个direct reports, ... 等等。 这就是一棵树。 是一个倒立的“树“:

 

所以John 是树的根(root)。

对于树这个数据结构, 能够自然而然而且很高效的的represent 那些本身就具有层次的数据(hierarchical data)。 除了这个用途外, 树这个数据结构也适合用于代表具有逻辑的数据。 树可以被定义为一个logical model。 可以被视为a collections of entities called nodes linked together ro simulate hierarchy (模拟层次).

树是一个非线性的数据结构, 或者更确切的说, 是一个hierarchical structures。 最上面的一个节点称为树的根(root)。 每一个节点代表我们的数据。 数据可以使任何类型(包括class, struct等用户自定义的类型。

例如在上面标示组织成员层次职位关系的时候, 每一个节点具有两个data fields(不考虑左右两个link fields, 指向这个节点的children), 一代表个是职位, 一个是对应的名字。

 

例如, 下面为了说明, 做的标记, 节点1是节点2 和3 的parent(关系是亲子关系, parent-child relationships), 节点2和节点3 的关系是siblings。

 

没有child 的节点被称为叶子节点(leaf)。

上图的黑色的节点均为leaf node, 橘红的节点表示internal nodes。

 

一般而言, 如果我们能够从一个节点A沿着link 的方向走向B(注意是单方向的, 箭头方向), 我们就说节点A是节点B的祖先(ancestor)。 NOTE: 对于一树结构, 如果两个节点有个path, 那么这个path 是唯一的。 这是树的一个很重要的性质。

B是A的后代(descendent):

再比如:

上图中, 我们可以说可以从根节点沿着link 的方向走到10号节点。

Q: 节点4 和节点10 的共同的祖先是谁

A: 节点1和2

 

Q: 节点5 和节点7是否为sibling

A: 不是的, 二者是cousin。

 

从数的结构来看, 不难发现, 是一个具有递归结构的数据结构(a recursive data structures) , 这一点很重要。 这意味着后面我们的大多数的处理都会应用到树的递归结构。

 

上面图中, 左边的树的根节点(红色节点)具有两个子树(subtrees), 一个是左子树(left subtrees), 一个是右子树(right subtrees)。  左边的那棵树结构不是二叉树(binary tree), 根节点有三棵树。

然后递归的, 我们进一步我们将上面左边的子树的根节点为2, 也用红色表示:

对于left subtrees , 根节点为2, 具有三个新的子树(subtrees) 等等, 依次递归定义下去, 最终我们得到我们想要的一棵树。 这就是递归, 将一颗复杂的书最终reduce 为base case, 也就是最简单的一棵树(没有节点了)。

除了树的这种具有递归的性质, 树的另一个重要的性质就是: 具有N个节点的树, 将会具有N-1个edges(或者links)。除了根节点以外, 其余所有的节点都有唯一的一个

incoming edges. 例如下图的节点2, 就具有唯一的一个incoming edges, 但是这个节点有三个outgoing links。  也就是说, N个节点的树具有N-1 个edges(根节点没有incoming edge)。

 

 

 

有了上面的性质, 下面我们定义树中某个节点x的Depth(x)(深度)和Height(x)(高度):

某个节点的深度就是从根节点到这个节点的路径(由于是树, 存在且唯一)边的长度。

Q: 节点4 和几点9 的深度:

A: depth(4) = 2, depth(9) = 3。

 

下面说说某个节点高度的定义:就是节点到叶子节点(注意, 这里并没有确定一个叶子, 所以路径有很多, 我们选择的是哪条最长的路径)最长的路径。

 

Q: 根节点的高度, 3 的深度, 任意一个叶子节点的深度:

height(1)  = 3, height(3) = 2, height(leaf) = 0 , 也就是说任何一个叶子节点的高度是0.

 

下面我们定义一棵树的深度: 一棵树的深度就是树的根节点的高度:

所以下图的树的高度是3:

 

 

另外, 树也可以分为简单的树和复杂的树。

如果一个树的任何一个节点至多有2 children, 我们就说这棵树是二叉树(binary tree).。 二叉树比较简单, 使用最广泛:

我们常常创建二叉树的办法是动态分配内存的方式创建一个新的节点, 然后使用指针或者refere 将这些连点链接起来。 每一个节点有三个field, 一个是指向左边的child node 的指针, 一个是存储着这个节点的数据, 一个指向右边孩子节点的指针。

 

 

对于二叉树(只需两个link field), C++编程上, 我们可以定义节点的类型为一个结构体如下:

具体的, 如下:

 

 

最后, 说说树这种数据结构的主要用途(applications):

(1)storing naturally hierarchical data structures, 例如 file system in your disc drive(想想文件, 文件夹啥的).

(2) organizing data,: for quick search, insertion, deletion等等。 例如对于BST(binary search tree), 可以实现二分法查找(O(n log n)), 排序等等问题。

(3)Trie - 即用于dictionary,

(4)network routing algorithm(网络路由算法)。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值