数据结构实验: 按层次构造二叉树及二叉树遍历

1、实验题目

按层次(从上到下,从左到右的顺序)输入树的结点,如果该结点为空,则用一个特定的值替代(比如0或者.)。例如下面的图中,输入为e b f a d . g . . c(当然为了方便输入,也可以用#结束字符串的输入)

要求构造一棵如下的二叉树,当二叉树构造成功后,需要对其进行先序遍历,后序遍历,中序遍历。

 

2、按层次构造树的两种方法

对于如下的一棵树

 

输入:

为了构造上图所示的这样一棵二叉树,键盘上输入的顺序如下:

ebfad.g..c#

其中可以看到这是根据层次的一种输入,先输入第一层的结点,然后是第二层的结点,第三层….直到把所有的带信息的结点输入完。也可以看到,在输入的序列中,有.号,这是代表结点为空。注意在输入的时候,为空的结点也要这样输入进去。

 

=====================================================

源代码:

Copyright ©L迁客2012-05-19. All Rights Reserved.

=====================================================

#include<iostream>
#include<queue>
#include<stack>
using namespace std;

//定义数据结构
struct BIN_NODE
{
char data;
BIN_NODE* left;
BIN_NODE* right;
};

/****************************
为什么用【节点指针】构建队列和栈?
因为这样的话,在入栈和出栈时,
我们可以直接把节点连接起来(地址),
所以在构建二叉树时,每个节点就可以轻易地挂起来。
****************************/
typedef queue<BIN_NODE*> charQueue;
typedef stack<BIN_NODE*> charStack;

class Bin_tree
{
public:
Bin_tree();//构造函数,就是将root=NULL

//遍历二叉树
void buildTree();
void preorder();
void inorder();
void postorder();
private:
//遍历树的辅助函数
void recursive_inorder(BIN_NODE* root);
void recursive_preorder(BIN_NODE* root);
void recursive_postorder(BIN_NODE* root);

BIN_NODE* root;//树根
};

//构造函数
Bin_tree::Bin_tree()
{
root = NULL;
}

 

//构建二叉树
void Bin_tree:: buildTree()
{
/*******************
这两个队列是用来构建层次二叉树用的。
*******************/
charQueue A;
charQueue B;

//临时节点,构造队列的节点。
BIN_NODE* tempNode;

do
{
tempNode = new BIN_NODE();//为临时节点申请空间。

cout<<"请输入字符,以#号结束:"<<endl;
cin>>tempNode->data;
if(tempNode->data !='#')
{
A.push(tempNode);
}

}while(tempNode->data !='#');//以“#”号作为结束条件。


//构造树根
BIN_NODE* pHead = A.front();
A.pop();
B.push(pHead);

//构造树的节点。
BIN_NODE* pfather;
BIN_NODE* pLchild;
BIN_NODE* pRchild;


while(!(A.empty()))
{

//B队列取第一个元素,然后出列
pfather = B.front();
B.pop();

//A队列取前两个元素,然后两个也出列
pLchild = A.front();
A.pop();

/*******************
取第二个元素的时候,A队列可能已经没有了,
再用front()的话,会出现访问空指针的情况。
所以判断一下,空队列的时候,就置NULL。
*******************/
if( !(A.empty()) )
{
pRchild = A.front();
A.pop();
}
else
{
pRchild = NULL;
}


/*******************
构造二叉树,
如果不是“.”号,就直接挂到父节点,
如果是“.”号,那么就置NULL
*******************/
if(pLchild->data !='.')
{
pfather->left = pLchild;
}
else
{
pfather->left = NULL;
}

/******************
如果之前取A队列的第二个元素的时候,
就是置NULL的,那么就访问不到他的data了,
这里判断一下。
******************/
if(pRchild != NULL)
{
if(pRchild->data != '.')
{
pfather->right = pRchild;
}
else
{
pRchild->right = NULL;
}
}

/******************************
在构造孩子的时候,必须把每个孩子的孩子指向NULL,
因为如果不这样的话,在遍历的时候,
就会访问到没有的、不存在的孩子,就会报错,
之后遍历的时候,到达NULL就是该子树结束。
******************************/

/*****************
如果之前pRchild已经是空的了,
他的孩子就访问不到了,
所以这里判断一下。
*****************/

if(pLchild !=NULL)
{
pLchild->left = NULL;
pLchild->right = NULL;
}

if(pRchild != NULL)
{
pRchild->left = NULL;
pRchild->right = NULL;
}


/******************
如果左右孩子不是NULL,
就把左右孩子放入B队列中
******************/
if(pLchild != NULL)
{
B.push(pLchild);
}
if(pRchild !=NULL)
{
B.push(pRchild);
}

}

//把根节点赋值
root = pHead;

}


/*******************
对于遍历二叉树,这里用递归实现。
首先要搞清楚思路,
这里用了两层的递归,
刚开始本人也研究了好久,
然后参阅一些递归的实现算法后,
才理解清楚,递归的实际调用过程,
如果看不懂这样的递归调用,
可以借鉴“递归的非递归实现【栈】”的算法,
有助于理解!
********************/


//【先序遍历】层次二叉树
void Bin_tree::preorder()
{
cout<<"先序遍历…"<<endl;

recursive_preorder(root);

cout<<endl;
}


//【先序遍历】层次二叉树的辅助方法。
void Bin_tree::recursive_preorder(BIN_NODE* root)
{
BIN_NODE* p = root;//取根节点,进行操作。。

//打印访问到的当前节点
if(p != NULL)
{
cout<<p->data<<" -> ";//visit()
}

/*******************
递归遍历左右子树,
条件是,左右子树访问到NULL
*******************/
if(p->left != NULL)
{
recursive_preorder(p->left);
}
if(p->right != NULL)
{
recursive_preorder(p->right);
}

}

//【中序遍历】层次二叉树
void Bin_tree::inorder()
{
cout<<"中序遍历…"<<endl;

recursive_inorder(root);

cout<<endl;
}

//【中序遍历】层次二叉树的辅助函数
void Bin_tree::recursive_inorder(BIN_NODE* root)
{
BIN_NODE* p = root;//取根节点,进行操作。。


/*******************
要先走到最左子树,
直到访问到NULL,
也就是左子树尽头,
就返回,
开始访问节点。
*******************/
if(p == NULL)
{
return;
}

/*******************
先遍历到最左节点,
然后,访问该节点,
如果该节点不是NULL,
就【递归遍历】左、中、右节点。
*******************/
if(p->left != NULL)
{
recursive_inorder(p->left);
}

cout<<p->data<<" -> ";//visit()

if(p->right != NULL)
{
recursive_inorder(p->right);
}

}


//【后序遍历】层次二叉树
void Bin_tree::postorder()
{
cout<<"后序遍历…"<<endl;

recursive_postorder(root);

cout<<endl;
}

//【后序遍历】层次二叉树的辅助函数。
void Bin_tree::recursive_postorder(BIN_NODE* root)
{
BIN_NODE* p = root;//取根节点,进行操作。。

/*******************
要先走到最左子树,
直到访问到NULL,
也就是左子树尽头,
就返回,
开始访问节点。
*******************/
if(p == NULL)
{
return;
}

/*******************
先遍历到最左节点,
然后,访问该节点,
如果该节点不是NULL,
就【递归遍历】左、中、右节点。
*******************/


if(p->left != NULL)
{
recursive_postorder(p->left);
}

if(p->right != NULL)
{
recursive_postorder(p->right);
}

cout<<p->data<<" -> ";//visit()

}


void main()
{
Bin_tree tree ;
tree.buildTree();//构造树
tree.preorder();//先序遍历
tree.inorder();//中序遍历
tree.postorder();//后序遍历
}

 

======================================================

 

 

posted @ 2012-05-19 13:43  L迁客  阅读(647)  评论(0编辑  收藏  举报