数据结构(C++)——二叉树

本文详细介绍二叉树的各种遍历方法,包括递归与非递归方式的前序、中序、后序遍历,以及层次遍历等。同时提供了创建二叉树的方法和计算节点个数、树高度等功能。

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

1.前中后序递归遍历

2.前中后序非递归遍历

3.层次遍历

4.求节点个数,求高度

#include"AllHead.h"
#include<stack>
#include<queue>
#include"seqstack.h"

template<class T>
class BinTree;

template<class T>
class BinTreeNode
{
	friend class BinTree<T>;
private:
	BinTreeNode<T> *left;
	BinTreeNode<T> *right;
	T data;
public:
	BinTreeNode():left(NULL),right(NULL){}
	BinTreeNode(T d):data(d),left(NULL),right(NULL){}
	T getData(){return data;}
};
template<class T>
class BinTree
{
public:
	BinTreeNode<T> *root;
	char flag;
public:
	BinTree()
	{
		root = NULL;
		flag = '#';
	}
	BinTree(BinTree<T> &p)
	{
		BinTree<T> *p = new BinTree<T>;
		p->root = p->root;
	}
	~BinTree()
	{
		destory();
	}
public:
	bool IsEmpty()
	{
		return IsEmpty(root);
	}
	BinTreeNode<T>* search(T const &x)
	{
		return search(root,x);
	}
	void CreatBintree(T *&ch)
	{
		CreatBintree(root,ch);
	}
	void CreatBintree()
	{
		CreatBintree(root);
	}
	void PreOrder()
	{
		PreOrder(root);
	}
	void InOrder()
	{
		InOrder(root);
	}
	void PostOrder()
	{
		PostOrder(root);
	}
	size_t sizeNode()
	{
		return sizeNode(root);
	}
	size_t Height()
	{
		return Height(root);
	}
	BinTreeNode<T>* findParent(T x)
	{
		return findParent(root,x);
	}
public://非递归前中后序遍历!!!
	void preorder_un()
	{
		preorder_un(root);
	}
	void inorder_un()
	{
		inorder_un(root);
	}
	void postorder_un()
	{
		postorder_un(root);
	}
	void levelorder()//层次遍历
	{
		levelorder(root);
	}
	void destory()
	{
		destory(root);
	}
protected:
	void destory(BinTreeNode<T> *&p)
	{
		if(p!=NULL)
		{
			destory(p->left);
			destory(p->right);
			delete p;
			p=NULL;//这句不能少!!!
		}
	}
	void levelorder(BinTreeNode<T> *&p)
	{
		queue<T> qe;
		T top;
		BinTreeNode<T> *t = p;
		qe.push(t->data);
		BinTreeNode<T> *s;
		while(!qe.empty())
		{
			top = qe.front();
			cout<<top<<"-->";
			qe.pop();
			s = search(p,top);
			if(s->left!=NULL)
				qe.push(s->left->data);
			if(s->right!=NULL)
				qe.push(s->right->data);
		}
		
	}
//主要思想:任意一个结点N,只要他有左孩子,则在N入栈之后,N的左孩子必然也跟着入栈了
//所以当我们拿到栈顶元素的时候,
//先判断这个元素要么没有左孩子,要么其左孩子已经被访问过。
//所以此时我们就不关心它的左孩子了,我们只关心其右孩子。
//如果右孩子已经被访问过,或是没有右孩子,则输出这个节点
	void postorder_un(BinTreeNode<T> *&p)
	{
		Stack<T> st;
		BinTreeNode<T> *t = p;
		while(t||!st.isempty())
		{
			while(t)
			{
				st.push(t->data);
				st.tag[st.lenth()-1] = 0;//设置访问标记。0为第一次访问,1为第二次访问
				t = t->left;
			}//从根节点开始往左走,一路上每个节点都入栈。
			if(st.tag[st.lenth()-1] == 0)//第一次访问时转向同层的有节点
			{
				st.tag[st.lenth()-1] = 1;
				t = search(p,st.gettop());
				t = t->right;
			}
			else
			{
				while(st.tag[st.lenth()-1] == 1)
				{
					cout<<st.gettop()<<"--->";
					st.pop();
				}
			}
		}

	}
	void inorder_un(BinTreeNode<T> *&p)
	{
		T top;			
	    stack<T> st;
		BinTreeNode<T> *t = p;
		do
		{
			while(t!=NULL)
			{
			   st.push(t->data);
			   t = t->left;
			}//最左边的节点找到,并一路压入栈中。
			if(!st.empty())
			{
				top = st.top();
				st.pop();
				cout<<top<<"-->"; //输出左孩子
				if(!st.empty())
				{
					top = st.top();
					st.pop();
					cout<<top<<"-->";//输出根
				}
				t = search(p,top);
				t = t->right;//转到右孩子上
			}

		}while(t!=NULL||!st.empty());//依次循环
		
	}
	void preorder_un(BinTreeNode<T> *t)
	{
		if(t!=NULL)
		{
			T top;
			BinTreeNode<T> *p;
			stack<T> st;
			st.push(t->data);//根节点压入栈中
			while(!st.empty())//只要栈不空
			{
				top = st.top();
				st.pop();
				cout<<top<<"-->";//取出栈顶元素并输出
				p = search(t,top);
				if(p->right != NULL)
					st.push(p->right->data);//把输出的这个栈顶元素的右孩子压入栈中
				if(p->left != NULL)
					st.push(p->left->data);//再把左孩子压入栈中  **特别注意这个顺序不能变!!!
			}
		}
	}
/	
//十分注意了!!!                                                                                                 //
//BinTreeNode<T> *&t(这里的t一定要加引用一定要引用传参,因为传进去的root本身就是指针,                             //
//如果不是引用传参的话会导致值一直不改变)                                                                          //
//ch要用引用传参否则会出现错误。(A——+B——+C——+C——+),与上面相同ch本身就是个指向字符串头的地址的指针!!!!//
//其实也就是跟上面的意思是一样的(两者如果不加引用传参的话就跟函数传值调用一样!!!)                             //
/
	void CreatBintree(BinTreeNode<T>*&t,T *&ch)//用字符串创建一个二叉树
	{
		if(*ch =='\0'||*ch == flag)
			t = NULL;
		else
		{
			t = new BinTreeNode<T>(*ch);
			//t = new BinTreeNode<T>;
			//t->data = *ch;
			CreatBintree(t->left,++ch);
			CreatBintree(t->right,++ch);
		}
	}
	BinTreeNode<T>* findParent(BinTreeNode<T>*t,T x)
	{
		if(t == NULL)
			return NULL;
		BinTreeNode<T> *p = search(t,x);
		if(p == NULL||p == t)//这是为了判断p不是根节点!!!
			return NULL;
		if(t->left->data == x||t->right->data == x)
			return t;
		p = findParent(t->left,x);
		if(p!=NULL)
			return p;
		return findParent(t->right,x);
    }
	BinTreeNode<T>* search(BinTreeNode<T> *&t,T const &x)
	{
		if(t == NULL)
			return NULL;
		if(t->data == x)
			return t;
		BinTreeNode<T> *s;
		s = search(t->left,x);
		if(s!=NULL)
			return s;
		return search(t->right,x);
		
	}
	bool IsEmpty(BinTreeNode<T> *t)
	{
		return t == NULL; 
	}
	size_t Height(BinTreeNode<T> *t)
	{
		if(t == NULL)
			return 0;
		else
			return(Height(t->left)>Height(t->right)?(Height(t->left)+1):(Height(t->right)+1));
	}
	size_t sizeNode(BinTreeNode<T> *t)
	{
		if(t == NULL)
			return 0;
		else
			return (sizeNode(t->left)+sizeNode(t->right)+1);
	}
	void PostOrder(BinTreeNode<T>*t)
	{
		if(t != NULL)
		{
			PostOrder(t->left);
			PostOrder(t->right);
			cout<<t->data<<"--+";
		}

	}
	void InOrder(BinTreeNode<T> *t)
	{
		if(t!=NULL)
		{
			InOrder(t->left);
			cout<<t->data<<"-+-";
			InOrder(t->right);
		}
	}
	void PreOrder(BinTreeNode<T> *t)
	{
		if(t != NULL)
		{
			cout<<t->data<<"+--";
			PreOrder(t->left);
			PreOrder(t->right);
		}
	}
	void CreatBintree(BinTreeNode<T> *&t)
	{
		T input;
		cin>>input;
		if(input == flag)
		{
			t = NULL;
		}
		else
		{
			//BinTreeNode<T> *newnode = new BinTreeNode<T>;
			//newnode->data = t;
			t = new BinTreeNode<T>(input);
			CreatBintree(t->left);
			CreatBintree(t->right);
		}
	}
};
主函数:

#include"BinTree.h"
int main()
{
	BinTree<char> bt;
	BinTreeNode<char> *get;
	char *input = "ABC##DE##F##G#H##";
	int select = 1;
	while(select)
	{
		cout<<"======================List==================="<<endl;
		cout<<"[1]creatBinTree       [2]PreOrder_BinTree===="<<endl;
		cout<<"[3]InOrder_BinTree    [4]PostOrder_BinTree==="<<endl;
		cout<<"[5]search             [6]FindParent=========="<<endl;
		cout<<"[7]size               [8]height=============="<<endl;
		cout<<"[9]CreatBinTreebychar [10]preorder_un ======="<<endl;
		cout<<"[11]inorder_un        [12]postorder_un ======"<<endl;
		cout<<"[13]destory           [14]levelorder========="<<endl;
                cout<<"============================================="<<endl;
		cout<<"请选择:>";
		cin>>select;
		switch(select)
		{
		case 1:
			bt.CreatBintree();break;
		case 2:
			cout<<"前序遍历:";
			bt.PreOrder();
			cout<<endl;
			break;
		case 3:
			cout<<"中序遍历:";
			bt.InOrder();
			cout<<endl;
			break;
		case 4:
			cout<<"后序遍历:";
			bt.PostOrder();
			cout<<endl;
			break;
		case 5:
			char ch;
			cout<<"请输入您所要找的元素:>";
			cin>>ch;
			cout<<"所找的值得地址为:<"<<bt.search(ch)<<endl;
			break;
		case 6:
			char ch1;
			BinTreeNode<char> *parent;
			cout<<"请输入孩子的元素:>";
			cin>>ch1;
			cout<<"其父节点为:<";
			parent = bt.findParent(ch1);
			cout<<(*parent).getData()<<endl; 
			break;
		case 7:
			size_t size;
			size = bt.sizeNode();
			cout<<"节点个数为:"<<size<<endl;
			break;
		case 8:
			size_t height;
			height = bt.Height();
			cout<<"树的高度为:"<<height<<endl;
			break;
		case 9:
			bt.CreatBintree(input);
			break;
		case 10:
			cout<<"非递归前序遍历:";
			bt.preorder_un();
			cout<<endl;
			break;
		case 11:
			cout<<"非递归中序遍历:";
			bt.inorder_un();
			cout<<endl;
			break;
		case 12:
			cout<<"非递归后序遍历:";
			bt.postorder_un();
			cout<<endl;
			break;
		case 13://注意二叉树摧毁后无法再创建
			bt.destory();
			cout<<endl;
			break;
		case 14:
			cout<<"层次遍历:";
			bt.levelorder();
			cout<<endl;
			break;
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值