二叉树

本文介绍了二叉树的基本概念,包括左子树和右子树的定义,以及二叉树在数据结构中的应用,如二叉查找树和二叉堆。同时,文章提供了使用C++实现二叉树基本操作的示例。

在计算机科学中,二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用作二叉查找树和二叉堆或是二叉排序数。二叉树的每个结点至多只有二棵子树(不存在出度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2的 i -1次方个结点;深度为k的二叉树至多有2^(k) -1个结点;对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为

 ,深度为2的结点数为
 ,则
 =
 + 1。

c++代码实现基本操作:

//二叉树
#include<cstdio>
#include<iostream>
#include<queue>
#include<stack>
using namespace std;

#define max(a,b) (((a)>(b))?(a):(b))
const int MAX = 50;
 
struct Node
{
	char data;//数据
	Node *lchild;//左孩子
	Node *rchild;//右孩子 
	Node(){
		lchild = rchild = NULL;
	}
};

class Tree
{
public:	
	Tree()
	{
		root = createTree();
	}
	~Tree(void)//析构 
	{
		destroyTree(root);
		root = NULL;
	}
	Node* getRoot()const //返回根 
	{
		return root;
	}
	void destroyTree(Node *&h);//摧毁 
	Node* createTree();//构造 
	void preOrder(Node* &p);//前序 
	void inOrder(Node* &p);//中序
	void postOrder(Node* &p);//后序
	void preOrderN(Node* p);//非递归前序,栈模拟 
	void inOrderN(Node* p);//非递归中序
	void postOrderN(Node* p);//非递归后序
	 
	void levelOrder(Node* &p);//层序
	void printInTree(Node* &p, int level);//树状打印 
	
	int treeHeight(Node* &p);//树高度
	int numOfLeaf(Node* &p);//叶子节点数目 
	int numOfNode(Node* &p);//节点数目
	int numOfNLeaf(Node* &p);//非叶子节点数目 
	
	
private:
	Node *root; 
};

Node* Tree::createTree()//前序建立 
{
	Node *root;
	char ch;
	cin >> ch;
	if(ch == '#')
		root = NULL;
	else
	{
		root = new Node;
		root->data = ch;
		root->lchild = createTree();
		root->rchild = createTree();
	}
	
	return root;
}

void Tree::preOrder(Node* &p)//前序 
{
	if(p!=NULL)
	{
		printf("%c ",p->data);
		preOrder(p->lchild);
		preOrder(p->rchild);
	}
	else
		return;
}

void Tree::inOrder(Node* &p)//中序
{
	if(p!=NULL)
	{
		inOrder(p->lchild);
		printf("%c ",p->data);
		inOrder(p->rchild);
	}
	else
		return;
}

void Tree::postOrder(Node* &p)//后序
{
	if(p!=NULL)
	{
		postOrder(p->lchild);
		postOrder(p->rchild);
		printf("%c ",p->data);
	}
	else
		return;
}

void Tree::levelOrder(Node* &p)//层序 
{
	queue<Node*> qnode;
	if(p!=NULL)
		qnode.push(p);
	while(!qnode.empty())
	{
		Node* tmp;
		tmp = qnode.front(); 
		printf("%c ",tmp->data);
	
		if(tmp->lchild)
			qnode.push(tmp->lchild);
		if(tmp->rchild)
			qnode.push(tmp->rchild);	
		qnode.pop();
	}
}

void Tree::inOrderN(Node* p)//中序非递归
{
	stack<Node*> st;

	while(p!=NULL || !st.empty())
	{
		while(p)
		{
			st.push(p);
			p = p->lchild;
		}
		if(!st.empty())
		{
			p = st.top();
			st.pop();
			printf("%2c", p->data);
			p = p->rchild;
		}
	}
} 

void Tree::preOrderN(Node* p)//前序非递归
{
	stack<Node*> st;

	while(p!=NULL || !st.empty())
	{
		while(p)
		{
			printf("%2c", p->data);
			st.push(p);
			p = p->lchild;
		}
		
		if(!st.empty())
		{
			p =st.top();
			st.pop();
			p = p->rchild;
		}
	}
} 

void Tree::postOrderN(Node* p)//后序非递归
{
	stack<Node*> st;
	
	Node *q;
	q = NULL;
	
	while(p!=NULL || !st.empty()) 
	{
		while(p)//p不为空访问根节点 遍历左子树
		{
			st.push(p);
			p = p->lchild;
		}
		if(!st.empty())
		{
			p = st.top();
			if(p->rchild==NULL || p->rchild==q)//没有左子树或者已经访问过左子树 
			{
				printf("%2c", p->data);
				q= p;
				p = NULL;
				st.pop();
			}
			else
				p = p->rchild;
		}
	}
} 

void Tree::printInTree(Node* &p, int level)//树状打印 
{
	int i;
	if(p == NULL)
		return;
	printInTree(p->rchild,level+1);//打印右子树 
	
	for(i=0; i<level; ++i)
	{
		printf("  ");
	}
	printf("%c\n", p->data);
	printInTree(p->lchild, level+1);
}

void Tree::destroyTree(Node* &h)
{
	if(h!=NULL)
	{
		destroyTree(h->lchild);
		destroyTree(h->rchild);
		delete h;
	}
}

int Tree::treeHeight(Node* &p)//树高
{
	if(p==NULL)
		return 0;
	else
		return 1+max(treeHeight(p->lchild),treeHeight(p->rchild)); 
} 

int Tree::numOfLeaf(Node* &p)//叶子几点数目
{
	if(p==NULL)
		return 0;
	else if(p->lchild==NULL && p->rchild==NULL)
		return 1;
	else
		return numOfLeaf(p->lchild)+numOfLeaf(p->rchild);
} 

int Tree::numOfNode(Node* &p)//节点数目
{
	if(p==NULL)
		return 0;
	else
		return 1+numOfNode(p->lchild)+numOfNode(p->rchild);
} 

int Tree::numOfNLeaf(Node* &p)//非叶子节点数目
{
	if(p==NULL || (p->rchild==NULL && p->lchild==NULL))
		return 0;
	else
		return  1+numOfNLeaf(p->rchild) + numOfNLeaf(p->rchild); 
}

int
main(void)
{
	Tree t;
	Node *root = t.getRoot();
	printf("前序递归为"); 
	t.preOrder(root);
	printf("\n前序非递归为"); 
	t.preOrderN(root);
	printf("\n中序递归为"); 
	t.inOrder(root);
	printf("\n中序非递归为"); 
	t.inOrderN(root);
	printf("\n后序递归为");
	t.postOrder(root);
	printf("\n后序非递归为");
	t.postOrderN(root);
	printf("\n层序为");
	t.levelOrder(root);
	printf("\n左转90后树状打印\n");
	t.printInTree(root,1);
	printf("\n树高%d", t.treeHeight(root));
	printf("\n叶子节点数目%d", t.numOfLeaf(root));
	printf("\n节点数目%d", t.numOfNode(root));
	printf("\n非叶子节点数目%d", t.numOfNLeaf(root)); 
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值