【树】二叉树的各种操作

本文介绍了如何使用递归和非递归来构建、遍历和分析二叉树,包括先序、中序、后序遍历以及层次遍历等方法,同时展示了如何计算二叉树的高度和叶子节点数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BinaryTree.h

#ifndef BINARYTREE_H
#define BINARYTREE_H

#include<iostream>
#include<stack>
#include<queue>
//binary tree node
struct binary_tree_node{
	char data;
	binary_tree_node* lchild;
	binary_tree_node* rchild;
	binary_tree_node() :lchild(NULL), rchild(NULL){}
	binary_tree_node(char ch) :data(ch), lchild(NULL), rchild(NULL){}
};
//BinaryTree
class BinaryTree{
public:
	typedef binary_tree_node node_value;
	typedef binary_tree_node* node_pointer;
	BinaryTree();
	~BinaryTree();
	node_pointer get_root();
	void create_preorder(node_pointer& p);

	void preorder_recursive(node_pointer p);
	void inorder_recursive(node_pointer p);
	void postorder_recursive(node_pointer p);

	void preorder_no_recursive(node_pointer p);
	void preorder_no_recursive2(node_pointer p);
	void inorder_no_recursive(node_pointer p);
	void postorder_no_recursive(node_pointer p);

	void levelorder(node_pointer p);
	void tree_depth(node_pointer p, int& depth, int level);
	int leaf_count(node_pointer p);
	int node_count(node_pointer p);
private:
	void destroy(node_pointer p);
private:
	node_pointer root;
};

BinaryTree::BinaryTree() :root(NULL){}
BinaryTree::~BinaryTree(){
	destroy(root);
	root = NULL;
}
void BinaryTree::destroy(node_pointer p){
	if (p == NULL)
		return;
	destroy(p->lchild);
	destroy(p->rchild);
	delete p;
}
BinaryTree::node_pointer BinaryTree::get_root(){
	return root;
}
void BinaryTree::create_preorder(node_pointer& p){
	char ch;
	std::cin >> ch;
	if (ch == '#')
		p = NULL;
	else{
		p = new node_value(ch);
		create_preorder(p->lchild);
		create_preorder(p->rchild);
	}
}
void BinaryTree::preorder_recursive(node_pointer p){
	if (p == NULL)
		return;
	std::cout << p->data << ' ';
	preorder_recursive(p->lchild);
	preorder_recursive(p->rchild);
}
void BinaryTree::inorder_recursive(node_pointer p){
	if (p == NULL)
		return;
	inorder_recursive(p->lchild);
	std::cout << p->data << ' ';
	inorder_recursive(p->rchild);
}
void BinaryTree::postorder_recursive(node_pointer p){
	if (p == NULL)
		return;
	postorder_recursive(p->lchild);
	postorder_recursive(p->rchild);
	std::cout << p->data << ' ';
}
/*
先让根进栈,只要栈不为空,就可以做弹出操作,
每次弹出一个结点,就把它的右孩子和左孩子依次入栈,这样可以保证右子树在栈中总处于左子树的下面。
*/
void BinaryTree::preorder_no_recursive(node_pointer p){
	if (p == NULL)
		return;
	std::stack<node_pointer> stk;
	stk.push(p);
	while (!stk.empty()){
		node_pointer cur = stk.top();
		std::cout << cur->data << ' ';
		stk.pop();
		if (cur->rchild)
			stk.push(cur->rchild);
		if (cur->lchild)
			stk.push(cur->lchild);
	}
}
/*
对于任一结点P:
1)访问结点P,并将结点P入栈;
2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);
若不为空,则将P的左孩子置为当前的结点P;
3)直到P为NULL并且栈为空,则遍历结束。
*/
void BinaryTree::preorder_no_recursive2(node_pointer p){
	if (p == NULL)
		return;
	std::stack<node_pointer> stk;
	node_pointer cur = p;
	while (cur != NULL || !stk.empty()){
		while (cur != NULL){
			std::cout << cur->data << ' ';
			stk.push(cur);
			cur = cur->lchild;
		}
		if (!stk.empty()){
			cur = stk.top();
			stk.pop();
			cur = cur->rchild;
		}
	}
}
/*
对于任一结点P,
1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
3)直到P为NULL并且栈为空则遍历结束
*/
void BinaryTree::inorder_no_recursive(node_pointer p){
	if (p == NULL)
		return;
	std::stack<node_pointer> stk;
	node_pointer cur = p;
	while (cur != NULL || !stk.empty()){
		while (cur != NULL){
			stk.push(cur);
			cur = cur->lchild;
		}
		if (!stk.empty()){
			cur = stk.top();
			std::cout << cur->data << ' ';
			stk.pop();
			cur = cur->rchild;
		}
	}
}
/*
对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;
或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,也可以直接访问它。
若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了
左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
*/
void BinaryTree::postorder_no_recursive(node_pointer p){
	if (p == NULL)
		return;
	std::stack<node_pointer> stk;
	stk.push(p);
	node_pointer cur;
	node_pointer pre = NULL;
	while (!stk.empty()){
		cur = stk.top();
		if ((cur->lchild == NULL&&cur->rchild == NULL) || pre != NULL && (cur->lchild == pre || cur->rchild == pre)){
			std::cout << cur->data << ' ';
			stk.pop();
			pre = cur;
		}
		else{
			if (cur->rchild)
				stk.push(cur->rchild);
			if (cur->lchild)
				stk.push(cur->lchild);
		}
	}
}
/*
先让根进队列,只要队列不为空,就可以做pop操作,
每次pop一个结点,就把它的左孩子和右孩子依次入队列,这样可以保证层次遍历。
*/
void BinaryTree::levelorder(node_pointer p){
	if (p == NULL)
		return;
	std::queue<node_pointer> que;
	que.push(p);
	while (!que.empty()){
		node_pointer temp = que.front();
		std::cout << temp->data << ' ';
		if (temp->lchild)
			que.push(temp->lchild);
		if (temp->rchild)
			que.push(temp->rchild);
		que.pop();
	}
}
void BinaryTree::tree_depth(node_pointer p, int& depth, int level){
	if (p == NULL)
		return;
	if (level>depth)
		depth = level;
	tree_depth(p->lchild, depth, level + 1);
	tree_depth(p->rchild, depth, level + 1);
}
int BinaryTree::leaf_count(node_pointer p){
	if (p == NULL)
		return 0;
	else if (p->lchild == NULL&&p->rchild == NULL)
		return 1;
	else
		return (leaf_count(p->lchild) + leaf_count(p->rchild));
}
int  BinaryTree::node_count(node_pointer p){
	if (p == NULL)
		return 0;
	else
		return (1 + node_count(p->lchild) + node_count(p->rchild));
}

#endif
main.cpp

#include"BinaryTree.h"
using namespace std;

void menu(){
	cout << "========================================================================" << endl;
	cout << "1.输入字符序列,以先序序列建立二叉树!" << endl;
	cout << "2.先序、中序、后序遍历二叉树(递归算法)!" << endl;
	cout << "3.先序、中序、后序遍历二叉树(非递归算法)!" << endl;
	cout << "4.层次遍历二叉树!" << endl;
	cout << "5.求二叉树的高度!" << endl;
	cout << "6.求二叉树的叶子个数!" << endl;
	cout << "7.求二叉树的节点个数!" << endl;
	cout << "0.退出程序!" << endl;
	cout << "========================================================================" << endl;
}

int main(){
	int choose;
	int depth;
	int level;
	bool flag = true;
	BinaryTree binary_tree;
	binary_tree_node* root = binary_tree.get_root();
	while (flag){
		menu();
		cout << "请输入要选择的功能:";
		cin >> choose;
		switch (choose){
		case 1:
			cout << "请输入二叉树中的元素,空的左右孩子以#替代:" << endl;
			binary_tree.create_preorder(root);
			break;
		case 2:
			cout << "先序遍历:" << endl;
			binary_tree.preorder_recursive(root);
			cout << endl << "中序遍历:" << endl;
			binary_tree.inorder_recursive(root);
			cout << endl << "后序遍历:" << endl;
			binary_tree.postorder_recursive(root);
			cout << endl;
			break;
		case 3:
			cout << "先序遍历:" << endl;
			cout << "方法一:";
			binary_tree.preorder_no_recursive(root);
			cout << endl << "方法二:";
			binary_tree.preorder_no_recursive2(root);
			cout << endl << "中序遍历:" << endl;
			binary_tree.inorder_no_recursive(root);
			cout << endl << "后序遍历:" << endl;
			binary_tree.postorder_no_recursive(root);
			cout << endl;
			break;
		case 4:
			cout << "层次遍历:" << endl;
			binary_tree.levelorder(root);
			cout << endl;
			break;
		case 5:
			depth = 1;
			level = 1;
			binary_tree.tree_depth(root, depth, level);
			cout << "二叉树的高度为:" << depth << endl;
			break;
		case 6:
			cout << "二叉树的叶子个数为:" << binary_tree.leaf_count(root) << endl;
			break;
		case 7:
			cout << "二叉树的节点个数为:" << binary_tree.node_count(root) << endl;
			break;
		case 0:
			flag = false;
			break;
		default:
			cout << "输入错误,请重新输入" << endl;
		}
	}

	return 0;
}

参考:

http://blog.youkuaiyun.com/hackbuteer1/article/details/6583988

http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值