// FileName;BTNode.h
// 二叉树类声明头文件
// 二叉树类声明头文件
#ifndef
BTNODE
#define BTNODE// 表示二叉树的节点
template <typename T>
#define BTNODE// 表示二叉树的节点
template <typename T>
class
BTNode
{
public:
// BTNode 是类的实现,使得数据成为公有成员简化了类函数的构造,
// 结合 BTNode 的应用场合,并不违反面向对象设计原则
T data;
BTNode<T> *left, *right; [r2]
{
public:
// BTNode 是类的实现,使得数据成为公有成员简化了类函数的构造,
// 结合 BTNode 的应用场合,并不违反面向对象设计原则
T data;
BTNode<T> *left, *right; [r2]
//
默认构造函数。数据项未被初始化,左、右指针为空
BTNode():left(NULL),right(NULL)
{}
BTNode():left(NULL),right(NULL)
{}
//
标准构造函数,初始化数据成员,左、右子树指针的默认参数值都为
NULL
BTNode (const T& item, BTNode<T> *lptr = NULL,
BTNode<T> *rptr = NULL):
data(item), left(lptr), right(rptr){}
};
BTNode (const T& item, BTNode<T> *lptr = NULL,
BTNode<T> *rptr = NULL):
data(item), left(lptr), right(rptr){}
};
#endif
// BTNODE
// FileName: BTreelib.h
// 二叉树类库函数头文件
// 二叉树类库函数头文件
#ifndef
TREE_LIBRARY_FUNCTIONS
#define TREE_LIBRARY_FUNCTIONS
#define TREE_LIBRARY_FUNCTIONS
#include
"BTNode.h" // use BTNode class
using
namespace std;
//
中序递归访问二叉树,
visit
函数是定制函数
template <typename T>
void inOrder(BTNode<T> *t, void visit(T& item));
template <typename T>
void inOrder(BTNode<T> *t, void visit(T& item));
//
后序递归访问二叉树,
visit
函数是定制函数
template <typename T>
void postOrder(BTNode<T> *t, void visit(T& item));
template <typename T>
void postOrder(BTNode<T> *t, void visit(T& item));
//有先序遍历
template
<typename T>
void preOrder(BTNode<T> *t, void visit(T& item));
void preOrder(BTNode<T> *t, void visit(T& item));
//
按照层次顺序遍历访问二叉树,
visit
是定制函数
template <typename T>
void levelOrder(BTNode<T> *t, void visit(T& item));
template <typename T>
void levelOrder(BTNode<T> *t, void visit(T& item));
//
在引用参数
count
中累计二叉树叶节点的的数目
,count
被初始化为
0
template <typename T>
void countLeaf(BTNode<T> *t, int& count);
template <typename T>
void countLeaf(BTNode<T> *t, int& count);
//
返回二叉树的深度
template <typename T>
int depth (BTNode<T> *t);
template <typename T>
int depth (BTNode<T> *t);
//
生成树
t
的副本,返回新的副本的指针
template <typename T>
BTNode<T> *copyTree(BTNode<T> *t);
template <typename T>
BTNode<T> *copyTree(BTNode<T> *t);
//
遍历并删除二叉树的节点
template <typename T>
void deleteTree(BTNode<T> *t);
template <typename T>
void deleteTree(BTNode<T> *t);
//
用
deleteTree()
删除树的所有节点,并将树根节点赋值为空
template <typename T>
void clearTree(BTNode<T> * & t);
template <typename T>
void clearTree(BTNode<T> * & t);
//
垂直显示二叉树,输出节点值
// 节点值的宽度不大于 dataWidth, 屏幕宽度为 screenWidth
template <typename T>
// 节点值的宽度不大于 dataWidth, 屏幕宽度为 screenWidth
template <typename T>
void
displayTree(const BTNode<T> *t, const int dataWidth=1,const int screenWidth=64);
//
各个函数的实现
template
<typename T>
void inOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
inOrder(t->left, visit); // 遍历左子树
visit(t->data); // 访问节点
inOrder(t->right, visit); // 遍历右子树
}
}
void inOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
inOrder(t->left, visit); // 遍历左子树
visit(t->data); // 访问节点
inOrder(t->right, visit); // 遍历右子树
}
}
template
<typename T>
void postOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
postOrder(t->left, visit); // 遍历左子树
postOrder(t->right, visit); // 遍历右子树
visit(t->data); // 访问节点
}
}
void postOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
postOrder(t->left, visit); // 遍历左子树
postOrder(t->right, visit); // 遍历右子树
visit(t->data); // 访问节点
}
}
template
<typename T>
void preOrder(BTNode<T> *t, void visit(T& item))
void preOrder(BTNode<T> *t, void visit(T& item))
{
//
当子树为空时,递归遍历终止
if (t != NULL)
{
if (t != NULL)
{
visit(t->data); //
访问节点
preOrder(t->left, visit); // 遍历左子树
preOrder(t->right, visit); // 遍历右子树
}
preOrder(t->left, visit); // 遍历左子树
preOrder(t->right, visit); // 遍历右子树
}
}
template
<typename T>
void levelOrder(BTNode<T> *t, void visit(T& item))
[r5] {
// 存储每个节点的兄弟节点到队列中,这样可以按树的下一层的顺序访问它们
queue<BTNode<T> *> q;
BTNode<T> *p;
void levelOrder(BTNode<T> *t, void visit(T& item))
[r5] {
// 存储每个节点的兄弟节点到队列中,这样可以按树的下一层的顺序访问它们
queue<BTNode<T> *> q;
BTNode<T> *p;
//
在队列中插入根节点来初始化队列
q.push(t);
q.push(t);
//
继续迭代过程,直到队列空
while(!q.empty())
{
// 从队列中删除前端节点,并访问节点
p = q.front();
q.pop();
visit( p->data);
while(!q.empty())
{
// 从队列中删除前端节点,并访问节点
p = q.front();
q.pop();
visit( p->data);
//
如果存在左子节点,将它插入到队列
if(p->left != NULL)
q.push(p->left);
// 如果存在右子节点,插入到队列,使它紧邻其兄弟
if(p->right != NULL)
q.push(p->right);
}
}
if(p->left != NULL)
q.push(p->left);
// 如果存在右子节点,插入到队列,使它紧邻其兄弟
if(p->right != NULL)
q.push(p->right);
}
}
//
引用参数
count
被初始化为
0
,计算叶子节点的个数
template <typename T>
void countLeaf (BTNode<T> *t, int& count)
{
if (t != NULL)
{
// 检查 t 是否为叶节点
// 如果是, count 增 1
if (t->left == NULL && t->right == NULL)// 此时说明是叶子节点
count++;
countLeaf(t->left, count); // 左子树遍历,计数
countLeaf(t->right, count); // 右子树遍历,计数
}
}
template <typename T>
void countLeaf (BTNode<T> *t, int& count)
{
if (t != NULL)
{
// 检查 t 是否为叶节点
// 如果是, count 增 1
if (t->left == NULL && t->right == NULL)// 此时说明是叶子节点
count++;
countLeaf(t->left, count); // 左子树遍历,计数
countLeaf(t->right, count); // 右子树遍历,计数
}
}
//
使用后序遍历算法决定树深度
[r6] template <typename T>
int depth (BTNode<T> *t)
{
int depthLeft, depthRight, depthval;// 分别用来记录左子树,右子树和总树的 // 深度
if (t == NULL)
// 空树的深度定为 -1
depthval = -1;
else
{
// 查找 t 的左子树的深度
depthLeft= depth(t->left);
// 查找 t 的右子树的深度
depthRight= depth(t->right);
// 以 t 为根的树的深度为: 1+ (两棵子树的最大深度)
depthval = 1 +
(depthLeft >= depthRight ? depthLeft : depthRight);
}
return depthval;
}
[r6] template <typename T>
int depth (BTNode<T> *t)
{
int depthLeft, depthRight, depthval;// 分别用来记录左子树,右子树和总树的 // 深度
if (t == NULL)
// 空树的深度定为 -1
depthval = -1;
else
{
// 查找 t 的左子树的深度
depthLeft= depth(t->left);
// 查找 t 的右子树的深度
depthRight= depth(t->right);
// 以 t 为根的树的深度为: 1+ (两棵子树的最大深度)
depthval = 1 +
(depthLeft >= depthRight ? depthLeft : depthRight);
}
return depthval;
}
template
<typename T>
BTNode<T> *copyTree(BTNode<T> *t)
[r7] {
// newNode 指向算法产生的新节点,
//newLptr 和 newRptr 指向 newNode 的左、右子树
BTNode<T> *newLeft, *newRight, *newNode;
BTNode<T> *copyTree(BTNode<T> *t)
[r7] {
// newNode 指向算法产生的新节点,
//newLptr 和 newRptr 指向 newNode 的左、右子树
BTNode<T> *newLeft, *newRight, *newNode;
//
到达空树时停止递归遍历
if (t == NULL)
return NULL;
if (t == NULL)
return NULL;
//
自底向上构造新树:先构造两个子树,然后构造父节点。
// 在节点 t ,生成左子树的副本,将其根节点指针赋值给 newLeft
newLeft = copyTree(t->left);
// 生成右子树的副本,将其根节点指针赋值给 newRight
newRight = copyTree(t->right);
// 在节点 t ,生成左子树的副本,将其根节点指针赋值给 newLeft
newLeft = copyTree(t->left);
// 生成右子树的副本,将其根节点指针赋值给 newRight
newRight = copyTree(t->right);
//
生成新节点,其节点值与
t
的值相同,其子节点是被复制的
t
的子树
newNode = new BTNode<T> (t->data, newLeft, newRight);
newNode = new BTNode<T> (t->data, newLeft, newRight);
//
返回新复制的树的根节点的指针
return newNode;
}
return newNode;
}
template
<typename T>
void deleteTree(BTNode<T> *t) [r8]
{
// 后序遍历,删除 t 的左、右子树,然后删除节点 t
if (t != NULL)
{
deleteTree(t->left);
deleteTree(t->right);
delete t;
}
}
void deleteTree(BTNode<T> *t) [r8]
{
// 后序遍历,删除 t 的左、右子树,然后删除节点 t
if (t != NULL)
{
deleteTree(t->left);
deleteTree(t->right);
delete t;
}
}
template
<typename T>
void clearTree(BTNode<T> * & t)
{
deleteTree(t);
t = NULL; // 此时根为 NULL
}
void clearTree(BTNode<T> * & t)
{
deleteTree(t);
t = NULL; // 此时根为 NULL
}
//
辅助结构
// 存放 displayTree 中节点坐标( x , y )的记录
struct Info
{
// 默认构造函数
Info() {}
// 初始化构造函数
Info(int indent, int level):xIndent(indent),yLevel(level) {};
int xIndent,yLevel;
};
// 存放 displayTree 中节点坐标( x , y )的记录
struct Info
{
// 默认构造函数
Info() {}
// 初始化构造函数
Info(int indent, int level):xIndent(indent),yLevel(level) {};
int xIndent,yLevel;
};
template
<typename T>
void displayTree(BTNode<T> *t, const int dataWidth,const int screenWidth=64)
[r10] {
// 存储每个节点的队列
queue<BTNode<T> *> q;
// 存放节点打印信息的队列;
queue<Info>QI;
BTNode<T> *currNode;
Info currInfo;
int units (screenWidth/dataWidth);
int offset = units/2;
// 当前节点的列坐标
int currlevel = -1;
// 当前节点的同层的前一节点的行坐标
int preX;
// 如果树为空,退出
if (t == NULL)
return;
void displayTree(BTNode<T> *t, const int dataWidth,const int screenWidth=64)
[r10] {
// 存储每个节点的队列
queue<BTNode<T> *> q;
// 存放节点打印信息的队列;
queue<Info>QI;
BTNode<T> *currNode;
Info currInfo;
int units (screenWidth/dataWidth);
int offset = units/2;
// 当前节点的列坐标
int currlevel = -1;
// 当前节点的同层的前一节点的行坐标
int preX;
// 如果树为空,退出
if (t == NULL)
return;
//
在队列
q
中插入根节点来初始化队列
q.push(t);
// 在队列 QI 中插入根节点坐标初始化队列
QI.push(Info(offset,0));
q.push(t);
// 在队列 QI 中插入根节点坐标初始化队列
QI.push(Info(offset,0));
//
继续迭代过程,直到队列空
while(!q.empty())
{
// 从队列中删除前端节点,并访问节点
currNode = q.front();
q.pop();
currInfo = QI.front();
QI.pop();
if( currInfo.yLevel != currlevel )
{
// 换两行
cout<<"/n/n" ;
// 新行,起始位置为 0
preX = 0;
// 子女节点的偏移量为 上层节点的 1/2
offset /= 2;
// 更新当前节点坐标层次
currlevel = currInfo.yLevel;
}
// 在相应位置输出节点队列头部元素的值,类型为 T ,
// 我们假定类型 T 定义了合适的 << 操作符
cout<<setw((currInfo.xIndent-preX)*dataWidth)
<<currNode->data;
if( currNode->left != NULL )
{
// 左子节点入队
q.push(currNode->left) ;
// 左子节点位置信息入队
QI.push(Info(currInfo.xIndent-offset,currInfo.yLevel+1));
}
if( currNode->right != NULL )
{
// 右子节点入队
q.push(currNode->right) ;
// 右子节点位置信息入队
QI.push(Info(currInfo.xIndent+offset,currInfo.yLevel+1));
}
preX = currInfo.xIndent;
} //while 循环
}
#endif // TREE_LIBRARY_FUNCTIONS
while(!q.empty())
{
// 从队列中删除前端节点,并访问节点
currNode = q.front();
q.pop();
currInfo = QI.front();
QI.pop();
if( currInfo.yLevel != currlevel )
{
// 换两行
cout<<"/n/n" ;
// 新行,起始位置为 0
preX = 0;
// 子女节点的偏移量为 上层节点的 1/2
offset /= 2;
// 更新当前节点坐标层次
currlevel = currInfo.yLevel;
}
// 在相应位置输出节点队列头部元素的值,类型为 T ,
// 我们假定类型 T 定义了合适的 << 操作符
cout<<setw((currInfo.xIndent-preX)*dataWidth)
<<currNode->data;
if( currNode->left != NULL )
{
// 左子节点入队
q.push(currNode->left) ;
// 左子节点位置信息入队
QI.push(Info(currInfo.xIndent-offset,currInfo.yLevel+1));
}
if( currNode->right != NULL )
{
// 右子节点入队
q.push(currNode->right) ;
// 右子节点位置信息入队
QI.push(Info(currInfo.xIndent+offset,currInfo.yLevel+1));
}
preX = currInfo.xIndent;
} //while 循环
}
#endif // TREE_LIBRARY_FUNCTIONS
// File: testBTree.cpp
//
此程序演示二叉树的各种算法
//
首先构建一棵二叉树,在屏幕上垂直输出
//
中序、后序及层次遍历二叉树
//
计算树的高度,并计算叶节点个数
//
并验证了复制、删除二叉树的操作
#include
<iostream>
#include
"BTNode.h" // BTNode
类
#include
"BTreelib.h" // BTNode
库
using
namespace std;
//
实用函数
makeCharTree
,生成一棵以字符为节点数据的二叉树
BTNode
<char> *makeCharTree();
//
遍历算法的
visit
函数,输出节点数据值
void
printChar(char& elem)
{
string
seperator = " ";
cout << elem << seperator;
}
int
main()
{
//
二叉树的根
BTNode
<char> *root1, *root2;
//
构造二叉树
root1 = makeCharTree();
//
显示树
cout << "
原始树的图示:
"
<< endl;
const
int charWidth=1;
const
int ScreenWidth=64;
displayTree(root1, charWidth,ScreenWidth);
cout << endl << endl;
//
节点的中序遍历
cout << "
中序遍历:
"
;
inOrder(root1, printChar);
cout << endl;
//
节点的后序遍历
cout << "
后序遍历:
"
;
postOrder(root1, printChar);
cout << endl;
//
节点的层次遍历
cout << "
层次遍历:
"
;
levelOrder(root1, printChar);
cout << endl<<endl;
//
叶结点计数
int
leafCount = 0;
countLeaf(root1, leafCount);
cout << "
叶节点数目是:
"
<< leafCount << endl;
cout << "
树的深度是:
"
<< depth (root1) <<endl;
//
生成
root1
的副本,根为
root2
root2 = copyTree(root1);
//
显示树的副本
cout << "
原始树的副本的图示:
"
<< endl;
displayTree(root2, charWidth,ScreenWidth);
cout << endl;
//
清空两棵树
clearTree(root1);
clearTree(root2);
cout << "
对
root1
调用的
clearTree
之后的图示:
"
<< endl;
displayTree(root1, charWidth,ScreenWidth);
cout << endl << endl;
cout<<"
按回车键结束程序
:"
<< endl;
cin.get();
return
0;
}
BTNode
<char> *makeCharTree()
{
// 9 BTNode
指针,指向
9
个节点项
BTNode
<char> *root, *b, *c, *d, *e, *f, *g, *h, *i;
g = new BTNode<char> ('G');
h = new BTNode<char> ('H');
i = new BTNode<char> ('I');
d = new BTNode<char> ('D',(BTNode<char> *)NULL, g);
e = new BTNode<char> ('E',h, i);
f = new BTNode<char> ('F');
b = new BTNode<char> ('B',d, (BTNode<char> *)NULL);
c = new BTNode<char> ('C',e, f);
root = new BTNode<char> ('A',b, c);
return
root;
}
//
声明二叉树类
template
<typename Type> class BinaryTree;
template
<typename Type> class BinTreeNode{
public
:
friend class BinaryTree<Type>;
[r12]
BinTreeNode():m_pleft(NULL),m_pright(NULL){}
BinTreeNode(Type item,BinTreeNode<Type> *left=NULL,BinTreeNode<Type> *right=NULL)
:m_data(item),m_pleft(left),m_pright(right){}
Type GetData() const; //get thd data
BinTreeNode<Type> *GetLeft() const; //get the left node
BinTreeNode<Type> *GetRight() const; //get the right node
void SetData(const Type data); //change the data
void SetLeft(const BinTreeNode<Type> *left); //change thd left node
void SetRight(const BinTreeNode<Type> *right); //change the right node
void InOrder(); //inorder the tree with the root of the node
void PreOrder(); //perorder the tree with the root of the node
void PostOrder(); //postoder the tree with the root of the node
int Size(); //get size
int Height(); //get height
BinTreeNode<Type> *Copy(const BinTreeNode<Type> *copy); //copy the node
void Destroy(){ //destroy the tree with the root of the node
if(this!=NULL){
this->m_pleft->Destroy();
this->m_pright->Destroy();
delete this;
}
}
friend bool equal(const BinTreeNode<Type> *s,const BinTreeNode<Type> *t); //is equal?
private
:
BinTreeNode<Type> *m_pleft,*m_pright;
Type m_data;
};
template
<typename Type> Type BinTreeNode<Type>::GetData() const{
return this!=NULL?m_data:-1;
}
template
<typename Type> BinTreeNode<Type>* BinTreeNode<Type>::GetLeft() const{
return this!=NULL?m_pleft:NULL;
}
template
<typename Type> BinTreeNode<Type>* BinTreeNode<Type>::GetRight() const{
return this!=NULL?m_pright:NULL;
}
template
<typename Type> void BinTreeNode<Type>::SetData(const Type data){
if(this!=NULL){
m_data=data;
}
}
template
<typename Type> void BinTreeNode<Type>::SetLeft(const BinTreeNode<Type> *left){
if(this!=NULL){
m_pleft=left;
}
}
template
<typename Type> void BinTreeNode<Type>::SetRight(const BinTreeNode<Type> *right){
if(this!=NULL){
m_pright=right;
}
}
template
<typename Type> BinTreeNode<Type>* BinTreeNode<Type>::Copy(const BinTreeNode<Type> *copy){
if(copy==NULL){
return NULL;
}
BinTreeNode<Type> *temp=new BinTreeNode<Type>(copy->m_data);
temp->m_pleft=Copy(copy->m_pleft);
temp->m_pright=Copy(copy->m_pright);
return temp;
}
template
<typename Type> bool equal(const BinTreeNode<Type> *s,const BinTreeNode<Type> *t){
if(s==NULL&&t==NULL){
return 1;
}
if(s&&t&&s->m_data==t->m_data&&equal(s->m_pleft,t->m_pleft)&&equal(s->m_pright,t->m_pright)){
return 1;
}
return 0;
}
template
<typename Type> void BinTreeNode<Type>::InOrder(){
if(this!=NULL){
this->m_pleft->InOrder();
cout<<"--->"<<this->m_data;
this->m_pright->InOrder();
}
}
template
<typename Type> void BinTreeNode<Type>::PreOrder(){
if(this!=NULL){
cout<<"--->"<<this->m_data;
this->m_pleft->PreOrder();
this->m_pright->PreOrder();
}
}
template
<typename Type> void BinTreeNode<Type>::PostOrder(){
if(this!=NULL){
this->m_pleft->PostOrder();
this->m_pright->PostOrder();
cout<<"--->"<<this->m_data;
}
}
template
<typename Type> int BinTreeNode<Type>::Size(){
if(this==NULL){
return 0;
}
return 1+this->m_pleft->Size()+this->m_pright->Size();
}
template
<typename Type> int BinTreeNode<Type>::Height(){
if(this==NULL){
return -1;
}
int lheight,rheight;
lheight=this->m_pleft->Height();
rheight=this->m_pright->Height();
return 1+(lheight>rheight?lheight:rheight);
}
#include
"BinTreeNode.h"
template
<typename Type> class BinaryTree{
public
:
BinaryTree():m_proot(NULL){}
BinaryTree(const Type stop):m_stop(stop),m_proot(NULL){}
BinaryTree(BinaryTree<Type>& copy);
virtual ~BinaryTree(){
m_proot->Destroy();
}
virtual bool IsEmpty(){ //is empty?
return m_proot==NULL;
}
virtual BinTreeNode<Type> *GetLeft(BinTreeNode<Type> *current); //get the left node
virtual BinTreeNode<Type> *GetRight(BinTreeNode<Type> *current);//get the right node
virtual BinTreeNode<Type> *GetParent(BinTreeNode<Type> *current);//ghe thd parent
const BinTreeNode<Type> *GetRoot() const; //get root
virtual bool Insert(const Type item); //insert a new node
virtual BinTreeNode<Type> *Find(const Type item) const; //find thd node with the data
void InOrder();
void PreOrder();
void PostOrder();
int Size(); //get size
int Height(); //get height
BinaryTree<Type>& operator=(const BinaryTree<Type> copy); //evaluate node
friend bool operator== <Type>(const BinaryTree<Type> s,const BinaryTree<Type> t);//is equal?
friend ostream& operator<< <Type>(ostream& ,BinaryTree<Type>&); //output the data
friend istream& operator>> <Type>(istream& ,BinaryTree<Type>&); //input the data
private
:
Type m_stop; //just using for input the data;
BinTreeNode<Type> *m_proot;
//find the parent of current in the tree with the root of start
BinTreeNode<Type> *GetParent(BinTreeNode<Type> *start,BinTreeNode<Type> *current);
void Print(BinTreeNode<Type> *start,int n=0); //print the tree with the root of start
};
template
<typename Type> BinaryTree<Type>::BinaryTree(BinaryTree<Type>& copy){
if(copy.m_proot){
this->m_stop=copy.m_stop;
}
m_proot=m_proot->Copy(copy.m_proot);
}
template
<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetLeft(BinTreeNode<Type> *current){
return m_proot&¤t?current->m_pleft:NULL;
}
template
<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetRight(BinTreeNode<Type> *current){
return m_proot&¤t?current->m_pright:NULL;
}
template
<typename Type> const BinTreeNode<Type>* BinaryTree<Type>::GetRoot() const{
return m_proot;
}
template
<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetParent(BinTreeNode<Type> *start, BinTreeNode<Type> *current){
if(start==NULL||current==NULL){
return NULL;
}
if(start->m_pleft==current||start->m_pright==current){
return start;
}
BinTreeNode<Type> *pmove;
if((pmove=GetParent(start->m_pleft,current))!=NULL){//find the parent in the left subtree
return pmove;
}
else{
return GetParent(start->m_pright,current); //find the parent in the right subtree
}
}
template
<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetParent(BinTreeNode<Type> *current){
return m_proot==NULL||current==m_proot?NULL:GetParent(m_proot,current);
}
template
<typename Type> bool BinaryTree<Type>::Insert(const Type item){
BinTreeNode<Type> *pstart=m_proot,*newnode=new BinTreeNode<Type>(item);
if(m_proot==NULL){
m_proot=newnode;
return 1;
}
while(1){
if(item==pstart->m_data){
cout<<"The item "<<item<<" is exist!"<<endl;
return 0;
}
if(item<pstart->m_data){
if(pstart->m_pleft==NULL){
pstart->m_pleft=newnode;
return 1;
}
pstart=pstart->m_pleft; //if less than the node then insert to the left subtree
}
else{
if(pstart->m_pright==NULL){
pstart->m_pright=newnode;
return 1;
}
pstart=pstart->m_pright;//if more than the node then insert to the right subtree
}
}
}
template
<typename Type> BinTreeNode<Type>* BinaryTree<Type>::Find(const Type item) const{
BinTreeNode<Type> *pstart=m_proot;
while(pstart){
if(item==pstart->m_data){
return pstart;
}
if(item<pstart->m_data){
pstart=pstart->m_pleft; //if less than the node then find in the left subtree
}
else{
pstart=pstart->m_pright;//if more than the node then find in the right subtree
}
}
return NULL;
}
template
<typename Type> void BinaryTree<Type>::Print(BinTreeNode<Type> *start, int n){
if(start==NULL){
for(int i=0;i<n;i++){
cout<<" ";
}
cout<<"NULL"<<endl;
return;
}
Print(start->m_pright,n+1); //print the right subtree
for(int i=0;i<n;i++){ //print blanks with the height of the node
cout<<" ";
}
if(n>=0){
cout<<start->m_data<<"--->"<<endl;//print the node
}
Print(start->m_pleft,n+1); //print the left subtree
}
template
<typename Type> BinaryTree<Type>& BinaryTree<Type>::operator=(const BinaryTree<Type> copy){
if(copy.m_proot){
this->m_stop=copy.m_stop;
}
m_proot=m_proot->Copy(copy.m_proot);
return *this;
}
template
<typename Type> ostream& operator<<(ostream& os,BinaryTree<Type>& out){
out.Print(out.m_proot);
return os;
}
template
<typename Type> istream& operator>>(istream& is,BinaryTree<Type>& in){
Type item;
cout<<"initialize the tree:"<<endl<<"Input data(end with "<<in.m_stop<<"!):";
is>>item;
while(item!=in.m_stop){ //m_stop is the end of input
in.Insert(item);
is>>item;
}
return is;
}
template
<typename Type> bool operator==(const BinaryTree<Type> s,const BinaryTree<Type> t){
return equal(s.m_proot,t.m_proot);
}
template
<typename Type> void BinaryTree<Type>::InOrder(){
this->m_proot->InOrder();
}
template
<typename Type> void BinaryTree<Type>::PreOrder(){
this->m_proot->PreOrder();
}
template
<typename Type> void BinaryTree<Type>::PostOrder(){
this->m_proot->PostOrder();
}
template
<typename Type> int BinaryTree<Type>::Size(){
return this->m_proot->Size();
}
template
<typename Type> int BinaryTree<Type>::Height(){
return this->m_proot->Height();
}
#include
<iostream>
using
namespace std;
#include
"BinaryTree.h"
int
main(){
BinaryTree<int> tree(-1);
// int init[10]={3,6,0,2,8,4,9,1,5,7};
int init[30]={17,6,22,29,14,0,21,13,27,18,2,28,8
,26,3,12,20,4,9,23,15,1,11,5,19,24,16,7,10,25};
for(int i=0;i<30;i++){
tree.Insert(init[i]);
}
//cin>>tree;
cout<<tree<<endl;
cout<<tree.GetParent(tree.Find(20))->GetData()<<endl;
cout<<tree.Find(15)->GetRight()->GetData()<<endl;
cout<<"size="<<tree.Size()<<endl;
cout<<"height="<<tree.Height()<<endl;
tree.InOrder();
cout<<endl<<endl;
tree.PreOrder();
cout<<endl<<endl;
tree.PostOrder();
cout<<endl<<endl;
BinaryTree<int> tree2=tree;
cout<<tree2<<endl;
cout<<tree2.GetParent(tree2.Find(20))->GetData()<<endl;
cout<<tree2.Find(15)->GetRight()->GetData()<<endl;
cout<<(tree==tree2)<<endl;
return 0;
}
//BTNode.h
#ifndef
BTNODE
#define BTNODE// 表示二叉树的节点
template<class TYPE>
class BTree;
template <typename T>
class BTNode
{
private:
T data;
BTNode<T> *left, *right;
public:
// 默认构造函数。数据项未被初始化,左、右指针为空
BTNode():left(NULL),right(NULL)
{}
// 标准构造函数,初始化数据成员,左、右子树指针的默认参数值都为 NULL
BTNode (const T& item, BTNode<T> *lptr = NULL,
BTNode<T> *rptr = NULL):
data(item), left(lptr), right(rptr){}
T GetData() const; //get thd data
BTNode<T> *GetLeft() const; //get the left node
BTNode<T> *GetRight() const; //get the right node
void SetData(const T data1); //change the data
void SetLeft(const BTNode<T> *left1); //change thd left node
void SetRight(const BTNode<T> *right1); //change the right node
BTNode<T> *Copy(const BTNode<T> *copy); //copy the node
friend bool equal(const BTNode<T> *s, const BTNode<T> *t);//is equal?
};
template<typename Type>
Type BTNode<Type>::GetData() const{
return this!=NULL?data:-1;
}
template<typename Type>
BTNode<Type>* BTNode<Type>::GetLeft() const{
return this!=NULL?left:NULL;
}
template<typename Type>
BTNode<Type>* BTNode<Type>::GetRight() const{
return this!=NULL?right:NULL;
}
template<typename Type>
void BTNode<Type>::SetData(const Type data1){
if(this!=NULL){
data=data1;
}
}
template<typename Type>
void BTNode<Type>::SetLeft(const BTNode<Type> *left1){
if(this!=NULL){
left=left1;
}
}
template<typename Type>
void BTNode<Type>::SetRight(const BTNode<Type> *right1){
if(this!=NULL){
right=right1;
}
}
template<typename Type>
BTNode<Type>* BTNode<Type>::Copy(const BTNode<Type> *copy){
if(copy==NULL){
return NULL;
}
BTNode<Type> *temp=new BTNode<Type>(copy->data);
temp->left=Copy(copy->left);
temp->right=Copy(copy->right);
return temp;
}
template<typename Type>
bool equal(const BTNode<Type> *s,const BTNode<Type> *t){
if(s==NULL&&t==NULL){
return 1;
}
if(s&&t&&s->data==t->data&&equal(s->left,t->left)&&equal(s->right,t->right)){
return 1;
}
return 0;
}
#endif // BTNODE
#define BTNODE// 表示二叉树的节点
template<class TYPE>
class BTree;
template <typename T>
class BTNode
{
private:
T data;
BTNode<T> *left, *right;
public:
// 默认构造函数。数据项未被初始化,左、右指针为空
BTNode():left(NULL),right(NULL)
{}
// 标准构造函数,初始化数据成员,左、右子树指针的默认参数值都为 NULL
BTNode (const T& item, BTNode<T> *lptr = NULL,
BTNode<T> *rptr = NULL):
data(item), left(lptr), right(rptr){}
T GetData() const; //get thd data
BTNode<T> *GetLeft() const; //get the left node
BTNode<T> *GetRight() const; //get the right node
void SetData(const T data1); //change the data
void SetLeft(const BTNode<T> *left1); //change thd left node
void SetRight(const BTNode<T> *right1); //change the right node
BTNode<T> *Copy(const BTNode<T> *copy); //copy the node
friend bool equal(const BTNode<T> *s, const BTNode<T> *t);//is equal?
};
template<typename Type>
Type BTNode<Type>::GetData() const{
return this!=NULL?data:-1;
}
template<typename Type>
BTNode<Type>* BTNode<Type>::GetLeft() const{
return this!=NULL?left:NULL;
}
template<typename Type>
BTNode<Type>* BTNode<Type>::GetRight() const{
return this!=NULL?right:NULL;
}
template<typename Type>
void BTNode<Type>::SetData(const Type data1){
if(this!=NULL){
data=data1;
}
}
template<typename Type>
void BTNode<Type>::SetLeft(const BTNode<Type> *left1){
if(this!=NULL){
left=left1;
}
}
template<typename Type>
void BTNode<Type>::SetRight(const BTNode<Type> *right1){
if(this!=NULL){
right=right1;
}
}
template<typename Type>
BTNode<Type>* BTNode<Type>::Copy(const BTNode<Type> *copy){
if(copy==NULL){
return NULL;
}
BTNode<Type> *temp=new BTNode<Type>(copy->data);
temp->left=Copy(copy->left);
temp->right=Copy(copy->right);
return temp;
}
template<typename Type>
bool equal(const BTNode<Type> *s,const BTNode<Type> *t){
if(s==NULL&&t==NULL){
return 1;
}
if(s&&t&&s->data==t->data&&equal(s->left,t->left)&&equal(s->right,t->right)){
return 1;
}
return 0;
}
#endif // BTNODE
//BTree.h
#ifndef
TREE_LIBRARY_FUNCTIONS
#define TREE_LIBRARY_FUNCTIONS
#include <iomanip>
#include <string>
#include <queue>
#include <fstream>
#include "BTNode.h"
using namespace std;
template<class T>
class BTree
{
public:
BTree():root(NULL),count(0){}
virtual~BTree()
{}
// 中序递归访问二叉树, visit 函数是定制函数
void inOrder(BTNode<T> *t, void visit(T& item));
// 后序递归访问二叉树, visit 函数是定制函数
void postOrder(BTNode<T> *t, void visit(T& item));
// 有先序遍历
void preOrder(BTNode<T> *t, void visit(T& item));
// 按照层次顺序遍历访问二叉树, visit 是定制函数
void levelOrder(BTNode<T> *t, void visit(T& item));
// 在引用参数 count 中累计二叉树叶节点的的数目 ,count 被初始化为 0
int countLeaf(BTNode<T> *t, int& count);
// 返回二叉树的深度
int depth (BTNode<T> *t);
// 生成树 t 的副本,返回新的副本的指针
BTNode<T> *copyTree(BTNode<T> *t);
// 遍历并删除二叉树的节点
void deleteTree(BTNode<T> *t);
// 用 deleteTree() 删除树的所有节点,并将树根节点赋值为空
void clearTree(BTNode<T> * & t);
// 垂直显示二叉树,输出节点值
// 节点值的宽度不大于 dataWidth, 屏幕宽度为 screenWidth
void displayTree(const BTNode<T> *t, const int dataWidth=1,const int screenWidth=64);
// 查找 //find thd node with the data
BTNode<T> *Find(const T item) const;
friend bool operator== <T>(const BTree<T> s,const BTree<T> t);//is equal?
private:
int count;// 叶子节点的个数
BTNode<T>* root;
// 辅助结构
// 存放 displayTree 中节点坐标( x , y )的记录
struct Info
{
// 默认构造函数
Info() {}
// 初始化构造函数
Info(int indent, int level):xIndent(indent),yLevel(level) {};
int xIndent,yLevel;
};
};
template <typename T>
void BTree<T>::inOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
inOrder(t->left, visit); // 遍历左子树
visit(t->data); // 访问节点
inOrder(t->right, visit); // 遍历右子树
}
}
template <typename T>
void BTree<T>::postOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
postOrder(t->left, visit); // 遍历左子树
postOrder(t->right, visit); // 遍历右子树
visit(t->data); // 访问节点
}
}
template <typename T>
void BTree<T>::preOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
visit(t->data); // 访问节点
preOrder(t->left, visit); // 遍历左子树
preOrder(t->right, visit); // 遍历右子树
}
}
template <typename T>
void BTree<T>::levelOrder(BTNode<T> *t, void visit(T& item))
{
// 存储每个节点的兄弟节点到队列中,这样可以按树的下一层的顺序访问它们
queue<BTNode<T> *> q;
BTNode<T> *p;
// 在队列中插入根节点来初始化队列
q.push(t);
// 继续迭代过程,直到队列空
while(!q.empty())
{
// 从队列中删除前端节点,并访问节点
p = q.front();
q.pop();
visit( p->data);
// 如果存在左子节点,将它插入到队列
if(p->left != NULL)
q.push(p->left);
// 如果存在右子节点,插入到队列,使它紧邻其兄弟
if(p->right != NULL)
q.push(p->right);
}
}
// 引用参数 count 被初始化为 0 ,计算叶子节点的个数
template <typename T>
int BTree<T>::countLeaf (BTNode<T> *t, int& count)
{
if (t != NULL)
{
// 检查 t 是否为叶节点
// 如果是, count 增 1
if (t->left == NULL && t->right == NULL)// 此时说明是叶子节点
count++;
countLeaf(t->left, count); // 左子树遍历,计数
countLeaf(t->right, count); // 右子树遍历,计数
}
return count;
}
// 使用后序遍历算法决定树深度
template <typename T>
int BTree<T>::depth (BTNode<T> *t)
{
int depthLeft, depthRight, depthval;// 分别用来记录左子树,右子树和总树的 // 深度
if (t == NULL)
// 空树的深度定为 -1
depthval = -1;
else
{
// 查找 t 的左子树的深度
depthLeft= depth(t->left);
// 查找 t 的右子树的深度
depthRight= depth(t->right);
// 以 t 为根的树的深度为: 1+ (两棵子树的最大深度)
depthval = 1 +
(depthLeft >= depthRight ? depthLeft : depthRight);
}
return depthval;
}
template <typename T>
BTNode<T>* BTree<T>::copyTree(BTNode<T> *t)
{
// newNode 指向算法产生的新节点,
//newLptr 和 newRptr 指向 newNode 的左、右子树
BTNode<T> *newLeft, *newRight, *newNode;
// 到达空树时停止递归遍历
if (t == NULL)
return NULL;
// 自底向上构造新树:先构造两个子树,然后构造父节点。
// 在节点 t ,生成左子树的副本,将其根节点指针赋值给 newLeft
newLeft = copyTree(t->left);
// 生成右子树的副本,将其根节点指针赋值给 newRight
newRight = copyTree(t->right);
// 生成新节点,其节点值与 t 的值相同,其子节点是被复制的 t 的子树
newNode = new BTNode<T> (t->data, newLeft, newRight);
// 返回新复制的树的根节点的指针
return newNode;
}
template <typename T>
void BTree<T>::deleteTree(BTNode<T> *t)
{
// 后序遍历,删除 t 的左、右子树,然后删除节点 t
if (t != NULL)
{
deleteTree(t->left);
deleteTree(t->right);
delete t;
}
}
template <typename T>
void BTree<T>::clearTree(BTNode<T> * & t)
{
deleteTree(t);
t = NULL; // 此时根为 NULL
}
template <typename T>
void BTree<T>::displayTree(const BTNode<T> *t, const int dataWidth/* =1 */,const int screenWidth/* =64 */)
{
// 存储每个节点的队列
queue<BTNode<T> *> q;
// 存放节点打印信息的队列;
queue<Info>QI;
BTNode<T> *currNode;
Info currInfo;
int units (screenWidth/dataWidth);
int offset = units/2;
// 当前节点的列坐标
int currlevel = -1;
// 当前节点的同层的前一节点的行坐标
int preX;
// 如果树为空,退出
if (t == NULL)
return;
// 在队列 q 中插入根节点来初始化队列
q.push(t);
// 在队列 QI 中插入根节点坐标初始化队列
QI.push(Info(offset,0));
// 继续迭代过程,直到队列空
while(!q.empty())
{
// 从队列中删除前端节点,并访问节点
currNode = q.front();
q.pop();
currInfo = QI.front();
QI.pop();
if( currInfo.yLevel != currlevel )
{
// 换两行
cout<<"/n/n" ;
// 新行,起始位置为 0
preX = 0;
// 子女节点的偏移量为 上层节点的 1/2
offset /= 2;
// 更新当前节点坐标层次
currlevel = currInfo.yLevel;
}
// 在相应位置输出节点队列头部元素的值,类型为 T ,
// 我们假定类型 T 定义了合适的 << 操作符
cout<<setw((currInfo.xIndent-preX)*dataWidth)
<<currNode->data;
if( currNode->left != NULL )
{
// 左子节点入队
q.push(currNode->left) ;
// 左子节点位置信息入队
QI.push(Info(currInfo.xIndent-offset,currInfo.yLevel+1));
}
if( currNode->right != NULL )
{
// 右子节点入队
q.push(currNode->right) ;
// 右子节点位置信息入队
QI.push(Info(currInfo.xIndent+offset,currInfo.yLevel+1));
}
preX = currInfo.xIndent;
} //while 循环
}
template<typename Type>
BTNode<Type>* BTree<Type>::Find(const Type item) const{
BTNode<Type> *pstart=root;
while(pstart){
if(item==pstart->data){
return pstart;
}
if(item<pstart->data){
pstart=pstart->left; //if less than the node then find in the left subtree
}
else{
pstart=pstart->right;//if more than the node then find in the right subtree
}
}
return NULL;
}
template<typename Type>
bool operator==(const BTree<Type> s,const BTree<Type> t){
return equal(s.root,t.root);
}
#endif
#define TREE_LIBRARY_FUNCTIONS
#include <iomanip>
#include <string>
#include <queue>
#include <fstream>
#include "BTNode.h"
using namespace std;
template<class T>
class BTree
{
public:
BTree():root(NULL),count(0){}
virtual~BTree()
{}
// 中序递归访问二叉树, visit 函数是定制函数
void inOrder(BTNode<T> *t, void visit(T& item));
// 后序递归访问二叉树, visit 函数是定制函数
void postOrder(BTNode<T> *t, void visit(T& item));
// 有先序遍历
void preOrder(BTNode<T> *t, void visit(T& item));
// 按照层次顺序遍历访问二叉树, visit 是定制函数
void levelOrder(BTNode<T> *t, void visit(T& item));
// 在引用参数 count 中累计二叉树叶节点的的数目 ,count 被初始化为 0
int countLeaf(BTNode<T> *t, int& count);
// 返回二叉树的深度
int depth (BTNode<T> *t);
// 生成树 t 的副本,返回新的副本的指针
BTNode<T> *copyTree(BTNode<T> *t);
// 遍历并删除二叉树的节点
void deleteTree(BTNode<T> *t);
// 用 deleteTree() 删除树的所有节点,并将树根节点赋值为空
void clearTree(BTNode<T> * & t);
// 垂直显示二叉树,输出节点值
// 节点值的宽度不大于 dataWidth, 屏幕宽度为 screenWidth
void displayTree(const BTNode<T> *t, const int dataWidth=1,const int screenWidth=64);
// 查找 //find thd node with the data
BTNode<T> *Find(const T item) const;
friend bool operator== <T>(const BTree<T> s,const BTree<T> t);//is equal?
private:
int count;// 叶子节点的个数
BTNode<T>* root;
// 辅助结构
// 存放 displayTree 中节点坐标( x , y )的记录
struct Info
{
// 默认构造函数
Info() {}
// 初始化构造函数
Info(int indent, int level):xIndent(indent),yLevel(level) {};
int xIndent,yLevel;
};
};
template <typename T>
void BTree<T>::inOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
inOrder(t->left, visit); // 遍历左子树
visit(t->data); // 访问节点
inOrder(t->right, visit); // 遍历右子树
}
}
template <typename T>
void BTree<T>::postOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
postOrder(t->left, visit); // 遍历左子树
postOrder(t->right, visit); // 遍历右子树
visit(t->data); // 访问节点
}
}
template <typename T>
void BTree<T>::preOrder(BTNode<T> *t, void visit(T& item))
{
// 当子树为空时,递归遍历终止
if (t != NULL)
{
visit(t->data); // 访问节点
preOrder(t->left, visit); // 遍历左子树
preOrder(t->right, visit); // 遍历右子树
}
}
template <typename T>
void BTree<T>::levelOrder(BTNode<T> *t, void visit(T& item))
{
// 存储每个节点的兄弟节点到队列中,这样可以按树的下一层的顺序访问它们
queue<BTNode<T> *> q;
BTNode<T> *p;
// 在队列中插入根节点来初始化队列
q.push(t);
// 继续迭代过程,直到队列空
while(!q.empty())
{
// 从队列中删除前端节点,并访问节点
p = q.front();
q.pop();
visit( p->data);
// 如果存在左子节点,将它插入到队列
if(p->left != NULL)
q.push(p->left);
// 如果存在右子节点,插入到队列,使它紧邻其兄弟
if(p->right != NULL)
q.push(p->right);
}
}
// 引用参数 count 被初始化为 0 ,计算叶子节点的个数
template <typename T>
int BTree<T>::countLeaf (BTNode<T> *t, int& count)
{
if (t != NULL)
{
// 检查 t 是否为叶节点
// 如果是, count 增 1
if (t->left == NULL && t->right == NULL)// 此时说明是叶子节点
count++;
countLeaf(t->left, count); // 左子树遍历,计数
countLeaf(t->right, count); // 右子树遍历,计数
}
return count;
}
// 使用后序遍历算法决定树深度
template <typename T>
int BTree<T>::depth (BTNode<T> *t)
{
int depthLeft, depthRight, depthval;// 分别用来记录左子树,右子树和总树的 // 深度
if (t == NULL)
// 空树的深度定为 -1
depthval = -1;
else
{
// 查找 t 的左子树的深度
depthLeft= depth(t->left);
// 查找 t 的右子树的深度
depthRight= depth(t->right);
// 以 t 为根的树的深度为: 1+ (两棵子树的最大深度)
depthval = 1 +
(depthLeft >= depthRight ? depthLeft : depthRight);
}
return depthval;
}
template <typename T>
BTNode<T>* BTree<T>::copyTree(BTNode<T> *t)
{
// newNode 指向算法产生的新节点,
//newLptr 和 newRptr 指向 newNode 的左、右子树
BTNode<T> *newLeft, *newRight, *newNode;
// 到达空树时停止递归遍历
if (t == NULL)
return NULL;
// 自底向上构造新树:先构造两个子树,然后构造父节点。
// 在节点 t ,生成左子树的副本,将其根节点指针赋值给 newLeft
newLeft = copyTree(t->left);
// 生成右子树的副本,将其根节点指针赋值给 newRight
newRight = copyTree(t->right);
// 生成新节点,其节点值与 t 的值相同,其子节点是被复制的 t 的子树
newNode = new BTNode<T> (t->data, newLeft, newRight);
// 返回新复制的树的根节点的指针
return newNode;
}
template <typename T>
void BTree<T>::deleteTree(BTNode<T> *t)
{
// 后序遍历,删除 t 的左、右子树,然后删除节点 t
if (t != NULL)
{
deleteTree(t->left);
deleteTree(t->right);
delete t;
}
}
template <typename T>
void BTree<T>::clearTree(BTNode<T> * & t)
{
deleteTree(t);
t = NULL; // 此时根为 NULL
}
template <typename T>
void BTree<T>::displayTree(const BTNode<T> *t, const int dataWidth/* =1 */,const int screenWidth/* =64 */)
{
// 存储每个节点的队列
queue<BTNode<T> *> q;
// 存放节点打印信息的队列;
queue<Info>QI;
BTNode<T> *currNode;
Info currInfo;
int units (screenWidth/dataWidth);
int offset = units/2;
// 当前节点的列坐标
int currlevel = -1;
// 当前节点的同层的前一节点的行坐标
int preX;
// 如果树为空,退出
if (t == NULL)
return;
// 在队列 q 中插入根节点来初始化队列
q.push(t);
// 在队列 QI 中插入根节点坐标初始化队列
QI.push(Info(offset,0));
// 继续迭代过程,直到队列空
while(!q.empty())
{
// 从队列中删除前端节点,并访问节点
currNode = q.front();
q.pop();
currInfo = QI.front();
QI.pop();
if( currInfo.yLevel != currlevel )
{
// 换两行
cout<<"/n/n" ;
// 新行,起始位置为 0
preX = 0;
// 子女节点的偏移量为 上层节点的 1/2
offset /= 2;
// 更新当前节点坐标层次
currlevel = currInfo.yLevel;
}
// 在相应位置输出节点队列头部元素的值,类型为 T ,
// 我们假定类型 T 定义了合适的 << 操作符
cout<<setw((currInfo.xIndent-preX)*dataWidth)
<<currNode->data;
if( currNode->left != NULL )
{
// 左子节点入队
q.push(currNode->left) ;
// 左子节点位置信息入队
QI.push(Info(currInfo.xIndent-offset,currInfo.yLevel+1));
}
if( currNode->right != NULL )
{
// 右子节点入队
q.push(currNode->right) ;
// 右子节点位置信息入队
QI.push(Info(currInfo.xIndent+offset,currInfo.yLevel+1));
}
preX = currInfo.xIndent;
} //while 循环
}
template<typename Type>
BTNode<Type>* BTree<Type>::Find(const Type item) const{
BTNode<Type> *pstart=root;
while(pstart){
if(item==pstart->data){
return pstart;
}
if(item<pstart->data){
pstart=pstart->left; //if less than the node then find in the left subtree
}
else{
pstart=pstart->right;//if more than the node then find in the right subtree
}
}
return NULL;
}
template<typename Type>
bool operator==(const BTree<Type> s,const BTree<Type> t){
return equal(s.root,t.root);
}
#endif
//Main.cpp
#include "BTNode.h"
#include "BTree.h"
#include <iostream>
using namespace std;
//遍历算法的visit函数,输出节点数据值
void printChar(char& elem)
{
string seperator = " ";
cout << elem << seperator;
}
BTNode<char> *makeCharTree();
int main()
{
const int charWidth=1;
const int ScreenWidth=64;
//任何自己想要完成的操作
cout<<"按回车键结束程序:" << endl;
cin.get();
return 0;
}
[r1]
注意:这个文件并没有完全组织好,我们可以利用类来完成。在这个
BTNode
私有成员里面添加二叉树的类为友元类。这样就
ok
啦、但是别忘记了,在添加友元的时候要声明一下二叉树类哦。另外提示一下:模板的定义和实现必须在一个文件里面。这个所有的编译器都是这么求的、其中第三个程序是把前
2
个结合在一起的。
std::size_t
无符号
INT
std::ptrdiff_t
有符号
INT
用于保存随机访问迭代器的的差值。
这是一个
C
文件的
C++
版本文件;
假如你用原版本
stddef.h
的话就不用
std::
了
.
[r5]
在层次遍历的时候用到了队列。而之前的三种遍历只是调用递归实现。其实也可以用非递归的方式实现,注意这个层次遍历
[r6]
注意,在计算二叉树的深度的时候只能用后续遍历算法。因为必须从下往上算起。
[r7]
用的也是后续遍历算法
[r8]
删除树的时候也必须从下往上,所以也是后续遍历。而且必须是。
[r9]
此处提示我们可以在类中在私有成员中添加一个结构体或者类来作为成员。
[r10]
这个函数用来在屏幕上直观的打印树、
[r11]
这个文件也是二叉树的实现。但是这个相对于上面的那个来说更加的适合新手。更加的规范。我们可以结合起来。
[r12]
添加为公开的友元类,。其实我们也可以添加为私有的。
说明一点,我的这个函数查找结点查找节点和获取双亲节点的算法有一些问题,因为那个急于排序之后的,比如二叉搜索树可以那样。对于二叉树逻辑不是很严密,我推荐用层次遍历来进行查找,另外,很多人都对于这个二叉树的创建很头疼,其实这个我一般用的是层次创建。具体的算法实现网上有,所以此粗话就不发了。