二叉树的相关操作

目的:
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;
}


3. 结果



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值