概念:
n(n>=0) 个节点构成的有限集合
- 空树
- n = 0
- 非空树
- 有一个根节点
- 其余节点分为m(m>0)个互不相交的有限集,每个集合本身也是树
非树:
树:
特点:
- 子树不相交
- 除了根节点外,每个节点有且仅有一个父节点
- n个节点的树有n-1条边
基本术语:
- 节点的度(Degree):一个节点的子节点的个数
- 树的度:树中,最大的节点的度
- 叶节点(Leaf):度为0的节点
- 父节点(Parent):有子树的节点,且是子树的的根节点
- 子节点(Child):A是B的父节点,则B是A的子节点
- 兄弟节点(Sibling):具有同一父节点的各节点彼此是兄弟节点
- 路径:从节点n到nk的路径为一个节点序列
- 路径长度:路径中所包含边的个数为路径长度
- 祖先节点(Ancestor):沿树根到某个节点上的所有节点都是这个节点的祖先节点
- 子孙节点(Descendant):某一节点的子树中所有节点是这个节点的子孙
- 节点的层次(Level):规定根节点在1层,其他任意节点是其分节点的层数+1
- 树的深度(Depth):树中所有节点中的最大层次是这颗树的深度
存储方式:
- 数组:
通常的树很难用数组表示(二叉树除外) - 链表:
这种方式构建链表,发现链表中的指针数量是根据整个树的度来决定的,当前树的度是3,也就是每个节点都有3个指针,如果一个节点中没有子节点,那么他会浪费会浪费很多空间
优化:儿子-兄弟表示法(类似于二叉树)
也就是左边放置子节点,右边放置兄弟节点
简单的实现:
根据给的节点
{
(‘A’, ‘B’),(‘A’, ‘C’),(‘A’, ‘D’)
(‘B’, ‘E’),(‘B’, ‘F’)
(‘C’, ‘G’)
(‘D’, ‘H’),(‘D’, ‘I’),(‘D’, ‘J’)
(‘E’, ‘K’),(‘E’, ‘L’)
(‘H’, ‘M’)
}
注:下面实现不包括值相同的节点,即B->B,这种操作不行,需要添加标志,注明节点的顺序
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
// 节点结构
struct TreeNode
{
char value;
TreeNode* child;
TreeNode* nextBrother;
TreeNode(char val):value(val), child(NULL), nextBrother(NULL)
{}
};
// 树
class Tree
{
public:
TreeNode* root;
Tree() {}
~Tree();
void CreateTree(std::map<int, std::map<char, char>> data); // 创建树
void DestroyNode(TreeNode* node); // 销毁树
TreeNode* GetNodeByVal(TreeNode* node, char val); // 根据值获取节点
};
void Tree::CreateTree(map<int, map<char, char>> data)
{
TreeNode* node = NULL;
for (int i = 0;i < data.size();i++)
{
map<char, char>::iterator iter = data[i].begin();
node = GetNodeByVal(node, iter->first);
if ( node == NULL)
{
node = new TreeNode(iter->first);
if (i == 0)
{
root = node;
}
}
if (node->child == NULL)
{
node->child = new TreeNode(iter->second);
}
else
{
TreeNode** next = &(node->child->nextBrother);
while (*next != NULL)
{
next = &((*next)->nextBrother);
}
*next = new TreeNode(iter->second);
}
}
}
TreeNode* Tree::GetNodeByVal(TreeNode* node, char val)
{
if (node == NULL || (node!=NULL && node->value == val))
{
return node;
}
TreeNode* cNode = GetNodeByVal(node->child, val);
if (cNode != NULL)
{
return cNode;
}
else
{
TreeNode* bNode = GetNodeByVal(node->nextBrother, val);
return bNode;
}
}
Tree::~Tree()
{
DestroyNode(root);
}
void Tree::DestroyNode(TreeNode* node)
{
TreeNode* child = NULL;
TreeNode * brother = NULL;
if (node == NULL)
{
return;
}
child = node->child;
brother = node->nextBrother;
delete node;
node = NULL;
DestroyNode(child);
DestroyNode(brother);
}
int main()
{
map<int, map<char, char>> data;
data[0].insert(pair<char, char>('A', 'B'));
data[1].insert(pair<char, char>('A', 'C'));
data[2].insert(pair<char, char>('A', 'D'));
data[3].insert(pair<char, char>('B', 'E'));
data[4].insert(pair<char, char>('B', 'F'));
data[5].insert(pair<char, char>('C', 'G'));
data[6].insert(pair<char, char>('D', 'H'));
data[7].insert(pair<char, char>('D', 'I'));
data[8].insert(pair<char, char>('D', 'J'));
data[9].insert(pair<char, char>('E', 'K'));
data[10].insert(pair<char, char>('E', 'L'));
data[11].insert(pair<char, char>('H', 'M'));
Tree t;
t.CreateTree(data);
// t.DestroyNode(t.root); 测试是否删除
system("pause");
return 0;
}