1.双亲表示法
采用一组连续空间来存储每个结点,同时每个结点总增设一个伪指针,指向其父结点在数组中的位置。
好查父结点,不好查儿子结点(需要遍历整个数组)。
存储结构的代码描述:
#define MAX_TREE_SIZE 100 //树中最多结点数
typedef struct{ //树的结点的定义
ElemType data; //数据元素
int parent; //父结点位置域
}PTNode;
typedef struct{ //树的类型定义
PTNode nodes[MAX_TREE_SIZE]; //双亲表示法的顺序存储结构
int n; //树中的结点数
}PTree;
2.孩子表示法
将每个结点的孩子们存在一张线性表中,以单链表为存储结构;
而头指针们又构成一张线性表,为便于查找,以顺序存储结构;
好查儿子结点,不好查父结点(需要遍历孩子链表)。
存储结构的代码描述:
#include <stdio.h>
#include <stdlib.h>
// 定义孩子结点
typedef struct ChildNode {
int data; // 结点数据
struct ChildNode* next; // 指向下一个孩子结点的指针
} ChildNode;
// 定义树结点
typedef struct TreeNode {
int data; // 结点数据
ChildNode* firstChild; // 指向第一个孩子结点的指针
} TreeNode;
// 定义树的头指针数组
typedef struct Tree {
TreeNode** roots; // 根结点数组
int rootCount; // 根结点数量
} Tree;
// 创建新结点
TreeNode* createNode(int data) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->data = data;
newNode->firstChild = NULL;
return newNode;
}
// 添加孩子结点
void addChild(TreeNode* parent, int childData) {
ChildNode* newChild = (ChildNode*)malloc(sizeof(ChildNode));
newChild->data = childData;
newChild->next = parent->firstChild;
parent->firstChild = newChild;
}
// 创建树
Tree* createTree(int rootCount) {
Tree* tree = (Tree*)malloc(sizeof(Tree));
tree->roots = (TreeNode**)malloc(rootCount * sizeof(TreeNode*));
tree->rootCount = rootCount;
return tree;
}
// 示例使用
int main() {
Tree* tree = createTree(2); // 创建树,包含2个根结点
tree->roots[0] = createNode(1);
tree->roots[1] = createNode(2);
addChild(tree->roots[0], 3); // 给第一个根结点添加孩子
addChild(tree->roots[0], 4); // 添加另一个孩子
// 打印根结点数据
for (int i = 0; i < tree->rootCount; i++) {
printf("Root %d: %d\n", i + 1, tree->roots[i]->data);
}
// 释放内存(略)
return 0;
}
3.孩子兄弟表示法
又称二叉树表示法,即以二叉链表作为树的存储结构。孩子兄弟表示法使每个结点包括三部分:指向第一个孩子结点的指针域,该结点的结点值,兄弟结点的指针域(沿此域可以找到该结点的所有兄弟结点)。
找儿子简单,找爹难(要是不设额外的父结点指针的话),优点是利于树转换为二叉树的操作。
存储结构的代码描述:
typedef struct CSNode{ //树的结点的定义
ElemType data; //数据元素
struct CSNode *firstchild,*nextsibling //第一个孩子和右兄弟指针
}CSNode,*CSTree;