1.二叉树有如下特性:
(1)包含n(n>0)个元素的二叉树边数为n-1;
(2)若二叉树的高度为h,h≥0,则该二叉树最少有h个元素,最多有个元素;
(3)包含n个元素的二叉树的高度最大为n,最小为。
2. 完全二叉树的定义
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
3. 完全二叉树的性质
设完全二叉树中艺元素的序号为i,1≤i≤n。则有以下关系成立:
(1)当i=1时,该节点为二叉树的根。若i>1,则该节点的父节点编号为;
(2)当2i>n时,该节点无左子。否则,其左孩子的编号为2i;
(3)当2i+1>n时,该节点无右子。否则,其右孩子的编号为2i+1。
4. 二叉树的前序、中序、后序遍历
struct BinaryTreeNode{
int mdata;
BinaryTreeNode* leftChild;
BinaryTreeNode* rightChild;
};
//前序遍历
void PreOrder(BinaryTreeNode* r){
if(r == NULL){
return;
}
cout << r->mdata << endl;
PreOrder(r->leftChild);
PreOrder(r->rightChild);
}
//中序遍历
void MedianOrder(BinaryTreeNode* r){
if(r == NULL){
return;
}
MedianOrder(r->leftChild);
cout << r->mdata << endl;
MedianOrder(r->rightChild);
}
//后序遍历
void PostOrder(BinaryTreeNode* r){
if(r == NULL){
return;
}
PostOrder(r->leftChild);
PostOrder(r->rightChild);
cout << r->mdata << endl;
}
5. 树的层序遍历
树的层序遍历就是从根开始,从上到下,从左到右,依次把树里的元素遍历一遍。比如,按照层序遍历方式,下面的二叉树输出1->2->3->4->5->6。这种先进先出的形式很好地符合了队列(queue)的性质,因此先用队列来存储遍历到的元素是个不错的选择。
// 二叉树的层序遍历
void LayerOrder(BinaryTreeNode* r){
queue<BinaryTreeNode*> treenum;
treenum.push(r);
while(!treenum.empty()){
BinaryTreeNode* fro = treenum.front();
cout << fro->mdata << endl; //输出头部元素
treenum.pop();//删除头部元素
if(fro->leftChild != NULL)
treenum.push(fro->leftChild); //加入左子
if(fro->rightChild != NULL)
treenum.push(fro->rightChild); //加入右子
}
}
6. 二叉树的重构
只由一种方式的输出结果是不能重构出二叉树的,但是只要知道其中任意两种的输出结果,就能准确地重构出二叉树。比如得知前序遍历序列{1,2,4,7,3,5,6,8},中序遍历序列{4,7,2,1,5,3,8,6},根据两种输出方式的特点,就可以重构出二叉树如下:
由于前序遍历的输出方式为:根→左子树→右子树,中序遍历的输出方式为:左子树→根→右子树,所以,可以先由前序遍历的序列确定根节点,再由中序遍历序列确定根节点的左右子树,再递归地处理左右子树。
struct BinaryTreeNode{
int value;
BinaryTreeNode* left;
BinaryTreeNode* right;
};
//重构二叉树的核心函数
/*
参数说明:
start_preorder 为前序遍历序列首元素指针
end_preorder 为前序遍历序列尾后指针
start_inorder 为中序遍历序列首元素指针
start_inorder 为中序遍历序列尾后指针
返回:root 根节点
*/
BinaryTreeNode* ReconstructCore(int* start_preorder, int* end_preorder,
int* start_inorder, int* end_inorder){
if((end_preorder - start_preorder < 0) || (end_inorder - start_inorder < 0))
throw exception("Invalid Input.");
//前序遍历序列的首元素变为根节点
int root_value = start_preorder[0];
BinaryTreeNode* root = new BinaryTreeNode;
root->value = root_value;
root->left = NULL;
root->right = NULL;
if(end_preorder == start_preorder){
if(start_inorder == end_inorder && *start_preorder == *start_inorder)
return root; //二叉树中只有一个节点的情况
else
throw exception("Invalid Input.");
}
int* temp_inorder = start_inorder;
int len_left = 0;
for(; temp_inorder != end_inorder; ++temp_inorder,++len_left){
if(*temp_inorder == root_value){
//cout << *temp_inorder << endl;
break; //找出中序遍历序列中根节点所在的位置,以确定左右子树中的结点元素
}
if(temp_inorder == end_inorder && *temp_inorder != root_value){
throw exception("Invalid Input.");
}
}
//int len_left = temp_inorder - start_inorder;
int length = end_preorder - start_preorder;
if(len_left <= length){
if(len_left > 0 ){
//递归地重构左子树
root->left = ReconstructCore(start_preorder+1, start_preorder+len_left, start_inorder,temp_inorder-1);
}
int len_right = length - len_left;
if(len_right > 0){
//递归地重构右子树
root->right = ReconstructCore(start_preorder+len_left+1, end_preorder,temp_inorder + 1,end_inorder);
}
}
return root;
}
//重构二叉树的主函数
/*
参数说明:
preorder 为前序遍历序列
inorder 为中序遍历序列
length 树中的结点个数
返回:root 根节点
*/
BinaryTreeNode* ReconstructTree(int* preorder, int* inorder, int length){
if(preorder == NULL || inorder == NULL || length < 0)
return NULL;
return ReconstructCore(preorder,preorder+length-1,inorder,inorder+length-1);
}
int main()
{
int pre[8] = {1,2,4,7,3,5,6,8}; //前序遍历序列
int ino[8] = {4,7,2,1,5,3,8,6}; // 中序遍历序列
BinaryTreeNode* root = ReconstructTree(pre,ino,8);
cout << root->left->value << endl;
return 0;
}
7. 其他,创建了一个二叉树的类,实现了简单的计算叶子数,树的高度,判断节点是否在树中等功能。
class BinaryTreeNode{
private:
int data;
BinaryTreeNode* left, *right;
public:
BinaryTreeNode(int num,BinaryTreeNode* l = NULL,BinaryTreeNode* r = NULL)
:data(num),left(l),right(r){}
BinaryTreeNode(){}
BinaryTreeNode(const BinaryTreeNode& oldnode){
data = oldnode.data;
left = new BinaryTreeNode;
right = new BinaryTreeNode;
left = oldnode.left;
right = oldnode.right;
}
~BinaryTreeNode(){delete left,right;}
public:
void set_data(int item){
data = item;
}
int get_data()const{
return data;
}
void set_left(BinaryTreeNode* l){
left = l;
}
BinaryTreeNode* get_left()const{
return left;
}
void set_right(BinaryTreeNode* r){
right = r;
}
BinaryTreeNode* get_right()const{
return right;
}
BinaryTreeNode& operator= (const BinaryTreeNode& oldnode){
if(this == &oldnode)
return *this;
if(left != NULL)
delete left;
if(right != NULL)
delete right;
data = oldnode.data;
left = new BinaryTreeNode;
right = new BinaryTreeNode;
left = oldnode.left;
right = oldnode.right;
return *this;
}
};
class BinaryTree{
private:
BinaryTreeNode* root;
public:
BinaryTree(BinaryTreeNode* t = NULL):root(t){}
~BinaryTree(){delete root;}
public:
void set_root(BinaryTreeNode* t){
root = t;
}
BinaryTreeNode* get_root()const{
return root;
}
BinaryTreeNode* Create_Tree();
void PreOeder(BinaryTreeNode* t);
int Get_leaf_num(BinaryTreeNode* t) const;
int Get_tree_height(BinaryTreeNode* t)const;
bool is_in_tree(BinaryTreeNode *r,BinaryTreeNode *t) const;
int Get_node_num(BinaryTreeNode* r) const;
void Delete(BinaryTreeNode* r);
};
BinaryTreeNode* BinaryTree::Create_Tree(){
char item;
BinaryTreeNode *t,*t_l,*t_r;
cin>>item;
if(item != '#')
{
BinaryTreeNode *pTmpNode = new BinaryTreeNode(item-48);
t = pTmpNode;
t_l = Create_Tree();
t->set_left(t_l);
t_r = Create_Tree();
t->set_right(t_r);
return t;
}
else
{
t = NULL;
return t;
}
}
void BinaryTree::PreOeder(BinaryTreeNode* t){
if(t != NULL){
cout << t->get_data() << " ";
PreOeder(t->get_left());
PreOeder(t->get_right());
}
}
int BinaryTree::Get_leaf_num(BinaryTreeNode* t) const{
if(t == NULL)
return 0;
if(t->get_left() == NULL && t->get_right() == NULL)
return 1;
return Get_leaf_num(t->get_left())+Get_leaf_num(t->get_right());
}
int BinaryTree::Get_tree_height(BinaryTreeNode* t) const{
if(t == NULL)
return 0;
if(t->get_left() == NULL && t->get_right() == NULL)
return 1;
return max(Get_tree_height(t->get_left()),Get_tree_height(t->get_right()))+1;
}
bool BinaryTree::is_in_tree(BinaryTreeNode *r,BinaryTreeNode *t) const{
if(r == NULL)
return false;
if(r == t)
return true;
bool isintree = false;
if(r->get_left() != NULL){
isintree = is_in_tree(r->get_left(),t);
}
if(!isintree && r->get_right() != NULL){
isintree = is_in_tree(r->get_left(),t);
}
return isintree;
}
int BinaryTree::Get_node_num(BinaryTreeNode* r) const{
if(r == NULL)
return 0;
if(r->get_left() == NULL && r->get_right() == NULL)
return 1;
return Get_node_num(r->get_left()) + Get_node_num(r->get_right()) + 1;
}
待续。。。