杂谈
这篇文章竟然沉了,不是很甘心,上回说到目录形式打印,这次再丰富一下(挣扎下)。博主从网上观察了一下,虽然有横向打印树的,但总不是很完美,这次更新着眼点就在这边。
概述
本例实现了基本二叉树的先序创建,前序遍历,层次遍历,以及目录结构式的打印。
目录形式打印
这是需要说明的目录本质上就是先序遍历,但是要想做一个相对好看的目录结构的树(这里是指从左到右的打印,而非从上到下),需要对控制字符的打印下些文章。博主在做时依据以下思路进行的
1、目录结构中的左子树不需要做过多考虑,仅需要前面输出"-----"即可。
2.对于右子树,发现从根节点到该节点路径中,当且仅当路径中节点的存在右节点且该右结点未被访问(其实就是路径中下个结点不是该右结点),这样就能确定该右结点前面控制符的情况了,有未被访问的右结点就是”|“否则就是空格。
注:如果在阅读过程发现问题,欢迎斧正。
水平打印
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#define maxDeep 100
using namespace std;
template <typename T>
class TNode_normal{
public:
T data;
TNode_normal* lchild,* rchild;
TNode_normal(T e){
data = e;
rchild = lchild = NULL;
}
TNode_normal(){
data = 0;
rchild = lchild = NULL;
}
};
template <typename T>
class Tree_normal{
public:
Tree_normal(){
root = new TNode_normal<T>();
}
TNode_normal<T>*& getRoot(){return root;};
void createTree_normal(TNode_normal<T> *&node);
void preOrderTraverse(TNode_normal<T>* node);
int getDeep(TNode_normal<T>* node);
void draw(TNode_normal<T>* node,int level = 0);
void levelTraverse(TNode_normal<T>* node);
void findPath(TNode_normal<T>* node,TNode_normal<T>* e,vector<TNode_normal<T>*> &res,int level = 0);
void whetherDrawRChild(TNode_normal<T>* node,TNode_normal<T>* e,vector<int> &res);
// void whetherDrawRChild(TNode_normal<T>* node,TNode_normal<T>* e,stack<int> Result);
private:
TNode_normal<T> *root;
};
template <typename T>
void Tree_normal<T>::createTree_normal(TNode_normal<T> *&node){
//preOrder to create a binary tree
T e;
cin >> e;
// node->lchild = new TNode_normal<T>(e);
if(e != 0){
if(node == root)
root->data = e;
else
node = new TNode_normal<T>(e);
}
else return; //end if
cout << node->data << " left : ";
createTree_normal(node->lchild);
cout << node->data << " right : ";
createTree_normal(node->rchild);
}
template <typename T>
void Tree_normal<T>::preOrderTraverse(TNode_normal<T>* node){
// cout << "preOrderTraverse : ";
if(node != NULL && node->data !=0){
cout << node->data << " ";
}
else return;
preOrderTraverse(node->lchild);
preOrderTraverse(node->rchild);
}
template <typename T>
void Tree_normal<T>::levelTraverse(TNode_normal<T>* node){
queue<TNode_normal<T>*> levelQueue;
levelQueue.push(node);
while(!levelQueue.empty()){
if(levelQueue.front()->lchild) levelQueue.push(levelQueue.front()->lchild);
if(levelQueue.front()->rchild) levelQueue.push(levelQueue.front()->rchild);
cout << levelQueue.front()->data << " ";
levelQueue.pop();
}
}
int Max(int a,int b){
if(a >= b) return a;
else return b;
}
template <typename T>
int Tree_normal<T>::getDeep(TNode_normal<T>* node){
if(node == NULL) return 0;
return Max(getDeep(node->lchild) + 1,getDeep(node->rchild) + 1);
}
template <typename T>
void Tree_normal<T>::findPath(TNode_normal<T>* node,TNode_normal<T>* e,vector<TNode_normal<T>*> &res,int level){
//res[0]作为终止标志位
if(node != NULL && res[0] != e){
if(node == e) res[0] = e;
res[level + 1] = node;
}else{
if(res[0] != e) res[level + 1] = NULL;
level --;return;
}
findPath(node->lchild,e,res,++level);
findPath(node->rchild,e,res,level);
}
template <typename T>
void Tree_normal<T>::whetherDrawRChild(TNode_normal<T>* node,TNode_normal<T>* e,vector<int> &res){
//flag 指明指明左右子树关系
//preOrdertraverse to find e whether has rchild
//res[0]为标志位
if(e == root){
res[0] = 0;return;
}
vector<TNode_normal<int>*> res2(maxDeep,NULL);
findPath(root,e,res2);
for(int i = 1;i < maxDeep && res2[i] != NULL ;i ++){
if(res2[i+1] && res2[i]->rchild != res2[i+1]) res[i] = 1;
}
}
template <typename T>
void Tree_normal<T>::draw(TNode_normal<T>* node,int level){
if(node != NULL && node->data != 0){
cout << "" <<node->data;
}else{
level --;return;
}
cout << " --L-- ";
draw(node->lchild,++ level);
vector<int> res(maxDeep,0);
whetherDrawRChild(root,node,res);
cout << "\n ";
for(int i = 0;i < level - 1;i ++){
if(res[i + 1]) cout << "| " << " ";
else cout << " " << " ";
}
cout << " --R-- ";
draw(node->rchild, level);
}
int main()
{
Tree_normal<int> t;
t.createTree_normal(t.getRoot());
cout << "前序遍历:\n";
t.preOrderTraverse(t.getRoot());
cout << "\n层次遍历:\n";
t.levelTraverse(t.getRoot());
cout << "\n最大深度:\n";
cout << t.getDeep(t.getRoot());
cout << "\n目录形式打印:\n";
t.draw(t.getRoot());
return 0;
}
##测试用例
/*
5
4
2
0
0
1
0
9
0
0
3
8
0
0
7
0
4
3
0
2
0
0
0
*/