关闭

二叉树的C++模板类头文件源代码实现

标签: 二叉树链式存储头文件
1322人阅读 评论(0) 收藏 举报

顺序存储的二叉树结构利用数组给满二叉树进行编号,而实际情况中的二叉树不满足满二叉树和完全二叉树,因此会导致内存空间的浪费,所以本文采用链表的存储方式,定义树节点结构体,包含数据和两个左右儿子指针。类的成员变量只有树的根节点,成员函数包括插入、前中后序遍历,这里遍历的方式采用经典的递归遍历,递归遍历的方式容易理解一些,非递归的方法需要利用栈结构保存父节点,这是下一步实现的内容。

通过编辑增加了二叉树非递归成员函数,非递归的前序和中序遍历比较容易实现,分别在入栈和出栈的时候访问数据,在实际操作当中的关键问题理解,个人感觉主要是嵌套的两层while循环,内层循环用于树的左节点的访问并将其压入栈中,外层循环用于访问右节点和弹出栈中存储节点,解决这个问题就能理解非递归了。对于非递归后续遍历需要对栈中数据根据是否访问了有节点进行标记,从而在访问右节点之后打印数据,代码实现以后再更新吧。

再次更新的内容为非递归后续遍历的方法,其实就是在非递归前序和中序遍历方法基础上,增加一个标记栈,记录遍历过程中是否已经访问了右节点,当树节点入栈的时候,未访问标记布尔变量入栈,当访问了右节点之后标记布尔变量改变值。关键之处在于理解树的在遍历过程中的路线图,从根节点到左子树,再回到根节点,从根节点到右子树,再回到根节点,3次访问根节点,打印的时间点决定了前序、中序和后序。

层次遍历利用队列的数据结构,通过根节点放入队列,利用循环在循环体中打印节点并分别将左右儿子加入队列,从而实现层次级别的访问。打印叶节点利用了递归和非递归两种方法,判断条件即左右儿子是否同时为空,为空即为叶节点并打印出来。计算树的深度需要利用递归,根据左右子树的高度最大值加一得到树的高度。删除树节点是比较麻烦的事情,主要考虑3种情况:叶节点的删除(直接将其父节点指向它的指针置为空,并释放该内存空间),只有一个儿子的节点删除(将儿子节点指针直接赋值给其父节点以代替其位置,并释放该节点地址),有两个儿子的节点删除(从右子树中寻找最小值节点,将其数据赋值给该节点,并删除最小值节点,表面上看删除了节点,实际上只是改变了数值,连接关系不变,简化了计算)。在以上过程中需要查询父节点函数,通过非递归遍历返回父节点,这里就反映出父节点指针的必要性了。寻找子树的最小值节点就是直接循环往左儿子节点找,直到某节点左儿子为空,该节点就是最小值节点。

以下是二叉树结构体的C++模板类头文件源代码:

//binarytree.h
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include <IOSTREAM>
template<class Type>
struct BinNode{
Type data;
BinNode<Type>* left;
BinNode<Type>* right;
};
template<class Type>
class BinTree
{
private:
BinNode<Type>* root;
public:
BinTree();
~BinTree();
void ReleaseBinNode(BinNode<Type>*);
bool IsEmpty();
void AddNode(Type);
void PreOrderTraversal(BinNode<Type>*);
void PreOrderTraversal(){PreOrderTraversal(root);}
void InOrderTraversal(BinNode<Type>*);
void InOrderTraversal(){InOrderTraversal(root);}
void PostOrderTraversal(BinNode<Type>*);
void PostOrderTraversal(){PostOrderTraversal(root);}
void NonRecursionTraversal();
void NonRecursionPostTraversal();
void LevelOrderTraversal();
void PrintLeaves();
void PrintLeaves(BinNode<Type>*);
int GetHeight();
int GetHeight(BinNode<Type>*);
void Delete(Type);
void Delete(BinNode<Type>* ,Type);
BinNode<Type>* FindMin(BinNode<Type>*);
BinNode<Type>* GetParentNode(BinNode<Type>*);
};
template<class Type>
BinTree<Type>::BinTree()
{
root=NULL; 
}
template<class Type>
BinTree<Type>::~BinTree()
{
ReleaseBinNode(root);
}
template<class Type>
void BinTree<Type>::ReleaseBinNode(BinNode<Type>* temp)
{
while(temp)
{
ReleaseBinNode(temp->left);
ReleaseBinNode(temp->right);
delete temp;
return;
}
return;
}
template<class Type>
bool BinTree<Type>::IsEmpty()
{
if(root)
return false;
else 
return true;
}
template<class Type>
void BinTree<Type>::AddNode(Type x)
{
BinNode<Type>* temp=new BinNode<Type>;
temp->data=x;
temp->left=NULL;
temp->right=NULL;
if(!root)
{
root=temp;
return;
}
BinNode<Type>* now=root;
BinNode<Type>* nowbefore=now;
int flag=-1;
while(now)
{
nowbefore=now;
if(now->data>x)
{
now=now->left;
flag=0;
}
else 
{
now=now->right;
flag=1;
}
}
if(flag==0)
nowbefore->left=temp;
else if(flag==1)
nowbefore->right=temp;
else
std::cout<<"It cannot add the number to the bintree!"<<std::endl;
return;
}
template<class Type>
void BinTree<Type>::PreOrderTraversal(BinNode<Type>* temproot)
{
if(!temproot)
return;
std::cout<<temproot->data<<" ";
PreOrderTraversal(temproot->left);
PreOrderTraversal(temproot->right);
}
template<class Type>
void BinTree<Type>::InOrderTraversal(BinNode<Type>* temproot)
{
if(!temproot)
return;
InOrderTraversal(temproot->left);
std::cout<<temproot->data<<" ";
InOrderTraversal(temproot->right);


}
template<class Type>
void BinTree<Type>::PostOrderTraversal(BinNode<Type>* temproot)
{
if(!temproot)
return;
PostOrderTraversal(temproot->left);
PostOrderTraversal(temproot->right);
std::cout<<temproot->data<<" ";
}
template<class Type>
void BinTree<Type>::NonRecursionTraversal()
{
LinkedStack<BinNode<Type>* > NodeStack;
BinNode<Type>* temp=root;
while(temp||!NodeStack.IsEmpty())
{
while(temp)
{
NodeStack.Push(temp);
std::cout<<temp->data<<" ";//PreOrderTraversal
temp=temp->left;
}
if(!NodeStack.IsEmpty())
{
temp=NodeStack.Pop();
//std::cout<<temp->data<<" ";//InOrderTraversal
temp=temp->right;
}
} 
std::cout<<std::endl;
}
template<class Type>
void BinTree<Type>::NonRecursionPostTraversal()
{
LinkedStack<BinNode<Type>* > NodeStack;
LinkedStack<bool> Visited;
BinNode<Type>* temp=root;
bool bPrint=true;
while(temp||!NodeStack.IsEmpty())
{
while(temp&&bPrint)
{
NodeStack.Push(temp);
Visited.Push(true);
temp=temp->left;
bPrint=true;
}
if(!NodeStack.IsEmpty())
{
if(Visited.GetTop())
{
temp=NodeStack.GetTop();
temp=temp->right;
Visited.Pop();
Visited.Push(false);
bPrint=true;
}
else
{
temp=NodeStack.Pop();
std::cout<<temp->data<<" ";//PostOrderTraversal
Visited.Pop();
bPrint=false;
} 
}
else
break;
} 
std::cout<<std::endl;
}
template<class Type>
void BinTree<Type>::LevelOrderTraversal()
{
if(IsEmpty())
return;
LinkedQueue<BinNode<Type>* > NodeQueue;
NodeQueue.AddElement(root);
while(!NodeQueue.IsEmpty())
{
BinNode<Type>* temp=NodeQueue.DeleteElement();
std::cout<<temp->data<<" ";
if(temp->left)
NodeQueue.AddElement(temp->left);
if(temp->right)
NodeQueue.AddElement(temp->right);
}
std::cout<<std::endl;
}
template<class Type>
void BinTree<Type>::PrintLeaves()
{
if(IsEmpty())
return;
PrintLeaves(root);
//NonRecursionTraversePrintLeaves
/*BinNode<Type>* temp=root;
LinkedStack<BinNode<Type>* > NodeStack;
while(temp||!NodeStack.IsEmpty())
{
while(temp)
{
if(!temp->left&&!temp->right)
{
std::cout<<temp->data<<" ";
}
NodeStack.Push(temp);
temp=temp->left;
}
if(!NodeStack.IsEmpty())
{
temp=NodeStack.Pop();
temp=temp->right;
}
}*/
}
template<class Type>
void BinTree<Type>::PrintLeaves(BinNode<Type>* temp)
{
if(temp)
{
if(!temp->left&&!temp->right)
{
std::cout<<temp->data<<" ";
return;
} 
PrintLeaves(temp->left);
PrintLeaves(temp->right);
}
}
template<class Type>
int BinTree<Type>::GetHeight()
{
return GetHeight(root);
}
template<class Type>
int BinTree<Type>::GetHeight(BinNode<Type>* temp)
{
if(!temp)
return 0;
int lHeight=GetHeight(temp->left);
int rHeight=GetHeight(temp->right);
return lHeight>rHeight?lHeight+1:rHeight+1;
}
template<class Type>
void BinTree<Type>::Delete(Type x)
{
Delete(root,x);
}
template<class Type>
void BinTree<Type>::Delete(BinNode<Type>* temp,Type x)
{
if(!temp)
std::cout<<"The delete element is not found!"<<std::endl;
if(x<temp->data)
{
Delete(temp->left,x);
}
else if(x>temp->data)
{
Delete(temp->right,x);
}
else
{
if(temp->right&&temp->left)
{
BinNode<Type>* now=FindMin(temp->right);
temp->data=now->data;
Delete(now,now->data);
}
else
{ 
if(temp->left)
{
BinNode<Type>* parent=GetParentNode(temp);
if(parent->left==temp)
{
parent->left=temp->left;
}
else
parent->right=temp->left;
delete temp; 
}
else if(temp->right)
{
BinNode<Type>* parent=GetParentNode(temp);
if(parent->left==temp)
{
parent->left=temp->right;
}
else
parent->right=temp->right;
delete temp;
}
else
{
BinNode<Type>* parent=GetParentNode(temp);
if(parent->left==temp)
{
parent->left=NULL;
}
else
parent->right=NULL;
delete temp; 
}
}
}
}
template<class Type>
BinNode<Type>* BinTree<Type>::FindMin(BinNode<Type>* temp)
{
while(temp)
{
if(!temp->left)
return temp;
else
temp=temp->left;
}
return NULL;
}
template<class Type>
BinNode<Type>* BinTree<Type>::GetParentNode(BinNode<Type>* child)
{
if(child==root)
{
std::cout<<"The root node has no parent node!"<<std::endl;
return NULL;
}
LinkedStack<BinNode<Type>* > NodeStack;
BinNode<Type>* temp=root;
BinNode<Type>* tempparent=root;
while(temp||!NodeStack.IsEmpty())
{
while(temp)
{
NodeStack.Push(temp);
tempparent=temp;
temp=temp->left;
if(temp==child)
return tempparent;
}
if(!NodeStack.IsEmpty())
{
temp=NodeStack.Pop();
tempparent=temp;
temp=temp->right;
if(temp==child)
return tempparent;
}
}
std::cout<<"We did not find the parent of this node in the tree!"<<std::endl;
return NULL;
}
#endif

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:38288次
    • 积分:1228
    • 等级:
    • 排名:千里之外
    • 原创:72篇
    • 转载:38篇
    • 译文:0篇
    • 评论:0条