题目:二叉树的遍历设计
一、需求分析与功能描述
现代社会生活中,计算机扮演着重要角色,而随着计算机运行速度的不断加快,对数据的处理能力也日益增强,因此,程序所涉及的数据很多,如何科学有效的对数据进行操作,使得计算机的时间和空间利用率最高是一个问题。针对这样的问题,我选择了二叉树对数据的各种操作作为我的课程设计主题,希望通过二叉树来提高对数据的处理能力,促进对数据结构课程的理解。我的这个课程设计也同样为二叉树方面学习还需进步的同学作为参考,共同进步。
程序功能包括建立二叉树,二叉树的递归遍历,非递归遍历,查询二叉树的深度,查询每层的结点数,查找两个结点的最近共同祖先,打印二叉树,程序运行后显示界面信息,输入相应数字会进入相应的功能,用户输入完数据,程序会输出运行结果,测试数据均为字符型数据
- 数据结构的选择与设计
在遍历算法的实现中使用了栈结构与队列结构,这大大方便了二叉树的遍历。( 数组,二叉树,栈,队列,线性表)
- 算法的选择与设计
在本次课程设计中,二叉树的建立使用了递归算法,遍历则同时使用了递归与非递归的算法,在前序、中序、后续遍历算法中,分别实现了递归与非递归算法,从实际应用中体验了递归这一算法的优越性
(二叉树的中序、前序、后序的递归、非递归遍历算法,层次序遍历非
递归算法,栈、队列的实现算法)
void preorder();
void inorder();
void postorder();
void levelorder();
int count();
int depth();
void display(ostream &os);
void LevelNum();
void PreOrder();
void PostOrder();
void creat();
T leastCommanAncestor(T va,T vb);
protected:
void creat(BiNode<T>*&root);
void release(BiNode<T>*&root);
BiNode<T>*Build(T ary[],int num,T node,int idx );
void PreOrder(BiNode<T>*root);
void PostOrder(BiNode<T>*root);
void LevelNum(BiNode<T>*root);
void preorder(BiNode<T>*root);
void inorder(BiNode<T>*root);
void postorder(BiNode<T>*root);
void levelorder(BiNode<T>*root);
int count(BiNode<T>*root);
int depth(BiNode<T>*root);
void display(ostream&os,BiNode<T>*root,int dep);
bool leastCommanAncestor(BiNode<T>*root,T va,T vb,BiNode<T>*&result,BiNode<T>*parrent);
private:
BiNode<T> *rootptr;
//实现外部递归调用
void BiTree<T>::creat()
{
creat(rootptr);
}
//类体内递归#创建二叉树
template <typename T>
void BiTree<T>::creat(BiNode<T>*&root)
{
T item;
cin>>item;
if(item=='#')
root =NULL;
else
{
root=new BiNode<T>;
root->data=item;
creat(root->lchild);
creat(root->rchild);
}
}
- 测试结果
- 分析与总结
创建二叉树:依次输入二叉树的前序遍历序列,构建相应的二叉树
二叉树的遍历:递归算法,非递归算法,调用相应函数进行测试,结果正确
求二叉树深度和结点数:创建一个二叉树,调用相关函数,测试结果正确
计算每层结点数:测试结果正确
求最近共同祖先,测试结果正确
这次的课程设计我选择了二叉树的遍历,因为树结构是数据结构课程的典型内容,而且综合使用了多种逻辑结构,具有代表性,可以锻炼个人编程能力。在刚开始选题后,我感觉无从下手,一是因为没有实践经验,二是因为对数据结构课程的内容没有把握到位,然后在参考一些专业书籍并且学习了之前其他人的课程设计,才逐渐可以上手去自己做。在做了一小段后我发现如果不使用数组来建立二叉树是很麻烦的一件事,每个结点的信息都靠键盘输入是不合理的,于是运用了数组这一数据类型。在之后的递归算法中,我遇到的最大困难是如何实现递归,为此我参考了一本专业书籍,学会了如何正确使用递归方法,这也让我感觉到学习与应用是不可分开的。对于非递归算法,我使用了栈结构和队列结构,分别用于前序遍历、中序、后序遍历、非递归层次序遍历方法中。使用栈和队列的过程中,我在实践中又学习了栈和队列的一些知识,提高了各种逻辑结构之间的综合运用能力。
通过这次课程设计,我发现,知识不仅仅是在课本上,多查阅一些资料能够更好的完成课题,并且,只有把书本上的知识实际应用下来,才能把知识学到融会贯通,而且学习过程中一定不要怕繁琐,调试过程中一定会遇到一些难以解决的问题,这个时候我需要和老师和同学去请教,还有慢慢耐心地调试,才可以调试成功
总体来说,在本次课程设计中,我深刻体会了再面向对象程序设计中数据结构的实现方法,既学到了专业知识,也体会到“温故知新”的乐趣,因此如果还有课程设计我还会积极参加,在实践中锻炼自己的能力水平。我会再接再厉,更好的学习数据结构这门高深莫测的学科
附录:代码
#include<iostream>
using namespace std;
#include<stack>
#include<queue>
template<typename T>
struct BiNode
{
BiNode<T>*rchild,*lchild;//指向左右孩子的指针
T data;//结点数据信息
};
template<typename T>
class BiTree
{
//template<typename T>
friend ostream & operator <<(ostream &os,BiTree<T> &bt);
public:
BiTree();
BiTree(int m) {};
BiTree(T ary[],int num,T node);
~BiTree();
void preorder();
void inorder();
void postorder();
void levelorder();
int count();
int depth();
void display(ostream &os);
void LevelNum();
void PreOrder();
void PostOrder();
void creat();
T leastCommanAncestor(T va,T vb);
protected:
void creat(BiNode<T>*&root);
void release(BiNode<T>*&root);
BiNode<T>*Build(T ary[],int num,T node,int idx );
void PreOrder(BiNode<T>*root);
void PostOrder(BiNode<T>*root);
void LevelNum(BiNode<T>*root);
void preorder(BiNode<T>*root);
void inorder(BiNode<T>*root);
void postorder(BiNode<T>*root);
void levelorder(BiNode<T>*root);
int count(BiNode<T>*root);
int depth(BiNode<T>*root);
void display(ostream&os,BiNode<T>*root,int dep);
bool leastCommanAncestor(BiNode<T>*root,T va,T vb,BiNode<T>*&result,BiNode<T>*parrent);
private:
BiNode<T> *rootptr;
};
//实现外部递归调用
void BiTree<T>::creat()
{
creat(rootptr);
}
//类体内递归#创建二叉树
template <typename T>
void BiTree<T>::creat(BiNode<T>*&root)
{
T item;
cin>>item;
if(item=='#')
root =NULL;
else
{
root=new BiNode<T>;
root->data=item;
creat(root->lchild);
creat(root->rchild);
}
}
template <typename T>
void BiTree<T>::PreOrder()
{
PreOrder(rootptr);
}
template <typename T>
void BiTree<T>::PreOrder(BiNode<T>*root)
{
stack<BiNode<T>*>s;
while(root!=NULL||!s.empty())
{
while(root)
{
cout<<root->data;
s.push(root);
root=root->lchild;
}
if(!s.empty())
{
root=s.top();
s.pop();
root=root->rchild;
}
}
}
template <typename T>
void BiTree <T>::PostOrder()
{
PostOrder(rootptr);
}
template <typename T>
void BiTree<T>::PostOrder(BiNode<T>*root)
{
stack<BiNode<T>*> s;
BiNode<T> *P=root;
BiNode<T> *pre=NULL;
while(p||!s.empty())
{
while(p)
{
s.push(p);
p=p->lchild;
}
p=s.top();
if(p->rchild==NULL||p->rchild==pre)
{
cout<<p->data;
s.pop();
pre=p;
p=NULL;
}
else
{
p-p->rchild;
}
}
}
template<typename T>
int BiTree<T>::depth()
{
return depth(rootptr);
}
template <typename T>
int BiTree<T>::depth(BiNode<T>*root)
{
int rdep,ldep;
if(root==NULL)
return 0;
else
{
ldep=depth(root->lchild);
rdep=depth(root->rchild);
return (rdep>ldep?rdep:ldep)+1;
}
}
template <typename T>
void BiTree<T>::LevelNum()
{
LevelNum(rootptr);
}
template <typename T>
void BiTree<T>::LevelNum(BiNode<T>*root)
{
queue<BiNode<T>*>q;
int front,rear,first,last,level;
front=rear=first=0;
last =level=1;
if(root)
{
q.push(root);
rear++;
while(front<rear)
{
root=q.front();
q.pop();
front++;
if(root->lchild)
{
q.push(root->lchild);
rear++;
}
if(root->rchild)
{
q.push(root->rchild);
rear++;
}
if(front==last)
{
cout<<"第"<<level<<"层有"<<last-first<<"个结点"<<endl;
level++;
last=rear;
first=front;
}
}
}
}
template <typename T>
T BiTree<T>::leastCommanAncestor(T n1,T n2)
{
return leastComanAncestor(rootptr,n1,n2);
}
template<typename T>
T BiTree<T>::leastCommanAncestor(BiNode<T>*root,T n1,T n2)
{
if(root==NULL||root->data==n1||root->data==n2)
return -1;
if((root->rchild!=NULL)&&(root->rchild->data==n1||root->rchild->data==n2))
return root->data;
if((root->lchild!=NULL)&&(root->lchild->data==n1||root->lchild->data==n2))
return root->data;
if(root->data>n1&&root->data<n2)
return root->data;
if(root->data>n1&&root->data>n2)
return leastCommanAncestor(root->lchild,n1,n2);
if(root->data<n1&&root->data<n2)
return leastCommanAncestor(root->rchild,n1,n2);
}
int main()
{
BiTree<char > Tree(1);
while (1)
{
cout<<"\t\t 欢迎使用本系统!! "<<endl;
cout<<"\t\t######################################## "<<endl;
cout<<"\t\t# # "<<endl;
cout<<"\t\t# 1--创建一颗二叉树并显示 # "<<endl;
cout<<"\t\t# 2--遍历二叉树 # "<<endl;
cout<<"\t\t# 3--查询二叉树的深度和结点数 # "<<endl;
cout<<"\t\t# 4--查询每层结点数 # "<<endl;
cout<<"\t\t# 5--查找两节点P 和Q 的最近共同祖先 # "<<endl;
cout<<"\t\t# 6--退出 # "<<endl;
cout<<"\t\t# # "<<endl;
cout<<"\t\t######################################## "<<endl;
cout<<" 请输入你的选择:" ;
int x;
cin>>x;
switch (x)
{
case 1:
{
cout<<" 请输入二叉树的前序遍历:" <<endl;
cout<<" (以#作为分支结尾,例如:A B # # C # #)" <<endl;
Tree.creat();
cout<<Tree;
cout<<endl;
}
break ;
case 2:
{
cout<<endl;
cout<<" 前序遍历为:" ;
Tree.PreOrder();
cout<<endl;
cout<<" 中序遍历为:" ;
Tree.inorder();
cout<<endl;
cout<<" 后序遍历为:" ;
Tree.PostOrder();
cout<<endl;
cout<<" 层序遍历为:" ;
Tree.levelorder();
cout<<endl;
cout<<endl;
}
break;
case 3:
{
cout<<" 树的深度为:" <<Tree.depth()<<endl;
cout<<" 树的结点数:" <<Tree.count()<<endl;
cout<<endl;
}
break ;
case 4:
{
Tree.LevelNum();
}
break ;
case 5:
{
char ch1,ch2;
cout<<" 请输入P 数据信息:" ;
cin>>ch1;
cout<<" 请输入Q 数据信息:" ;
cin>>ch2;
cout<<ch1<<" 和" <<ch2<<" 的最近共同祖先是" <<Tree.leastCommanAncestor(ch1, ch2)<<endl;
}
break ;
case 6:
{ return;
}
break ;
default :
cout<<" 请输入正确的选择!!!" <<endl;
}
}
}