码迷,mamicode.com
首页 > 其他好文 > 详细

二叉树相关

时间:2014-10-01 23:17:31      阅读:357      评论:0      收藏:0      [点我收藏+]

标签:blog   io   os   sp   div   问题   c   on   log   

 

/*
	_递归的精髓在二叉树的各种问题上体现的淋漓尽致!!!
*/


#include<stdio.h>
#include<iostream>
#include <stack>
#include<vector>
#include <assert.h>
using namespace std;

typedef struct node				//二叉树结点的结构体表示形式
{
	int data;
	node *left,*right;
}BTree;

//---------------------------------_创建二叉树(前序方式)---------------------------
BTree *Create()
{
	int data;
	scanf("%d",&data);
	if(data==0)	return 0;		//_输入0表示没有子节点
	BTree *root=new BTree;
	root->data=data;
	root->left=Create();
	root->right=Create();
	return root;
}
BTree *Create2(int *x,int N)
{
	static int i=-1;
	i++;
	if(x[i]==0)	return 0;
	BTree *tmp=new BTree;
	tmp->data=x[i];
	tmp->left=Create2(x,N);
	tmp->right=Create2(x,N);
	return tmp;
}
//-------------_遍历二叉树(前序方式)-------------
void Preorder(BTree *tree)
{
	if(tree==0)	return;
	printf("%d  ",tree->data);
	Preorder(tree->left);
	Preorder(tree->right);
}
void Preorder2(BTree *tree)		//堆栈方式
{
	if(tree==0)	return;
	stack <BTree*> s;
	s.push(tree);
	BTree *temp=0;
	while(!s.empty())
	{
		temp=s.top();
		printf("%d ",temp->data);
		s.pop();
		if(temp->right)	s.push(temp->right);
		if(temp->left)	s.push(temp->left);
	}
}
//-------------_遍历二叉树(中序方式)-------------
void Inorder(BTree *tree)
{
	if(tree==0)	return;
	Inorder(tree->left);
	printf("%d  ",tree->data);
	Inorder(tree->right);
}
void Inorder2(BTree *tree)
{
	if(tree==0)	return;
	stack<BTree *> s;
	BTree *temp=0;
	s.push(tree);
	while(!s.empty())
	{
		temp=s.top();s.pop();		//_弹出节点
		while(temp)					//_至最左端
		{
			s.push(temp);
			temp=temp->left;
		}
		if(!s.empty())
		{
			temp=s.top();s.pop();		//_取出最左端节点
			printf("%d ",temp->data);
			s.push(temp->right);		//_存入最左端节点的右兄弟,必须要压入右边的,无论有无节点
		}

	}

}
//-------------_遍历二叉树(后序方式)-------------
void Posorder(BTree *tree)
{
	if(tree==0)	{return;}
	Posorder(tree->left);
	Posorder(tree->right);
	printf("%d  ",tree->data);
}
void Posorder2(BTree *tree)
{
	if(!tree)	return;
	stack<BTree *> s;
	BTree *temp=0,*lastvisit=0;
	s.push(tree);

	while(!s.empty())
	{
		temp=s.top();
		s.pop();
		while(temp)
		{
			s.push(temp);
			temp=temp->left;
		}

		temp=s.top();
		if(temp->right&&(temp->right!=lastvisit))
		{
			s.push(temp->right);
		}
		else
		{
			lastvisit=temp;
			printf("%d ",lastvisit->data);
			s.pop();
		}
	}

}

//-------------------------------------_二叉树的镜像--------------------------------
void GetImage(BTree *tree)					//_求二叉树镜像
{
	if(tree==0)	return;
	GetImage(tree->left);
	GetImage(tree->right);
	//互换left_和right
	BTree *tmp=tree->left;tree->left =tree->right;tree->right=tmp;
}
bool IsImage(BTree *tree1,BTree *tree2)		//_判断二叉树是否是镜像的
{
	if(tree1==0&&tree2==0)	return true;
	if(!tree1||!tree2)		return false;

	if(tree1->data!=tree2->data)	return false;

	bool same1=IsImage(tree1->left,tree2->right);
	bool same2=IsImage(tree1->right,tree2->left);
	return same1&&same2;
}
//--------------------------------------_与路径相关的问题---------------------------
BTree * findnode(BTree *tree ,int key)												//_寻找key为某个值的节点,没找到返回0
{
	if(!tree)	return 0;
	if(tree->data==key)	return tree;

	BTree *tmp=findnode(tree->left,key);
	if(tmp)	return tmp;

	tmp=findnode(tree->right,key);
	if(tmp)	return tmp;

	return 0;
}
bool findnode1(BTree *tree,int key,BTree *&node)									//_这种写法更简洁明白
{
	if(!tree)	return false;
	if(tree->data==key)
	{
		node=tree;return true;
	}
	return findnode1(tree->left,key,node)||findnode1(tree->right,key,node);
}

bool findpath(BTree *tree,BTree *p,stack<BTree*> &st)								//_从根节点到某一节点的路径
{
	if(!tree||!p)	return 0;
	if(tree==p)
	{
		st.push(tree);
		return 1;
	}
	if(findpath(tree->left,p,st)||findpath(tree->right,p,st))
	{	//_以tree为根的左右子树中包含想要的节点,则根节点必在路径上
		st.push(tree);
		return 1;
	}
	else
		return 0;
}

void findsumpath(BTree *tree,int expectedSum,int &currentSum,vector<BTree *> &v)	//_输出和为某一值的路径
{
	if(!tree)	return;
	v.push_back(tree);
	currentSum+=tree->data;
	if(expectedSum==currentSum)
	{  //_打印输出
		vector<BTree *>::iterator it=v.begin();
		while(it!=v.end())	{ cout<<(*it)->data<<‘ ‘;it++;}
		cout<<endl;
	}
	if(tree->left)
		findsumpath(tree->left,expectedSum,currentSum,v);
	if(tree->right)
		findsumpath(tree->right,expectedSum,currentSum,v);

	//_每一次返回到父节点时,删除当前节点
	currentSum-=v.back()->data;
	v.pop_back();
}

BTree *LowestCommonAncestor(BTree *tree,BTree *A,BTree *B)					//_最近公共父节点
{/*很简单:对于节点i,如果A和B分别在该节点的左右子树中,该节点就是了,
	或者这个节点就是已知的两个节点中的一个,而另一个恰好在它的下面_
*/
	if(!tree)	return 0;
	if(tree==A)	return A;  //_找到节点,返回
	if(tree==B)	return B;	
	
	BTree *tmp1 = LowestCommonAncestor(tree->left,A,B);
	BTree *tmp2 = LowestCommonAncestor(tree->right,A,B);
	if(tmp1&&tmp2)
		return tree;	//_左右都找到,父节点就是tree了
	if(tmp1)
		return tmp1;
	if(tmp2)
		return tmp2;
}
//最近公共父节点的另一种方法:保存两条路径,_找最后一个相同的节点



//--------------------------------------_与二叉树自身相关的信息---------------------------
//深度(或高度)从1开始计算,有个好处是,当树为空时深度为0
int depth(BTree *tree)														//_二叉树深度
{
	if(tree==0)	return 0;
	return 1+max(depth(tree->left),depth(tree->right));
}

void levelnum(BTree *tree,int depth,int current)											//_输出某一层的节点
{
	if(tree==0)	return;
	if(current==depth)
	{
		cout<<tree->data<<‘ ‘;
		return;
	}
	levelnum(tree->left, depth,current+1);
	levelnum(tree->right,depth,current+1);
}




//=================================================================================
void main5()
{
	//BTree *tree=Create();
	int x[15]={1,2,4,0,0,5,7,0,0,0,3,0,6,0,0};
/*
			1
		  ╱ ╲
		 2     3
	   ╱ ╲    ╲
	  4     5	  6
	      ╱
		 7
*/
	BTree *tree=Create2(x,15);
	//printf("前序遍历:");Preorder(tree);printf("\n");
	//GetImage(tree);
	//printf("前序遍历:");Preorder(tree);printf("\n");


	//printf("中序遍历:");Inorder2(tree);printf("\n");
	//printf("后序遍历:");Posorder(tree);printf("\n");
/* 测试:从根节点到某一节点的路径
	BTree *node;findnode1(tree,7,node);
	stack<BTree *> st;
	findpath(tree,node,st);
	while(!st.empty())
	{
		cout<<st.top()->data<<" ";st.pop();
	}
** 测试:和为某一值的路径
	int currentSum=0;vector<BTree *> v;
	findsumpath(tree,10,currentSum,v);
** 测试:_最近公共父节点
	BTree *A,*B,*C;findnode1(tree,4,A);findnode1(tree,2,B);
	C=LowestCommonAncestor(tree,A,B);
	cout<<C->data<<endl;
** 测试:_树的深度
	cout<<depth(tree)<<endl;
	return;
** 测试:_输出树的某一层
	levelnum(tree,4,1);
*/
	


}

 

二叉树相关

标签:blog   io   os   sp   div   问题   c   on   log   

原文地址:http://www.cnblogs.com/shirishiyue/p/4003636.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!