二叉树的遍历的应用

17 篇文章 0 订阅
14 篇文章 0 订阅

 

//二叉树的定义
typedef struct  _BinaryTreeNode
{
	char data;
	//int ltag , rtag;
	struct _BinaryTreeNode *lchild;
	struct _BinaryTreeNode *rchild; 

}BTNode;
/*
1、表达式(a-(b+c)*(d/e))存储在存储在以二叉链表为存储结构的二叉树中,编写程序求出表达式中的值。
*/
int op(int A,int B ,char oper)
{
	switch (oper)
	{
	case '+':
		return A+B;
		break;
	case '-':
		return A-B;
		break;
	case '*':
		return A*B;
		break;
	case '/':
		return A/B;
		break;
	}


}
int comp(BTNode *p)
{
	int A,B;
	if (p!=NULL)
	{
		if (p->lchild!=NULL&&p->rchild!=NULL)
		{
			A = comp(p->lchild);
			B = comp(p->rchild);
			return op(A,B,p->data);
		}
		else
			return p->data -'0';
	}
	else
		return 0;
}

 

//写出一个算法求出二叉树的高度
int  getDepth(BTNode *p)
{
	int LD=0,RD=0;
	if (p ==NULL)
	{
		return 0;
	}
	else
	{
		LD = getDepth(p->lchild);
		RD = getDepth(p->rchild);
		return (LD>RD ? LD:RD)+1;
	}

}

 

 

//在以二叉链表为存储结构的链表中查询data域值等于key的节点。
//前序遍历就OK  可以用中序遍历么 
void Search_one(BTNode *p, BTNode *&q, char key)
{
	if (p!=NULL)
	{
		if (p->data==key)
		{
			q = p;
		}
		else
		{

			Search_one(p->lchild,q,key);
			Search_one(p->rchild,q,key);
		}
	}

}
//前序遍历就OK  可以用中序遍历么 
void Search_two(BTNode *p, BTNode *&q, char key)
{
	if (p!=NULL)
	{
		if (p->data==key)
		{
			q = p;
		}
		else
		{

			Search_two(p->lchild,q,key);
			if (q==NULL)
			{
				Search_two(p->rchild,q,key);
			}//只有在左子树中没有找到才在右子树中找
		}
	}

}

 

//求出二叉树的最大宽度:某一层节点个数最多的那一层
int BinaryTreeWidth(BTNode *root)
{
	//核心思想: 第一次入队根节点,这个时候的宽度为1 当根节点出队,其子节点入队之后,这个队列的大小就是这一层的宽度 以此类推。
	if (root ==NULL)
	{
		return 0;
	}
	int  width = 0;
	int  maxwidth =0;
	queue<BTNode*> q;
	BTNode *p = NULL;
	q.push(root);
	while(!q.empty())
	{
		width = q.size();//本层元素的个数
		if (maxwidth<width)
		{
			maxwidth = width;
		}
		//将该层元素的孩子入栈
		for (int i = 0;i<width;i++)
		{
			p = q.front();
			q.pop();
			if (p->lchild!=NULL)
			{
				q.push(p->lchild);
			}
			if (p->lchild!=NULL)
			{
				q.push(p->rchild);
			}
		}

	}
	return maxwidth;
//求二叉树的深度的非递归算法
/*
其实知道了树的深度的非递归算法,很容易知道树的深度 因为树的宽度的外层循环每进行一次,树的深度就增加1
*/
int BinaryTreeDepth(BTNode *root)
{
	//核心思想: 第一次入队根节点,这个时候的宽度为1 当根节点出队,其子节点入队之后,这个队列的大小就是这一层的宽度 以此类推。
	if (root ==NULL)
	{
		return 0;
	}
	int  width = 0 ;
	int  dept = 0 ;
	queue<BTNode*> q;
	BTNode *p = NULL;
	q.push(root);
	
	while(!q.empty())
	{
		width = q.size();//本层元素的个数
		dept++;
		//将该层元素的孩子入栈
		for (int i = 0;i<width;i++)
		{
			p = q.front();
			q.pop();
			if (p->lchild!=NULL)
			{
				q.push(p->lchild);
			}
			if (p->lchild!=NULL)
			{
				q.push(p->rchild);
			}
		}

	}
	return dept;
}

 

//中序和后续确定一颗树 --后续确定根的位置,中序把树分为两个部分
BTNode *BTConstruct23(char *inorder,char *postorder,int inStart,int inEnd,int postStart,int postEnd)
{
	//建立新的节点
	BTNode *tree = new BTNode;
	tree->data =postorder[postEnd];//后序遍历的最后一个节点一定是根节点
	tree->lchild =NULL;//前序遍历的第一个节点将中序遍历的节点分为左右子树
	tree->rchild =NULL;

	if (inStart==inEnd&&postStart==postEnd)
	{
		return tree;
	}
	int root =0;
	//在中序遍历中查找该值
	for ( root = inStart;root<inEnd;root++)
	{
		if (inorder[root]==postorder[postEnd])
			break;
	}
	//划分左子树
	int leftTreeLength = root - inStart;
	//cout<<leftTreeLength<<endl;
	int rightTreeLength = inEnd - root;
	//cout<<rightTreeLength<<endl;
	
	if (leftTreeLength>0)
	{
		//注意中序和后续保持元素个数相等即为正确的 leftTreeLength-1
		tree->lchild = BTConstruct23(inorder,postorder,inStart,root-1,postStart,postStart+leftTreeLength-1);
		
	}
	if (rightTreeLength>0)
	{
		tree->rchild = BTConstruct23(inorder,postorder,root+1,inEnd,postStart+leftTreeLength,postEnd-1);
	}
	return tree;
}
BTNode *BTConstruct12(char *preorder,char *inorder,int preStart,int preEnd,int inStart,int inEnd)
{
	//建立新的节点
	BTNode *tree = new BTNode;
	tree->data =preorder[preStart];//前序遍历的第一个节点一定是根节点
	tree->lchild =NULL;//前序遍历的第一个节点将中序遍历的节点分为左右子树
	tree->rchild =NULL;

	if (preStart==preEnd&&inStart==inEnd)
	{
		return tree;
	}
	int root =0;
	//在中序遍历中查找该值
	for ( root = inStart;root<=inEnd;root++)
	{
		if (inorder[root]==preorder[preStart])
			break;
	}
	//划分左子树
	int leftTreeLength = root - inStart;
	int rightTreeLength = inEnd - root;
	if (leftTreeLength>0)
	{
		tree->lchild = BTConstruct12(preorder,inorder,preStart+1,preStart+leftTreeLength,inStart,root-1);
	}
	if (rightTreeLength>0)
	{
		tree->rchild = BTConstruct12(preorder,inorder,preStart+1+leftTreeLength,preEnd,root+1,inEnd);
	}
	return tree;
}
//根据二叉树的前序和中序遍历确定一颗二叉树
BTNode * RecoveryBinaryTreeBy12(char* preorder ,int lenpre,char *inorder,int lenin)
{
	if (lenpre==0&& lenin==0)
	{
		return NULL;
	}
	return BTConstruct12(preorder,inorder,0,lenpre-1,0,lenin-1);
}

//去取出先序遍历的第k的点
int n =0;
void pretrave(BTNode*p ,int key)
{
	if (p!=NULL)
	{
		n++;
		if (key==n)
		{
			cout<<p->data<<endl;
			return;
		}
		pretrave(p->lchild,key);
		pretrave(p->rchild,key);
	}
	//cout<<"不存在"<<endl;
}
#include<iostream>
#include<vector>
#include<string.h>
#include<algorithm>
#include<map>
#include<stack>
#include <queue>
#define MAX_Size 100;
using namespace std;
//
//  BinaryTreeNode.h
//  BinaryTreeNode
//
//  Created by 吴珝君 on 2018/12/25.
//  Copyright  ©   2018年 闲着也是贤者. All rights reserved.
//

typedef struct  _BinaryTreeNode
{
	char data;
	//int ltag , rtag;
	struct _BinaryTreeNode *lchild;
	struct _BinaryTreeNode *rchild; 

}BTNode;

/*
1、表达式(a-(b+c)*(d/e))存储在存储在以二叉链表为存储结构的二叉树中,编写程序求出表达式中的值。
*/
int op(int A,int B ,char oper)
{
	switch (oper)
	{
	case '+':
		return A+B;
		break;
	case '-':
		return A-B;
		break;
	case '*':
		return A*B;
		break;
	case '/':
		return A/B;
		break;
	}


}
int comp(BTNode *p)
{
	int A,B;
	if (p!=NULL)
	{
		if (p->lchild!=NULL&&p->rchild!=NULL)
		{
			A = comp(p->lchild);
			B = comp(p->rchild);
			return op(A,B,p->data);
		}
		else
			return p->data -'0';
	}
	else
		return 0;
}
//写出一个算法求出二叉树的高度
int  getDepth(BTNode *p)
{
	int LD=0,RD=0;
	if (p ==NULL)
	{
		return 0;
	}
	else
	{
		LD = getDepth(p->lchild);
		RD = getDepth(p->rchild);
		return (LD>RD ? LD:RD)+1;
	}

}
//在以二叉链表为存储结构的链表中查询data域值等于key的节点。
//前序遍历就OK  可以用中序遍历么 
void Search_one(BTNode *p, BTNode *&q, char key)
{
	if (p!=NULL)
	{
		if (p->data==key)
		{
			q = p;
		}
		else
		{

			Search_one(p->lchild,q,key);
			Search_one(p->rchild,q,key);
		}
	}

}
//前序遍历就OK  可以用中序遍历么 
void Search_two(BTNode *p, BTNode *&q, char key)
{
	if (p!=NULL)
	{
		if (p->data==key)
		{
			q = p;
		}
		else
		{

			Search_two(p->lchild,q,key);
			if (q==NULL)
			{
				Search_two(p->rchild,q,key);
			}//只有在左子树中没有找到才在右子树中找
		}
	}

}
//求出二叉树的最大宽度:某一层节点个数最多的那一层
int BinaryTreeWidth(BTNode *root)
{
	//核心思想: 第一次入队根节点,这个时候的宽度为1 当根节点出队,其子节点入队之后,这个队列的大小就是这一层的宽度 以此类推。
	if (root ==NULL)
	{
		return 0;
	}
	int  width = 0;
	int  maxwidth =0;
	queue<BTNode*> q;
	BTNode *p = NULL;
	q.push(root);
	while(!q.empty())
	{
		width = q.size();//本层元素的个数
		if (maxwidth<width)
		{
			maxwidth = width;
		}
		//将该层元素的孩子入栈
		for (int i = 0;i<width;i++)
		{
			p = q.front();
			q.pop();
			if (p->lchild!=NULL)
			{
				q.push(p->lchild);
			}
			if (p->lchild!=NULL)
			{
				q.push(p->rchild);
			}
		}

	}
	return maxwidth;
}
//求二叉树的深度的非递归算法
/*
其实知道了树的深度的非递归算法,很容易知道树的深度 因为树的宽度的外层循环每进行一次,树的深度就增加1
*/
int BinaryTreeDepth(BTNode *root)
{
	//核心思想: 第一次入队根节点,这个时候的宽度为1 当根节点出队,其子节点入队之后,这个队列的大小就是这一层的宽度 以此类推。
	if (root ==NULL)
	{
		return 0;
	}
	int  width = 0 ;
	int  dept = 0 ;
	queue<BTNode*> q;
	BTNode *p = NULL;
	q.push(root);
	
	while(!q.empty())
	{
		width = q.size();//本层元素的个数
		dept++;
		//将该层元素的孩子入栈
		for (int i = 0;i<width;i++)
		{
			p = q.front();
			q.pop();
			if (p->lchild!=NULL)
			{
				q.push(p->lchild);
			}
			if (p->lchild!=NULL)
			{
				q.push(p->rchild);
			}
		}

	}
	return dept;
}
int m =0;

//中序和后续确定一颗树 --后续确定根的位置,中序把树分为两个部分
BTNode *BTConstruct23(char *inorder,char *postorder,int inStart,int inEnd,int postStart,int postEnd)
{
	//建立新的节点
	BTNode *tree = new BTNode;
	tree->data =postorder[postEnd];//后序遍历的最后一个节点一定是根节点
	tree->lchild =NULL;//前序遍历的第一个节点将中序遍历的节点分为左右子树
	tree->rchild =NULL;

	if (inStart==inEnd&&postStart==postEnd)
	{
		return tree;
	}
	int root =0;
	//在中序遍历中查找该值
	for ( root = inStart;root<inEnd;root++)
	{
		if (inorder[root]==postorder[postEnd])
			break;
	}
	//划分左子树
	int leftTreeLength = root - inStart;
	//cout<<leftTreeLength<<endl;
	int rightTreeLength = inEnd - root;
	//cout<<rightTreeLength<<endl;
	
	if (leftTreeLength>0)
	{
		//注意中序和后续保持元素个数相等即为正确的 leftTreeLength-1
		tree->lchild = BTConstruct23(inorder,postorder,inStart,root-1,postStart,postStart+leftTreeLength-1);
		
	}
	if (rightTreeLength>0)
	{
		tree->rchild = BTConstruct23(inorder,postorder,root+1,inEnd,postStart+leftTreeLength,postEnd-1);
	}
	return tree;
}
//根据二叉树的前序和中序遍历确定一颗二叉树
BTNode * RecoveryBinaryTreeBy23(char* inorder ,int lenin,char *postorder,int lenpost)
{
	if (lenin==0&& lenpost==0)
	{
		return NULL;
	}
	return BTConstruct23(inorder,postorder,0,lenin-1,0,lenpost-1);
}
void PostOrder(BTNode *root)
{
	if (root ==NULL)
	{
		return ;
	}
	PostOrder(root->lchild);
	PostOrder(root->rchild);
	cout<<root->data<<endl;
}

BTNode *BTConstruct12(char *preorder,char *inorder,int preStart,int preEnd,int inStart,int inEnd)
{
	//建立新的节点
	BTNode *tree = new BTNode;
	tree->data =preorder[preStart];//前序遍历的第一个节点一定是根节点
	tree->lchild =NULL;//前序遍历的第一个节点将中序遍历的节点分为左右子树
	tree->rchild =NULL;

	if (preStart==preEnd&&inStart==inEnd)
	{
		return tree;
	}
	int root =0;
	//在中序遍历中查找该值
	for ( root = inStart;root<=inEnd;root++)
	{
		if (inorder[root]==preorder[preStart])
			break;
	}
	//划分左子树
	int leftTreeLength = root - inStart;
	int rightTreeLength = inEnd - root;
	if (leftTreeLength>0)
	{
		tree->lchild = BTConstruct12(preorder,inorder,preStart+1,preStart+leftTreeLength,inStart,root-1);
	}
	if (rightTreeLength>0)
	{
		tree->rchild = BTConstruct12(preorder,inorder,preStart+1+leftTreeLength,preEnd,root+1,inEnd);
	}
	return tree;
}
//根据二叉树的前序和中序遍历确定一颗二叉树
BTNode * RecoveryBinaryTreeBy12(char* preorder ,int lenpre,char *inorder,int lenin)
{
	if (lenpre==0&& lenin==0)
	{
		return NULL;
	}
	return BTConstruct12(preorder,inorder,0,lenpre-1,0,lenin-1);
}

//去取出先序遍历的第k的点
int n =0;
void pretrave(BTNode*p ,int key)
{
	if (p!=NULL)
	{
		n++;
		if (key==n)
		{
			cout<<p->data<<endl;
			return;
		}
		pretrave(p->lchild,key);
		pretrave(p->rchild,key);
	}
	//cout<<"不存在"<<endl;
}

int main()
{
	/*
	测试程序
	*/

	//is2operator(v,vv,ms);
	BTNode b1,b2,b3,b4,b5,b6,b7,b8,b9;
	b1.data ='*';

	b2.data ='-';

	b3.data ='/';
	b3.lchild =NULL;
	b3.rchild =NULL;

	b4.data ='a';
	b4.lchild =NULL;
	b4.rchild =NULL;
	b5.data ='+';
	b5.lchild =NULL;
	b5.rchild =NULL;
	b5.data ='+';
	b5.lchild =NULL;
	b5.rchild =NULL;
	b6.data ='d';
	b6.lchild =NULL;
	b6.rchild =NULL;
	b7.data ='e';
	b7.lchild =NULL;
	b7.rchild =NULL;
	b8.data ='b';
	b8.lchild =NULL;
	b8.rchild =NULL;

	b9.data ='c';
	b9.lchild =NULL;
	b9.rchild =NULL;

	b1.lchild = &b2;
	b1.rchild =&b3;

	b2.lchild =&b4;
	b2.rchild =&b5;
	b3.lchild =&b6;
	b3.rchild = &b7;
	b5.lchild = &b8;
	b5.rchild =&b9;
	char preorder[9] ={'*','-','a','+','b','c','/','d','e'};
	char inorder[9] ={'a','-','b','+','c','*','d','/','e'};
	char postorder[9] ={'a','b','c','+','-','d','e','/','*'};
	//BTNode * r1= RecoveryBinaryTreeBy12(preorder,9,inorder,9);
	//PostOrder(r1);
	BTNode * r2= RecoveryBinaryTreeBy23(inorder,9,postorder,9);
	PostOrder(r2);
	system("pause");
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值