1双亲表示法(用数组进行存储):双亲表示法(顺序存储):每个结点中保存指向双亲的指针
#define MAX_TREE_SIZE 100 //树中最多结点数
typedef struct{ //树的结点定义
ElemType data;
int parent;
}PTNode;
typedef struct{
PTNode nodes [ MAX_TREE_SIZE 100 ];
int n;//结点数
}Ptree;
- 增:新增数据元素,无需按逻辑上的次序存储;(需要更改结点数
n
) - 删(叶子结点):① 将伪指针域设置为
-1
;②用后面的数据填补;(需要更改结点数n
) - 查询:①优点-查指定结点的双亲很方便;②缺点-查指定结点的孩子只能从头遍历,空数据导致遍历更慢;
2孩子表示法(顺序+链式)
struct CTNode{
int child; //孩子结点在数组中的位置
struct CTNode *next; // 下一个孩子
};
typedef struct{
ElemType data;
struct CTNode *firstChild; // 第一个孩子
}CTBox;
typedef struct{
CTBox nodes[MAX_TREE_SIZE];
int n, r; // 结点数和根的位置
}CTree;
3孩子兄弟表示法
typedef struct CSNode{
ElemType data; //数据域
struct CSNode *firstchild, *nextsibling; //第一个孩子和右兄弟指针, *firstchild 看作左指针,*nextsibling看作右指针
}CSNode. *CSTree;
如果存储树的话,可以将其转化成二叉树(二叉链表)进行存储。
将树转化成二叉树的方法是:左孩子右兄弟
树的遍历
先根遍历:若树非空,先访问根节点,再依次对每棵子树进行先根遍历;(与对应二叉树的先序遍历序列相同)
void PreOrder(TreeNode *R){
if(R!=NULL){
visit(R); //访问根节点
while(R还有下一个子树T)
PreOrder(T); //先跟遍历下一个子树
}
}
后根遍历:若树非空,先依次对每棵子树进行后根遍历,最后再返回根节点;(与对应二叉树的中序遍历序列相同)
void PostOrder(TreeNode *R){
if(R!=NULL){
while(R还有下一个子树T)
PostOrder(T); //后跟遍历下一个子树
visit(R); //访问根节点
}
}
层序遍历(队列实现):
- 先序遍历:等同于依次对各个树进行先根遍历;也可以先转换成与之对应的二叉树,对二叉树进行先序遍历;
- 中序遍历:等同于依次对各个树进行后根遍历;也可以先转换成与之对应的二叉树,对二叉树进行中序遍历;