标签: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 ¤tSum,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