二叉树的基本操作



创建一棵二叉树,分别实现先序、中序和后序遍历一棵二叉树,计算二叉树结点个数等操作等。

头文件:BTree.h

#include<iostream.h>
#include<math.h>

int couter=0;//全局变量,用于存储二叉树的叶子总数

//二叉树链结点类:
class BTreeNode
{
	friend class BTree;
	friend class Queue;
	int data;
	BTreeNode *lchild,*rchild;
public:
	BTreeNode():lchild(NULL),rchild(NULL){};
	BTreeNode(int d,BTreeNode *l=NULL,BTreeNode *r=NULL):data(d),lchild(l),rchild(r){};
	int getdata(){return data;};
	BTreeNode *getleft(){return lchild;};
	BTreeNode *getright(){return rchild;};
};

//队列类(为层次遍历而定义的):
class Queue
{
protected:
	friend class BTree;
	int front,rear,count;
	BTreeNode *elem[100];
	int maxsz;//队列
public:
	Queue(int n){maxsz=n;front=rear=count=0;};//队列构造函数
	bool Enqueue(BTreeNode *p);               //结点入列
	BTreeNode *Dequeue();                     //结点出列
	bool IsEmpty(){return count==0;};         //判断队列是否为空
};

bool Queue::Enqueue(BTreeNode *p)
{
	if(!(count>=100))
	{
		elem[rear]=p;
		rear=(rear+1)%maxsz;
		count++;
		return true;
	}
	else return false;
}

BTreeNode *Queue::Dequeue()
{
	BTreeNode *el;
	if(!IsEmpty())
	{
		el=elem[front];
		front=(front+1)%maxsz;
		count--;
		return el;
	}
	else return NULL;
}
//单链表结点类:
class Node
{
	friend class List;
	int Ndata;
	Node *next;
public:
	Node(int d=0,Node *n=NULL):Ndata(d),next(n){};
	void setnext(Node *p){next=p;};
};

//单链表类:
class List
{
private:
	friend class BTree;
	Node *head,*tail;
	int size;
public:
	List(){head=new Node();size=0;};//构造函数

	List(int a[],int n)//构造函数,建链表
	{
		Node *p;head=new Node(0,NULL);
		for(int i=n-1;i>=0;i--)
		{
			p=new Node(a[i],head->next);
			head->setnext(p);
		}
		size=n;};

	~List(){delete []head;};//析构函数

	int get(int i)//取元素值
	{
		Node *p=head;int j=0;
		while(p!=NULL&&j<i)
		{
			p=p->next;j=j+1;
		}
		if(p!=NULL&&j==i)return p->Ndata;
		else return NULL;
	};

	void print()//打印各元素值
	{
		cout<<"\n    单链表的各叶子结点值为:\n\t";
		for(int i=1;i<=size;i++)
			cout<<get(i)<<"   ";
	};
};


//二叉树类:
class BTree
{
	int *a;int n;
	BTreeNode *build0(int i);//递归创建二叉链表
protected:
	BTreeNode *root;         //二叉树的根结点
public:
	BTree(BTreeNode *p=NULL){copybt(root,p);};
	BTree(int a[],int n){this->a=a;this->n=n;root=build0(1);};
	void build(int a[],int n){this->a=a;this->n=n;root=build0(1);};             //相当于构造函数,用于二叉树初始化

	int num(){return num(root);};                                               //求结点个数
	static int num(BTreeNode *p){if(p==NULL)return 0;else return num(p->lchild)+num(p->rchild)+1;};

	int dep(){return dep(root);};                                               //求二叉树的高度(深度)
	static int dep(BTreeNode *p);

	bool equal(BTree& bt){if(equal(root,bt.root)==true)return 1;else return 0;};//判断两棵二叉树是否相等
	static bool equal(BTreeNode *p,BTreeNode *q);

	void dest(BTreeNode *p);                                                    //释放存储空间                                                 
	void copybt(BTree &bt){dest(root);copybt(root,bt.root);};                   //复制一棵二叉树
	static void copybt(BTreeNode *&p,BTreeNode *q);

	void preorder(void visit(BTreeNode *p)){preorder(root,visit);cout<<endl;};  //前序遍历(递归)
	static void preorder(BTreeNode *p,void visit(BTreeNode *p));
	void preorder1(void visit(BTreeNode *p));                                   //前序遍历(非递归)

	void inorder(void visit(BTreeNode *p)){inorder(root,visit);cout<<endl;};    //中序遍历(递归)
	static void inorder(BTreeNode *p,void visit(BTreeNode *p));
	void inorder1(void visit(BTreeNode *p));                                    //中序遍历(非递归)

	void postorder(void visit(BTreeNode *p)){postorder(root,visit);cout<<endl;};//后序遍历(递归)
	static void postorder(BTreeNode *p,void visit(BTreeNode *p));
	void postorder1(void visit(BTreeNode *p));                                  //后序遍历(非递归)

	void layerorder();                                                          //层次遍历

	void exchange(BTreeNode *t); //交换左右子树
	void exchange(){BTree::exchange(root);};

	void BTreeL();

	void print(){print(root,1);};//输出二叉树
	void print(BTreeNode *p,int l);

	void leaves(BTreeNode *t);   //求叶子总数
	void leaves(){BTree::leaves(root);};
};

BTreeNode *BTree::build0(int i)
{
	BTreeNode *p;int l,r;
	if((i<=n)&&(a[i-1]!=' '))
	{
		p=new BTreeNode;p->data=a[i-1];
		l=2*i;r=2*i+1;
		p->lchild=build0(l);
		p->rchild=build0(r);
		return p;
	}
	else return NULL;
};

int BTree::dep(BTreeNode *p)
{
	int max;
	if(p==NULL)return 0;
	else
	{
		max=dep(p->lchild);
		if(dep(p->rchild)>max)max=dep(p->rchild);
		return max+1;//加上根结点
	}
};

bool BTree::equal(BTreeNode *p,BTreeNode *q)
{
	bool b;
	if(p==NULL&&q==NULL)b=true;
	else if(p==NULL||q==NULL)b=false;
	else b=(p->data==q->data)&&equal(p->lchild,q->lchild)&&equal(p->rchild,q->rchild);
	return b;
};

void BTree::dest(BTreeNode *p)
{
	if(p!=NULL)
	{
		dest(p->lchild);
		dest(p->rchild);
		delete p;
	}
};

void BTree::copybt(BTreeNode *&p,BTreeNode *q)
{
	if(q==NULL)p=NULL;//复制一棵空树
	else
	{
		p=new BTreeNode;
		p->data=q->data;
		copybt(p->lchild,q->lchild);
		copybt(p->rchild,q->rchild);
	}
};

void BTree::preorder(BTreeNode *p,void visit(BTreeNode *p))
{
	if(p!=NULL)
	{
		visit(p);//访问结点,并输出结点数据
		preorder(p->lchild,visit);
		preorder(p->rchild,visit);
	}
};

void BTree::preorder1(void visit(BTreeNode *p))
{
	BTreeNode *stack[100],*p;
	int top=0;
	stack[top]=root;
	while(top>=0)
	{
		while(stack[top]!=NULL)
		{
			visit(stack[top]);
			p=stack[top]->lchild;
			stack[++top]=p;
		}
		top--;
		if(top>=0)
		{
			p=stack[top];
			stack[top]=p->rchild;
		}
	}
	cout<<endl;
};

void BTree::inorder(BTreeNode *p,void visit(BTreeNode *p))
{
	if(p!=NULL)
	{
		inorder(p->lchild,visit);
		visit(p);
		inorder(p->rchild,visit);
	}
};

void BTree::inorder1(void visit(BTreeNode *p))
{
	BTreeNode *stack[100],*p;
	int top=0;
	stack[top]=root;
	while(top>=0)
	{
		while(stack[top]!=NULL)
		{
			p=stack[top]->lchild;
		    stack[++top]=p;
		}
		top--;
	    if(top>=0)
		{
			p=stack[top];
			visit(p);
		    stack[top]=p->rchild;
		}
	}
	cout<<endl;
};

void BTree::postorder(BTreeNode *p,void visit(BTreeNode *p))
{
	if(p!=NULL)
	{
		postorder(p->lchild,visit);
		postorder(p->rchild,visit);
		visit(p);
	}
};

void BTree::postorder1(void visit(BTreeNode *p))
{
///*
//第一种方式:
	struct stacknode//用结构类型定义栈元素类型
	{
		BTreeNode *d;
		int flag;   //定义标志变量
	};
	BTreeNode *p=root;
	stacknode *stack;
	stack=new stacknode[num()];
	int top=0;
	while(p!=NULL||top!=0)
	{
		if(p!=NULL)
		{
			stack[++top].d=p;   //结点进栈
			stack[top].flag=1;  //奇次访问,标志值为1
			p=p->lchild;
		}
		else if(stack[top].flag)//判断栈顶的标志是否为1,若是,则标志出栈
		{
			stack[top].flag=0;  //偶次访问,标志值为0
			p=stack[top].d->rchild;
		}
		else
		{
			visit(stack[top--].d);//p=stack[top].d;cout<<"    "<<p->data;top--;
			p=NULL;
		}
	}
	delete []stack;//释放空间
	cout<<endl;
//*/
//第二种方式:
/*
	BTreeNode *stack[100];//定义栈,存储结点
	int top=0,flag[100];//定义标志数组flag
	stack[top]=root;
	flag[top]=0;
	do
	{
		while(stack[top]!=NULL)
		{
			stack[++top]=stack[top]->lchild;
			flag[top]=0;//第一次访问,标志置为0
		}
		while(flag[top-1]==1)visit(stack[--top]);//cout<<"    "<<stack[--top]->data;

		if(top>0)       //栈不为空
		{
			stack[top]=stack[top-1]->rchild;
			flag[top]=0;  //栈顶标志值为0(也可当做是第一次访问)
			flag[top-1]=1;//第二次访问,标志置为1
		}
	}while(top!=0);
	cout<<endl;
/*/
};

void BTree::layerorder()
{
	Queue q(num());
	BTreeNode *t=root;
	if(t!=NULL)q.Enqueue(t); //结点入列
	cout<<"\t";
	while(!q.IsEmpty())
	{
		t=q.Dequeue();       //结点出列
		cout<<t->data<<"   ";//输出该结点的数据
		if(t->lchild!=NULL)q.Enqueue(t->lchild);//若左孩子非空,则左孩子入列
		if(t->rchild!=NULL)q.Enqueue(t->rchild);//若右孩子非空,则右孩子入列
	}
}

void BTree::exchange(BTreeNode *t)
{
	BTreeNode *x;
	if(t!=NULL)
	{
		x=t->lchild;t->lchild=t->rchild;t->rchild=x;//交换左右子树的结点
		exchange(t->lchild);
		exchange(t->rchild);
	}
};

void BTree::BTreeL()
{
	BTreeNode *stack[100],*p;
	int top=0,i=0;
	stack[top]=root;
	while(top>=0)
	{
		while(stack[top]!=NULL)
		{
			p=stack[top]->lchild;
		    stack[++top]=p;
		}
		top--;
	    if(top>=0)
		{
			p=stack[top];
			if(p->lchild==NULL&&p->rchild==NULL)a[i++]=p->data;
		    stack[top]=p->rchild;
		}
	}
	List L(a,i);
	L.print();
	cout<<endl;
};

void BTree::print(BTreeNode *p,int l)
{
	if(p!=NULL)
	{
		print(p->rchild,l+1);
		for(int i=0;i<6*(l-1);i++)cout<<" ";
		cout<<"..."<<p->data<<endl;
		print(p->lchild,l+1);
	}
	else if(num()==0)
		cout<<"\t\t空树!\n";
};

void BTree::leaves(BTreeNode *t)
{
	if(t!=NULL)
	{
		if(t->lchild==NULL&&t->rchild==NULL)couter++;
	    leaves(t->lchild);
	    leaves(t->rchild);
	}
};

void f(BTreeNode *p)//visit()函数输出
{
	cout<<"   "<<p->getdata();
};


void func(int a[],int n)
{
	cout<<"输入二叉树的各个元素值:\n";
	for(int i=0;i<n;i++)
		cin>>a[i];
};

main函数:

#include "BTree.h"
void main()
{
	int a[]={0,1,2,3,4,5,6,7,8,9};
	BTree bt(a,10);//程序自动初始化
	BTree bt1;     //定义一个新对象,用于建立一棵新的二叉树,进行复制、比较等
	int chioce,finial=1;
	cout<<"\n****************** 菜单 *************************\n";
	cout<<"\n\t 1--建立一棵二叉树\n\t 2--前序遍历递归算法\n\t 3--前序遍历非递归算法\n\t 4--中序遍历递归算法\n\t 5--中序遍历非递归算法\n"
		<<"\t 6--后序遍历递归算法\n\t 7--后序遍历非递归算法\n\t 8--层次遍历算法\n\t 9--求树高\n\t10--求叶子总数\n"
		<<"\t11--交换左右子树\n\t12--复制一棵二叉树\n\t13--判断两棵二叉树是否相等\n\t14--输出二叉树\n\t15--二叉树叶子结点→单链表<左→右>\n\t16--退出\n";
	while(finial!=0)
	{		
	    cout<<"\n请选择<1~16>:";
		cin>>chioce;
		while(chioce>16||chioce<1){cout<<"\n对不起,您的选择不正确!请重新选择<1~15>:";cin>>chioce;}
		switch(chioce)
		{
			case 1:
				int b[100],n;
				cout<<"\n输入二叉树的元素个数(<=100):";cin>>n;
				func(b,n);//调用函数进行初始化
				bt.build(b,n);break;

			case 2:cout<<"\n前序遍历(递归):\n";bt.preorder(f);break;

			case 3:cout<<"\n前序遍历(非递归):\n";bt.preorder1(f);break;

			case 4:cout<<"\n中序遍历(递归):\n";bt.inorder(f);break;

			case 5:cout<<"\n中序遍历(非递归):\n";bt.inorder1(f);break;

			case 6:cout<<"\n后序遍历(递归):\n";bt.postorder(f);break;

			case 7:cout<<"\n后序遍历(非递归):\n";bt.postorder1(f);break;

			case 8:cout<<"\n层次遍历:\n";bt.layerorder();break;

			case 9:cout<<"\n\t该二叉树的树高为:"<<bt.dep()<<endl;break;

			case 10:
				bt.leaves();
				cout<<"\n\t该二叉树的叶子总数为:"<<couter<<endl;
				couter=0;break;//初始化
			
			case 11:bt.exchange();cout<<"\n\t已成功交换该二叉树的左右子树!\n";break;

			case 12:
				bt1.copybt(bt);
				cout<<"\n\t已复制成功!\n  该二叉树是:\n";
				bt1.print();break;

			case 13:
				cout<<"\n  因为这两棵二叉树分别是:\n\n\t第一棵:\n";bt.print();
				cout<<"\n\t第二棵:\n";bt1.print();
				if(bt.equal(bt1)==1)
					cout<<"\n  所以:\n\t这两棵二叉树是相等的!\n";
				else 
					cout<<"\n  所以:\n\t这两棵二叉树是不相等的!\n";break;

			case 14:cout<<"\n该二叉树是:\n";bt.print();break;

			case 15:bt.BTreeL();break;
			
			case 16:finial=0;cout<<"\n\t退出程序!谢谢您的使用!\n\n";break;
		}
	}
}

截图:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值