这一章节开始介绍一个数据结构中的一个基本概念——树。
我们从数据结构的解读来解释树结构的重要性,现实世界的数据除了最基本的线性结构(我们常用队列、数组和链表等结构表征),还有一个重要的特性——层级结构需要我们去表征,例如世界杯的对阵表、遗传系谱图等等,这时候我们基于对现实世界的抽象,会很自然的理解为什么会有树这样一个数据结构。
而树这种数据结构也是能够分类的,我们将每个节点记录某种抽象的概念或者具象的事物,这样用来表征一种从属关系,我们称其为抽象型数据结构的树。或者将每个节点储存一些数据,基于这棵树我们能够完成检索查找之类的操作,我们称其为检索型数据结构的树。
关于树的基本的术语和其中的基本概念,这里不再累述,读者可以通过查找离散数学或者图论的资料了解。
树的实现:
既然了解到了树存在的必要性和重要性,下面我们就应该去关注怎样实现一棵树了。在《啊哈算法》中,作者介绍了用一维数组实现的二叉树,这是基于二叉树一些非常特殊的形式,但是对于更加一般的情况的多叉树呢?我们需要采用更加一般的方法。对于树中的每一个节点,我们很关注如下集合很有价值的数据:它的父节点?它的子节点?存在该节点的数据?关于它的父节点和子节点,其实就是需要我们表征一种“联系”,即通过该节点,我们能够轻松的找到和它关联的父节点和子节点,我们很容易便可以想到指针。而基于一维数组实现的二叉树,就是二叉树的基本性质,通过为节点标号从而实现了指针的作用。
通过上面的分析,我们能够定义树节点的结构体。
struct Treenode { <data> TreeNode* parent; vector<TreeNode*> children; };
树的遍历:
树本质上也是一种图,因此这里采用基本的深搜就可以完成对树的遍历。
void printLabels(TreeNode* root) { cout<< root-> <data><<endl; for(int i = 0;i < root->chilren.size();i++) printLabels(root->children[i]); }
基于对树的遍历,我们同时可以完成对树的高度的计算。
int height(TreeNode* root) { int h = 0; for(int i = 0;i < root->children.size();i++) h = max(h,1+height(root->children[i])); return h; }
时间: 2024-10-13 22:24:34