之前有写过关于树和二叉树的(K, R)逻辑关系,即每个节点(除根节点)有唯一前驱和多个后继。
完全二叉树有一个比较好的性质
注意,在顺序存储中不需要花额外存储记录数据之间的关系。
但是需要将非完全二叉树补成完全二叉树
关于树的存储结构
树多用链式存储结构,不过也可以用顺序存储结构。
这里先说说链式存储
- 存储数据和数据之间的关系
- 数据之间的关系用指针来记录
- 数据与关系封装在一个类中:BinaryTreeNode;
//具体BinaryTreeNode类的抽象数据类型如下
//这是根据你如何使用这个Node来定义你的内置函数
//我写一个一般化的BinaryTreeNode类
//但是具体问题需要更改函数的设置方式
template<typename T>
class BinaryTreeNode{
private:
T item;
BinaryTreeNode<T>* leftChild;
BinaryTreeNode<T>* rightChild;
public:
//这是默认构造函数
BinaryTreeNode(){}
//构造函数
BinaryTreeNode(const T& a, BinaryTreeNode<T>* l = NULL
,BinaryTreeNode<T>* r = NULL){
this->item = a;
leftChild = l;
rightChild = r;
}
//返回左右节点的指针
BinaryTreeNode<T>* getLeftChild() const{
return leftChild;
}
BinaryTreeNode<T>* getRightChild() const{
return rightChild;
}
//返回数据域
const T& getItem(){
return item;
}
//修改数据域
void setItem(const T& a){
item = a;
}
};
再看看顺序存储
完全二叉树有一个比较好的性质
- 将完全二叉树从上到下,从左到右标号
- 任意节点和它的前驱后继之间满足一个代数关系
注意,在顺序存储中不需要花额外存储记录数据之间的关系。
但是需要将非完全二叉树补成完全二叉树
//这是一个完全二叉树的顺序存储抽象数据类型
//包含访问孩子节点,访问父节点
//通过一个数组将树的元素输入
template<class T>
class ArrayTree{
private:
T*[] arr; //这是用来存储每个节点的指针,可以节省空间开销
int count; //这是用来记录存储节点的个数,包括补上的虚节点
public:
//默认构造函数
ArrayTree(){count = 0;}
//构造函数
ArrayTree(const T * a , int a){
for(int i = 0, i < a; i++){
arr[i] = &a[i];
}
count = a
}
//返回第i个节点的左右孩子
int getLeftChild(int i){ return 2*i+1;}
int getRightChild(int i){ return 2*i+2;}
int getParent(int i){return (i - 1)/2;}
//访问第i个节点
T getMe(int i){return *arr[i];}
//修改第i个节点
void setMe(int I, const T val){ *arr[i] = val;}
};
注:代码只是示例,并不能运行,而且有错。