目的:
1. 实现二叉树的生成,以先序序列输入生成二叉树,空格字符表示为空;
2. 先序,中序,后序的递归和非递归遍历;
3. 递归和非递归实现计算叶子节点数目;
4. 递归和非递归计算二叉树的高度;
5. 按层次遍历二叉树。
1. 实现二叉树的生成,以先序序列输入生成二叉树,空格字符表示为空;
2. 先序,中序,后序的递归和非递归遍历;
3. 递归和非递归实现计算叶子节点数目;
4. 递归和非递归计算二叉树的高度;
5. 按层次遍历二叉树。
实现如下:
// Note:Your choice is C++ IDE
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
typedef struct BiTNode
{
char data;
struct BiTNode* lchild, *rchild;
}BiTNode,*BiTree;
void CreateBitree( BiTree& bt )
{
char data;
//cin >> data;
data = getchar();
if( data == '\n' )
{
return;
}
if( data != ' ' )
{
bt = NULL;
bt = new BiTNode;
if( bt == NULL )
{
cout << "无法分配内存!" << endl;
system( "pause" );
return;
}
bt->data = data;
bt->lchild = NULL;
bt->rchild = NULL;
CreateBitree( bt->lchild );
CreateBitree( bt->rchild );
}
return;
}
// 先序递归遍历
void PreTrave( BiTree bt )
{
BiTree p = bt;
if( p != NULL )
{
cout << p->data << " ";
PreTrave( p->lchild );
PreTrave( p->rchild );
}
return;
}
//非递归先序遍历
// 先访问根节点,然后把右子树和左子树先后入栈,这样就可以先访问左子树后访问右子树了
void prePrint( BiTree bt )
{
if( bt == NULL )
{
return;
}
BiTree pNode = NULL;
stack<BiTree> st;
st.push(bt);
while( !st.empty() )
{
pNode = st.top();
st.pop();
cout << " " << pNode->data;
if( pNode->rchild != NULL ) //右子树先入栈
{
st.push(pNode->rchild);
}
if( pNode->lchild != NULL ) //再入左子树
{
st.push(pNode->lchild);
}
}
return;
}
/*
* 利用栈进行前序遍历
* 1、从根节点开始,遍历左子树,输出父节点的内容,并将父节点入栈,并使得指针指向其左子树
* 2、遍历遇到节点为NULL时,取出栈顶元素,得到其右孩子节点
* 3、右孩子节点不为空时,此时将该右节点看作是根节点,重复1、2操作
* 4、右孩子节点为空时,继续出栈,得到右孩子节点,重复3、4操作
代码来源:http://blog.csdn.net/dazhong159/article/details/7862774
*/
void prePrint1( BiTree bt )
{
if( bt == NULL )
{
return;
}
BiTree pNode = bt;
stack<BiTree> st;
while( pNode != NULL || !st.empty() )
{
if( pNode != NULL )
{
cout << " " << pNode->data;
st.push(pNode);
pNode = pNode->lchild;
}
else
{
pNode = st.top();
st.pop();
pNode = pNode->rchild;
}
}
return;
}
void MidTrave( BiTree bt ) // 中序递归遍历
{
if( bt != NULL )
{
MidTrave( bt->lchild );
cout << bt->data << " ";
MidTrave( bt->rchild );
}
return;
}
//非递归中序遍历
/*
* 利用栈进行中序遍历
* 1、从根节点开始,遍历左子树,将父节点入栈
* 2、遍历遇到节点为NULL时,取出栈顶元素,输出节点内容,得到其右孩子节点
* 3、右孩子节点不为空时,此时将该右节点看作是根节点,重复1、2操作
* 4、右孩子节点为空时,继续出栈,重复3、4操作
代码来源:http://blog.csdn.net/dazhong159/article/details/7862774
*/
void midPrint( BiTree bt )
{
if( bt == NULL )
{
return;
}
BiTree pNode = bt;
stack<BiTree> st;
while( pNode != NULL || !st.empty() )
{
if( pNode != NULL ) // 左子树不为空则入栈
{
st.push(pNode);
pNode = pNode->lchild;
}
else // 左子树为空了,则出栈并访问
{
pNode = st.top();
st.pop();
cout << " " << pNode->data;
pNode = pNode->rchild;
}
}
return;
}
void BackTrave( BiTree bt ) // 后序递归遍历
{
if( bt != NULL )
{
BackTrave( bt->lchild );
BackTrave( bt->rchild );
cout << bt->data << " ";
}
}
typedef struct TPostTree
{
BiTree node;
int isFirst;
}TPostNode;
//非递归后序遍历
/*
* 利用栈后序遍历
* 1、首先创建一种新的数据结构,包含原来的数据结构和isFirst标志()
* 2、从根节点开始,入栈,将isFirst置为1,访问左子树
* 3、遇到节点为NULL时,如果isFirst==1,访问栈顶元素,得到该节点的右孩子
* 4、该节点的右孩子为NULL时,出栈,访问该节点,然后将该节点置为NULL,使下次循环必定会进入第3步
* 5、该节点的右孩子不为NULL时,将该右孩子当作根节点,重复2、3
代码来源:http://blog.csdn.net/dazhong159/article/details/7862774
*/
void backPrint( BiTree bt )
{
stack<TPostNode> st;
struct TPostTree treenode,treend;
BiTree pNode = bt;
while( pNode != NULL || !st.empty() )
{
if( pNode != NULL )
{
treenode.node = pNode;
treenode.isFirst = 1;
st.push(treenode);
pNode = pNode->lchild;
}
else if( st.top().isFirst ) //右
{
treend = st.top();
treend.isFirst = 0;
st.pop();
st.push(treend);
pNode = st.top().node->rchild; //找到右节点
}
else //根节点
{
pNode = st.top().node;
st.pop();
cout << " " << pNode->data;
pNode = NULL;
}
}
return;
}
//非递归计算叶子节点数目
int getLeafNum( BiTree bt )
{
int leafNum = 0;
BiTree pNode = NULL;
queue<BiTree> q;
if( bt == NULL )
{
return 0;
}
q.push(bt);
while( !q.empty() )
{
pNode = q.front();
q.pop();
if( pNode->lchild == NULL && pNode->rchild == NULL )
{
leafNum++;
}
if( pNode->lchild != NULL )
{
q.push(pNode->lchild);
}
if( pNode->rchild != NULL )
{
q.push(pNode->rchild);
}
}
return leafNum;
}
//递归求叶子数目
int RecurGetLeafNum( BiTree bt )
{
int leafNum = 0;
if( bt->lchild == NULL && bt->rchild == NULL )
{
return 1;
}
int leftLeafNum = 0;
int rightLeafNum = 0;
if( bt->lchild != NULL )
{
leftLeafNum = RecurGetLeafNum(bt->lchild);
}
if( bt->rchild != NULL )
{
rightLeafNum = RecurGetLeafNum(bt->rchild);
}
return leftLeafNum + rightLeafNum;
}
//非递归求树的高度
int getHeight( BiTree bt )
{
if( bt == NULL )
{
return 0;
}
int height = 0;
queue<BiTree> q;
int curVisitedNum = 0;
int lastLevelNum = 1;
int enQueuenum = 1; //当前入栈的序号,root为1
BiTree pNode = NULL;
q.push(bt);
while( !q.empty() )
{
pNode = q.front();
q.pop();
curVisitedNum++;
if( pNode->lchild != NULL )
{
q.push(pNode->lchild);
enQueuenum++;
}
if( pNode->rchild != NULL )
{
q.push(pNode->rchild);
enQueuenum++;
}
if( curVisitedNum == lastLevelNum ) //访问的是上一层最后一个节点
{
height++;
lastLevelNum = enQueuenum;
}
}
return height;
}
//递归求树的高度(左子树和右子树高度中的较大的值+根节点高度1)
int RecurGetHeight( BiTree bt )
{
if ( bt == NULL )
{
return 0;
}
int lh=RecurGetHeight( bt->lchild );
int rh=getHeight( bt->rchild );
return lh > rh ? lh+1:rh+1;
}
void TravelByLevel( BiTree bt ) //按层次遍历
{
if( bt == NULL )
{
return;
}
BiTree pNode = NULL;
queue<BiTree> q;
q.push(bt);
while( !q.empty() )
{
pNode = q.front();
q.pop();
cout << " " << pNode->data;
if( pNode->lchild != NULL )
{
q.push(pNode->lchild);
}
if( pNode->rchild != NULL )
{
q.push(pNode->rchild);
}
}
return;
}
/*
在建立二叉链表时,例如输入1 2 0 0 3 0 0,将建立以1为根节点,2为左子树,3为右子树的二叉树
表示如下:
1
/ \
2 3
*/
//测试数据:ABDXXXCEXXFXX,其中X表示空格
/*
*/
int main()
{
BiTree root = NULL;
cout << "请以加入节点的先序序列输入,构造二叉链表(输入空格代表将相应的节点置空): " << endl;
CreateBitree(root);
cout << "递归先序遍历的结果:" << endl;
PreTrave(root); // 或者prePrint(root);
cout << endl << "非递归先序遍历结果: " << endl;
prePrint(root);
cout << endl << "递归中序遍历的结果:" << endl;
MidTrave(root);
cout << endl << "非递归中序遍历的结果: " << endl;
midPrint(root);
cout << endl << "递归后序遍历的结果:" << endl;
BackTrave(root);
cout << endl << "非递归后序遍历的结果:" << endl;
backPrint(root);
cout << endl << "叶子数目为: " << RecurGetLeafNum(root) << endl; //或用getLeafNum(root)
cout << "二叉树的高度为: " << getHeight(root) << endl; // 或用RecurGetHeight(root);
cout << "按层次遍历二叉树: ";
fflush(stdout);
TravelByLevel(root);
cout << endl;
system("pause");
return 0;
}