二叉树的创建和操作

一·二叉树定义及其5大性质:

	根+左右子树,每个节点最多只能有2个孩子节点。
	1)第i层上至多有2^(i-1)个节点。
	2)深度为k至多有2^k-1个节点。
	3)n0 = n2+1
		:n = n1+n2+n0,n = n1+2n2+1(根节点)
	4)节点为n个,深度为「log2 n」+1。
	5)***完全二叉树***:编号为i的节点,左孩子编号必为2i,右孩子编号必为2i+1,其双亲编号必为i/2(i=1时除外)。

二·二叉树的创建及其操作:

1.树的创建。
2.求树的深度
3.四种遍历(递归)
4.先序查找元素
5.统计叶子个数
6.3种遍历(非递归)“stack使用”
7.复制二叉树
————————————————————————————
1.树的创建:

//1顺序树(EZ)
/*
#include<iostream>
using namespace std;
#define MAXSIZE 100
typedef char TElemtype;
typedef TElemtype SqTree[MAXSIZE];
SqTree T;
*/

//2叉链表树:
#include<iostream>
#include<queue>
using namespace std;
#define MAXSIZE 100
typedef char TElemtype;
typedef int Status;

typedef struct TNode{
	TElemtype data;
	struct TNode * lc,* rc;//左右孩子
}TNode,*TP;

//创建一个树:(点创建)
void CreateTree(TP &T){
	TElemtype ch;
	cin>>ch;
	if(ch=='*')
		T=NULL;
	else{
		if(!(T = new TNode))//空间分配失败
			exit(-1);
		T->data = ch;//根创建完毕
		CreateTree(T->lc);//递归创建左子树
		CreateTree(T->rc);//右子树
	}
}

2.计算树的深度:(后序遍历的应用)

int TreeDepth(TP &T){
	if(T == NULL)
		return 0;
	else{
		int ld = TreeDepth(T->lc);
		int rd = TreeDepth(T->rc);
		return ld>rd ? ld+1 : rd+1; //取左右深度较大的,加上根深度1。如果是为叶子节点则d为1。
	}
}

3.四种递归遍历(已知一种序列,树形状不唯一;中序+另1种即可

//先序遍历(根左右)
void PreOrder(TP T){
	if(T!=NULL){
		cout<<T->data<<' ';
		PreOrder(T->lc);
		PreOrder(T->rc);
	}
}
//中序遍历(左根右)
void InOrder(TP T){
	if(T!=NULL){
		InOrder(T->lc);
		cout<<T->data<<' ';
		InOrder(T->rc);
	}
}
//后序遍历(左右根)
void PostOrder(TP T){
	if(T!=NULL){
		PostOrder(T->lc);
		PostOrder(T->rc);
		cout<<T->data<<' ';
	}
}
//层序遍历(使用系统队列)
void LineOrder(TP T)
{
	queue<TP> q;
	if(T)
		q.push(T);//先把根节点入队
	while(!q.empty())//队空退出循环
	{
		cout<<q.front()->data<<' ';//输出队首元素
		if(q.front()->lc)
			q.push(q.front()->lc);
		if(q.front()->rc)
			q.push(q.front()->rc);
	//队首元素的左右孩子,谁不空谁入队,这样就录入了一层数据。
		q.pop();//将使用过的队首元素删除
	}
}

//第a层序遍历:
void LevelOrder(TP T,int a){
	if(T == NULL || a<0)
		return ;
	//a什么时候为0,什么时候输出
	if(a == 0)
		cout<<T->data<<' ';
	LevelOrder(T->lc,a-1);
	LevelOrder(T->rc,a-1);
	return ;
}
/*
可搭配此main语句达成各层遍历
main()
{
	if(d==0)
		d++;
	for(int i=0;i<d;i++){
		LevelOrder(T,i)
	}
}
*/

4.先序查找元素(根左右):

Status PreFind(TP T,TElemtype e,TP &p){
	if(T){
		if(T->data == e){
			p = T;
			return 1;
		}
		else{
			if(PreFind(T->lc,e,p))
				return 1;
			else
				return(PreFind(T->rc,e,p));
		}
	}
	else return 0;
}

5.统计叶子节点个数:count在外部传入,初时设置为0

void CountLeaf(TP T,int &count){
	if(T){
		if((T->lc==NULL)&&(T->rc==NULL))
			count++;
		CountLeaf(T->lc,count);
		CountLeaf(T->rc,count);
	}
}
//int CountLeaf(TP T){
//	int m,n;
//	if(!T)
//		return 0;
//	if(!T->lc&&!T->rc)
//		return 1;
//	else{
//		m = CountLeaf(T->lc);
//		n = CountLeaf(T->rc);
//		return (m+n);
//	}
//}

6.非递归遍历:

typedef TP SElemtype;//栈存的是->以存根节点的指针
//非递归:需要栈的使用
typedef struct SqStack{
	SElemtype elem[MAXSIZE];
	int top;
}SqStack;
//初始化栈:
void InitStack(SqStack &S){
	S.top = 0;
}
//判断栈空:
Status StackEmpty(SqStack S){
	if(S.top == 0)
		return 1;
	else 
		return 0;
}
//取栈顶元素:
Status GetTop(SqStack &S,SElemtype &e){
	if(StackEmpty(S))
		return 0;
	e = S.elem[S.top];
	return 1;
}
//入栈:
Status Push(SqStack &S,SElemtype e){
	if(S.top == MAXSIZE-1)
		return -1;   //栈满
	else
	{
		S.top++;
		S.elem[S.top] = e;
		return 1;
	}
}
//出栈:
Status Pop(SqStack &S,SElemtype &e)
{
	if(StackEmpty(S))
		return 0;
	else
	{
		e = S.elem[S.top];
		S.top--;
		return 1;
	}
}
//先序非递归:
void PreOrder(TP T){
	SqStack S;
	InitStack(S);
	TP p = NULL;
	if(T!=NULL){
		Push(S,T); //根入栈
		while(!StackEmpty(S)){
			Pop(S,p);
			cout<<p->data<<' ';
			if(p->rc!=NULL)     //因为栈是先入后出,所以右孩子先入栈。
				Push(S,p->rc);
			if(p->lc!=NULL)
				Push(S,p->lc);
		}
	}
}
//中序非递归:
void InOrder(TP T){
	SqStack S;
	InitStack(S);
	TP p = T; 
	do{
		while(p!=NULL){ //疯狂入左孩子,直到没有左孩子。
			Push(S,p);
			p = p->lc;
		}
		if(!StackEmpty(S)){
			Pop(S,p);     //弹出子根,此时这个根没有左孩子
			cout<<p->data<<' ';
			p = p->rc;
		}
	}while(p!=NULL || !StackEmpty(S));//p为空 或者 栈为空就退出循环
}
//后续非递归:
void PostOrder(TP T){
	SqStack S;
	InitStack(S);
	int tag[MAXSIZE];
	TP p=T,temp = NULL;
	do{
		while(p!=NULL){ //扫描左节点入栈
			Push(S,p);
			tag[S.top]=0;
			p = p->lc;
		}
		if(!StackEmpty(S)){ //
			if(tag[S.top]==1){
				Pop(S,temp);
				cout<<temp->data<<' ';
			}
			else{
				GetTop(S,p);
				p = p->lc;  //扫描右节点
				tag[S.top] = 1;
			}
		}
	}while(p!=NULL || !StackEmpty(S));
}

7.复制二叉树—3步骤:
/*
1)为新的二叉树分配根节点。当结点分配失败返回NULL;当根为NULL时也返回NULL
2)先复制左子树(递归),在复制右子树(递归),最后赋值根节点。
3)返回该新建节点。
*/

void Copy(TP T,Tp &EXT){
	if(T==NULL)
		return;
	else{
		EXT = new TNode();
		
		EXT->data = T->data;
		EXT->lc = T->lc;
		EXT->cr = T->rc;
	
		Copy(T->lc,EXT->lc);
		Copy(T->rc,EXT->rc);
	}
}
posted @ 2019-12-07 16:50  LASER_06  阅读(81)  评论(0)    收藏  举报