树的一些基本概念
节点的度:结点所拥有的子树数。
树的度:树的所有结点度里面,结点度最大的那个度就是树的度。
有序树、无序树:如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树(自由树)。
森林:森林( Forest)是m(m>=0)棵互不相交的树的集合。对树中每个结点而言,其子树的集合即为森林。
二叉树:每个结点最多含有两个子树的树称为二叉树。
满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子节点都在同一层上,这样的又树称为满二叉树。
完全二叉树:对一个具有n个结点的二叉树按层序编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为i的结点位置完全相同,则这棵三叉树称为完全二叉树。
二叉树的性质1:在二叉树的第i层上至多有2^(i-1)个结点(i>=1)
二叉树的性质2:深度为k的二叉树至多有2^k-1个结点(k>=1)
二叉树的性质3:对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1
二叉树的性质4:具有n个结点的完全二叉树的深度为log₂n向下取整,然后+1
双亲表示法
双亲表示法的特点就是每一个节点里面除了存放节点数据之外,还存放着该节点的双亲节点位置。
#include<iostream>
#define maxTree 100
using namespace std;
typedef struct//双亲节点
{
string data;//节点数据
int parent;//节点的双亲节点下标
}Pparent;
typedef struct
{
Pparent nodes[maxTree];//节点数组
int r, n;//r存放根的位置,n代表节点数目
}Pnode;
孩子表示法
孩子表示法的特点就是每个节点除了存放节点数据,还存放该节点的孩子节点位置。
存放孩子有两种方式,一种就是最简单的。获取该树的度(也就是各子树中度最大的那个),然后设置孩子节点的数目为度的大小。不过该方法容易造成空间浪费。
另一种方法是用指针指向孩子节点,这样可以有效节省空间。(代码就是这种)
#include<iostream>
#define maxTree 100
using namespace std;
typedef struct//孩子节点
{
int chird;//孩子节点下标
Pchird* next;//下一个孩子节点指针
}*Pchird;
typedef struct//双亲节点
{
string data;//节点数据
Pchird firstChird;//表头节点的第一个孩子节点
}Pparent;
typedef struct
{
Pparent nodes[maxTree];//节点数组
int r, n;//r存放根的位置,n代表节点数目
}Pnode;
双亲孩子表示法
双亲孩子表示法的结构特点就是在每一个节点里面除了存放数据之外,还都存放着该节点的双亲节点的位置,也存放着该节点的孩子节点的位置。
#include<iostream>
#define maxTree 100
using namespace std;
typedef struct//孩子节点
{
int chird;//孩子节点下标
Pchird* next;//下一个孩子节点指针
}*Pchird;
typedef struct//双亲节点
{
string data;//节点数据
int parent;//节点的双亲节点下标
Pchird firstChird;//表头节点的第一个孩子节点
}Pparent;
typedef struct
{
Pparent nodes[maxTree];//节点数组
int r, n;//r存放根的位置,n代表节点数目
}Pnode;
总结
总的来说,各个表示法的实现方式大同小异。
利用数组和链表来实现树的存储结构是一种较好的存储方式。
三种方法中,双亲孩子表示法是最好的存储方式。