目的:使用C++模板设计并逐步完善二叉树的抽象数据类型(ADT)。
内容:(1)请参照链表的ADT模板,设计二叉树并逐步完善的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考教材、课件,以及网盘中的链表ADT原型文件,自行设计二叉树的ADT。)
注意:二叉树ADT的基本操作的算法设计很多要用到递归的程序设计方法。
(2)基本操作5:在二叉树的二叉链表存储形式建立的基础上,设计二叉树的层次遍历算法。完成后将其加入到二叉树的ADT基本操作集中。
注意:二叉树的层次遍历需要使用顺序队列来存储遍历的中间过程。
初始条件:二叉树T存在,visit是对结点操作的应用函数。
操作结果:层次遍历T,对每个结点调用函数visit一次且仅一次。一旦visit()失败,则操作失败。
参考函数原型:
(1)//层次遍历外壳(用户函数)
template<class ElemType>
bool LayerOrderTraverse(BinaryTree<ElemType> &T){
BinaryTreeNode<ElemType> *root;
root = T.GetRoot();
if(root == NULL) return false;
int num = 0;
T.LayerOrderTraverse( root, visit, num );
return true;
}
(2)//层次遍历,成员函数
template<class ElemType>
bool BinaryTree<ElemType>::LayerOrderTraverse(BinaryTreeNode<ElemType> *root, bool (*visit)(BinaryTreeNode<ElemType> *T, int &num), int &num) const;
输入说明 :
第一行:表示无孩子或指针为空的特殊分隔符
第二行:二叉树的先序序列(结点元素之间以空格分隔)
输出说明 :
第一行:二叉树层次遍历结果
输入范例 :#
A B # C D # # E # # F # G # H # #
输出范例 :
A,B,F,C,G,D,E,H
层次遍历和上一篇的前序中序后后序遍历差别还是蛮大滴。用的是队列。
下面是代码:
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<sstream>
#define MAXSIZE 10000
using namespace std;
/* 二叉表的结点定义 */
template<class ElemType>
struct BinaryTreeNode
{
ElemType data;
BinaryTreeNode<ElemType> *LChild, *RChild;
BinaryTreeNode() : LChild(NULL), RChild(NULL) {} //构造函数1,用于构造根结点
BinaryTreeNode(const ElemType &item, BinaryTreeNode<ElemType> *Lptr = NULL, BinaryTreeNode<ElemType> *Rptr = NULL) //构造函数2,用于构造其他结点
//函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
{
LChild = Lptr;
RChild = Rptr;
data = item;
}
ElemType getData()
{
return data; //取得结点中的数据
}
void SetLChild( BinaryTreeNode<ElemType> *link )
{
LChild = link; //修改结点的左孩子域
}
void SetRChild( BinaryTreeNode<ElemType> *link )
{
RChild = link; //修改结点的右孩子域
}
void SetData( ElemType value )
{
data = value; //修改结点的data域
}
BinaryTreeNode<ElemType> * GetLChild() const
{
return LChild; //获取左孩子结点
}
BinaryTreeNode<ElemType> * GetRChild() const
{
return RChild; //获取左孩子结点
}
};
template<class ElemType>
bool visit(BinaryTreeNode<ElemType> *root,int &num)
{
if(!root)
return false;
else
{
if(num==0)
{
cout<<root->data;
num++;
}
else
cout<<","<<root->data;
return true;
}
}
//二叉树
template<class ElemType>
class BinaryTree
{
private:
BinaryTreeNode<ElemType> *root; // 头指针
void BinaryTreeDestroy_Cursive( BinaryTreeNode<ElemType> *T ); //销毁树(递归准备,private)
public:
//无参数的构造函数
BinaryTree():root(NULL) {}
//带参数的构造函数
BinaryTree(const ElemType &item)
{
root = new BinaryTreeNode<ElemType>(item);
}
//生成树
void makeBinaryTree( const ElemType &item, BinaryTree &left, BinaryTree &right);
//拷贝构造函数
//LinkQueue(LinkQueueList<ElemType> &Queue);
//析构函数
//~BinaryTree()
//{
// BinaryTreeDestroy();
//}
//重载函数:赋值
//LinkList<ElemType>& operator=(LinkList<ElemType> &List);
//销毁树
void BinaryTreeDestroy();
//销毁子树
void ChildDestroy(int flag);
//返回二叉树结点的个数
int BinaryTreeSize( BinaryTreeNode<ElemType> *T ) const;
//判断二叉树是否为空
bool BinaryTreeisEmpty() const
{
return root == NULL;
}
//获取根结点元素值
ElemType GetRootData() const
{
return root->data;
}
//bool Location(ElemType &x, BinaryTreeNode<ElemType> * &location);
//设置根结点
void SetRoot(BinaryTreeNode<ElemType> * p)
{
root = p;
}
//获取根结点
BinaryTreeNode<ElemType> * GetRoot() const
{
return root;
}
//前序遍历
bool Pre(BinaryTreeNode<ElemType> *T,bool(*visit)(BinaryTreeNode<ElemType> *T,int &num),int &num) const; //前序遍历(递归)//num的初始值为0,作用为控制输出格式(最后1个结点后不加“,”)
//中序遍历
bool In(BinaryTreeNode<ElemType> *T,bool(*visit)(BinaryTreeNode<ElemType> *T,int &num),int &num) const; //中序遍历(递归)
//后序遍历
bool Post(BinaryTreeNode<ElemType> *T,bool(*visit)(BinaryTreeNode<ElemType> *T,int &num),int &num) const; //后序遍历(递归)
//层次遍历
bool Ceng(BinaryTreeNode<ElemType> *T,bool(*visit)(BinaryTreeNode<ElemType> *T,int &num),int &num) const;//层次遍历 (递归)
//建立二叉树的存储结构
BinaryTreeNode<ElemType>* CreateBinaryTree(vector<ElemType> &x, ElemType &sym, int &n);
};
//建立二叉树的存储结构 (递归部分,成员函数)
template<class ElemType>
BinaryTreeNode<ElemType>* BinaryTree<ElemType>::CreateBinaryTree(vector<ElemType> &x, ElemType &sym, int &n)
{
ElemType ch = x[n];
n++;
if (ch == sym)
{
return NULL;
}
else
{
BinaryTreeNode<ElemType> *Node = new BinaryTreeNode<ElemType>;
Node->data = ch;
Node->LChild = CreateBinaryTree(x, sym, n);
Node->RChild = CreateBinaryTree(x, sym, n);
return Node;
}
}
//建立二叉树的存储结构 (外壳)
template<class ElemType>
void CreateTree(BinaryTree<ElemType> &T, ElemType &str, ElemType &sym)
{
ElemType tmp;
vector<ElemType> t;
stringstream input_T(str);
while(input_T>>tmp)
{
t.push_back(tmp);
}
BinaryTreeNode<ElemType> *root;
int num=0;
root=T.CreateBinaryTree(t,sym,num);
T.SetRoot(root);
}
template<class ElemType>
void BinaryTree<ElemType>::makeBinaryTree(const ElemType &item, BinaryTree &left, BinaryTree &right)
{
root=new BinaryTreeNode<ElemType>(item,left.root,right.root);
left.root=NULL;
right.root=NULL;
}
template<class ElemType>//层次遍历,成员函数
bool BinaryTree<ElemType>::Ceng(BinaryTreeNode<ElemType> *T, bool (*visit)(BinaryTreeNode<ElemType> *T, int &num), int &num) const
{
BinaryTreeNode<ElemType> *p;
if(!T) return false;
queue<BinaryTreeNode<ElemType>*>Q;//大家注意这里的<>里面是BinaryTreeNode<ElemType>*,如果没有写这个,直接queue Q的话会报错说缺东西
Q.push(T);//本来还想着自己写一个队列的,结果太麻烦了,然后弄了好半天把自己绕昏了,然后最终还是用的头文件,标准库函数
while(!Q.empty())
{
p=Q.front();
Q.pop();
if(num==0)
{
cout<<p->data;
num++;
}
else
{
cout<<","<<p->data;
num++;
}
if(p->LChild)
Q.push(p->LChild);
if(p->RChild)
Q.push(p->RChild);
}
return true;
}
template<class ElemType>
bool Ceng(BinaryTree<ElemType> &T){
//用户函数,递归
BinaryTreeNode<ElemType> *root;
root = T.GetRoot();
if(root == NULL) return false;
int num = 0;
T.Ceng( root, visit, num );
return true;
}
int main()
{
BinaryTree<string>BT;
string mytree;
string sym;
getline(cin,sym);
getline(cin,mytree);
CreateTree(BT,mytree,sym);
Ceng(BT);
return 0;
}
就这样。我的第二篇博客,还希望多多支持呀~