二叉树相关

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

#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);
*/

}
时间: 2024-11-05 06:26:34

二叉树相关的相关文章

LeetCode:二叉树相关应用

LeetCode:二叉树相关应用 基础知识 617.归并两个二叉树 题目 Given two binary trees and imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge them into a new binary tree. The merge ru

acwing 70-72 剑指OFFER 二叉树相关

地址 https://www.acwing.com/problem/content/66/ https://www.acwing.com/problem/content/67/ https://www.acwing.com/problem/content/submission/68/ 三道题都是二叉树相关 使用递归遍历即可解决 70. 二叉搜索树的第k个结点 给定一棵二叉搜索树,请找出其中的第k小的结点. 你可以假设树和k都存在,并且1≤k≤树的总结点数. 输入 输入:root = [2, 1,

C++实现二叉树相关操作

测试环境:windows 7 vs2010 主要实现二叉树的初始化递归和非递归遍历,层次遍历,获取叶子节点的个数,获取树的高度以及镜像树,部分代码也参考了互联网上的相关资料. 源程序: BinaryTreeNode.h #ifndef _BINARY_NODE #define _BINARY_NODE #include<iostream> using namespace std; template<class ItemType> struct BinaryTreeNode { It

二叉树相关知识总结(三)

前两篇日志主要研究了二叉树的相关基本知识,以及二叉树的最基本的实现 今天我们主要研究下,二叉查找树的相关主要特点,以及Java实现. 一.概念 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值: (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值: 换句话说:中根遍历是有序的. (3)左.右子树也分别为二叉排序树: 思考:重复的值怎么处理?是否存在值一样的节点? 初始化一颗二叉排序树根节点的选取问题 p

二叉树相关基础知识总结

一:树的概念 树是一种数据结构,它是由n(n>=1)个有限结点组成一个具有层次关系的集合.把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的.它具有以下的特点: 1:每个结点有零个或多个子结点: 2:没有父结点的结点称为根结点: 3:每一个非根结点有且只有一个父结点: 4:除了根结点外,每个子结点可以分为多个不相交的子树 二:树相关术语 节点的度:一个节点含有的子树的个数称为该节点的度: 叶节点或终端节点:度为0的节点称为叶节点: 非终端节点或分支节点:度不为0的节点:

二叉树相关题目总结

1. 简要介绍   关于二叉树问题,由于其本身固有的递归属性,通常我们可以用递归算法来解决.(<编程之美>,P253) 总结的题目主要以leetcode题目为主. 2. 测试用例 空树,只有节点的二叉树,只有左子树/右子树的二叉树,既有左子树右有右子树的二叉树. 3. 二叉树的遍历 遍历简介: 二叉树的遍历 分层遍历:二叉树分层遍历 前序遍历:[LeetCode] Binary Tree Preorder Traversal 中序遍历:[LeetCode] Binary Tree Inorde

[原创]二叉树相关笔试题代码

1 //二叉树问题集: 2 //20140822 3 4 #include <iostream> 5 #include <cstdio> 6 #include <cstdlib> 7 #include <queue> 8 #include <stack> 9 #include <list> 10 using namespace std; 11 12 13 typedef int ElementType; 14 typedef stru

java实现二叉树相关代码-----数据结构

接口 /*1.开发时间:2014-11-5  *2.开发者:赵远  *3.维护者:赵远  *3.程序说明:树的接口  *4.注意事项:暂且没有  * **/ package Tree; import Tree.node; public interface TreeNode { // class Node {};  // 1. 求二叉树中的节点个数  int GetNodeNum(node root);  // 2. 求二叉树的深度  int GetDepth(node root);  // 3.

二叉树相关问题

给定一个初始为空的栈,和n个操作组成的操作序列,每个操作只可能是出栈或入栈 要求在操作序列的执行过程中不会出现非法操作,即不会再空栈时执行出栈操作,同时保证当操作序列完成是栈恰好为空 求符合条件的序列个数 1<=n<=1000 思路:利用栈层次顺序建一棵二叉树,二叉树的节点的值非1即-1(1表示进栈,-1表示出栈) 如n=4,二叉树如下:(8种可能序列) 1 1       -1 1  -1    1   -1 1 -1  1 -1 1  -1  1  -1 满足的有    *    *