0.目录
1.树的定义与操作
2.树的存储结构与实现
3.小结
1.树的定义与操作
树是一种非线性的数据结构:
- 树是由 n ( n ≥ 0 ) 个结点组成的有限集合
- 如果 n = 0,称为空树;
- 如果 n > 0,则:
树的示例:
树中度的概念:
- 树的结点包含一个数据及若干指向子树的分支
- 结点拥有的子树数目称为结点的度
- 度为 0 的结点称为叶结点
- 度不为 0 的结点称为分支结点
- 树的度定义为所有结点中度的最大值
树的度示例:度为 3 的树
树中的前驱和后继:
- 结点的直接后继称为该结点的孩子
- 相应的,该结点称为孩子的双亲
- 结点的孩子的孩子的......称为该结点的子孙
- 相应的,该结点称为子孙的祖先
- 同一个双亲的孩子之间互称兄弟
树的前驱和后继示例:
树中结点的层次:
- 根为第1层
- 根的孩子为第2层
- ......
树中结点的最大层次称为树的深度或高度
树的有序性:
- 如果树中结点的各子树从左向右是有次序的,子树间不能互换位置,则称该树为有序树,否则为无序树。
森林的概念
- 森林是由 n ( n ≥ 0 ) 棵互不相交的树组成的集合
树的一些常用操作:
- 将元素插入树中
- 将元素从树中删除
- 获取树的结点数
- 获取树的高度
- 获取树的度
- 清空树中的元素
- 。。。
树在程序中表现为一种特殊的数据类型:
树中的结点也表现为一种特殊的数据类型:
树与结点的类关系:
在StLib中定义TreeNode类和Tree类:
TreeNode.h
#ifndef TREENODE_H
#define TREENODE_H
#include "Object.h"
namespace StLib
{
template <typename T>
class TreeNode : public Object
{
public:
T value;
TreeNode<T>* parent;
TreeNode()
{
parent = NULL;
}
virtual ~TreeNode() = 0;
};
template <typename T>
TreeNode<T>::~TreeNode()
{
}
}
#endif // TREENODE_H
Tree.h
#ifndef TREE_H
#define TREE_H
#include "TreeNode.h"
#include "SharedPointer.h"
namespace StLib
{
template <typename T>
class Tree : public Object
{
protected:
TreeNode<T>* m_root;
public:
Tree() { m_root = NULL; }
virtual bool insert(TreeNode<T>* node) = 0;
virtual bool insert(const T& value, TreeNode<T>* parent) = 0;
virtual SharedPointer< Tree<T> > remove(const T& value) = 0;
virtual SharedPointer< Tree<T> > remove(TreeNode<T>* node) = 0;
virtual TreeNode<T>* find(const T& value) const = 0;
virtual TreeNode<T>* find(TreeNode<T>* node) const = 0;
virtual TreeNode<T>* root() const = 0;
virtual int degree() const = 0;
virtual int count() const = 0;
virtual int height() const = 0;
virtual void clear() = 0;
};
}
#endif // TREE_H
2.树的存储结构与实现
本节目标:
- 完成树和结点的存储结构设计
设计要点:
- GTree 为通用树结构,每个结点可以存在多个后继结点
- GTreeNode 能够包含任意多指向后继结点的指针
- 实现树结构的所有操作 ( 增,删,查,等 )
GTreeNode 的设计与实现:
GTree 的设计与实现:
GTree ( 通用树结构 ) 的实现架构:
在StLib中定义GTreeNode类和GTree类,搭建基本框架:
GTreeNode.h
#ifndef GTREENODE_H
#define GTREENODE_H
#include "TreeNode.h"
#include "LinkList.h"
namespace StLib
{
template <typename T>
class GTreeNode : public TreeNode<T>
{
public:
LinkList<GTreeNode<T>*> child;
};
}
#endif // GTREENODE_H
GTree.h
#ifndef GTREE_H
#define GTREE_H
#include "Tree.h"
#include "GTreeNode.h"
namespace StLib
{
template <typename T>
class GTree : public Tree<T>
{
public:
bool insert(TreeNode<T>* node)
{
bool ret = true;
return ret;
}
bool insert(const T& value, TreeNode<T>* parent)
{
bool ret = true;
return ret;
}
SharedPointer< Tree<T> > remove(const T& value)
{
return NULL;
}
SharedPointer< Tree<T> > remove(TreeNode<T>* node)
{
return NULL;
}
GTreeNode<T>* find(const T& value) const
{
return NULL;
}
GTreeNode<T>* find(TreeNode<T>* node) const
{
return NULL;
}
GTreeNode<T>* root() const
{
return dynamic_cast<GTreeNode<T>*>(this->m_root);
}
int degree() const
{
return 0;
}
int count() const
{
return 0;
}
int height() const
{
return 0;
}
void clear()
{
this->m_root = NULL;
}
~GTree()
{
clear();
}
};
}
#endif // GTREE_H
问题:
- 每个树结点中为什么包含指向前驱结点的指针?
根结点 → 叶结点:非线性数据结构
叶结点 → 根节点:线性数据结构 ( 链表 )
3.小结
- 树是一种非线性的数据结构
- 结点拥有唯一前驱 ( 父结点 ) 和若干后继 ( 子结点 )
- 树的结点包含一个数据及若干指其它结点的指针
- 树与结点在程序中表现为特殊的数据类型