//先序遍历
void BinTreePreOrderLoop(BinTreeNode* root)
{
//空树,直接返回
if(root==NULL)
{
return ;
}
//定义一个栈,并初始化
SeqStack stack;
SeqStackInit(&stack);
//定义一个节点,保存当前元素
BinTreeNode* cur=NULL;
//先入栈根节点
SeqQueuePush(&stack,root);
//循环取栈顶元素为当前元素(栈为空,循环结束)
while(SeqStacKTop(&stack,&cur))
{
// 出栈当前元素
SeqStackPop(&stack);
//访问当前元素
printf("%c ",cur->data);
//把当前元素的右子树入栈
SeqStackPush(&stack,cur->pright);
//把当前元素的左子树入栈
SeqStackPush(&stack,cur->pleft);
}
//循环结束,返回
return ;
}
//中序遍历(非递归)
void BinTreeInOrderLoop(BinTreeNode* root )
{
//空树,直接返回
if(root==NULL)
{
return ;
}
//定义一个栈并初始化
SeqStack stack;
SeqStackInit(&stack);
//定义一个节点,指向根节点
BinTreeNode* cur=root;
while( 1)
{
//判断当前节点是否为空,不为空,将当前元素出栈,
//并且将cur=cur-
while( cur)
{
SeqStackPush(&stack,cur);
cur=cur->pleft;
}
//为空,循环取栈顶元素,访问,出栈
//让cur=cur->pright,重复上面步骤
BinTreeNode* top=NULL;
while(SeqStacKTop(&stack,&top))
{
printf( "%c ",cur->data);
SeqStackPop(&stack);
}
cur=cur->pleft;
}
return ;
}
//后序遍历
void BinTreePostOrderLoop( BinTreeNode* root)
{
if(root==NULL)
{
return ;
}
SeqStack stack;
//定义一个指针cur指向root,用于保存当前节点
BinTreeNode* cur=root;
//定义一个指向当前节点的前一个节点
BinTreeNode* pre=NULL;
while( 1)
{
//循环判断当前节点是否为空,不为空,出栈当前元素,
//,并且cur=cur->pleft
while(cur)
{
SeqStackPush(&stack,cur);
cur=cur->pleft;
}
//为空,循环取栈顶元素,
BinTreeNode top=NULL;
while(SeqStacKTop(&stack,&top))
{
//对栈顶元素进行判定:如果栈顶元素的右子树为空,或者栈顶元素与访问元素的前一个元素不相同
if(top->pleft==NULL||top->pright!=pre)
{
//访问,并出栈,修改pre的值
printf("%c ",top->data);
SeqStackPop(&stack);
pre=cur;
}
//如果不满足上面条件,让cur=cur->pright,重复上面步骤
else
{
cur=cur->pright;
}
}
return ;
}
}
求二叉树镜像(递归)
void BinTreeMirrorR(BinTreeNode* root)
{
if( root==NULL)
{
return ;
}
Swap(&root->pleft,root->pright);
BinTreeMirrorR(root->pleft);
BinTreeMirrorR(root->pright);
return ;
//层序遍历二叉树,将打印式访问变成交换当前节点的左右孩子
}
//求二叉树镜像,非递归(层序遍历二叉树,将打印式访问变成交换当前节点的左右孩子)
void BinTreeMirror(BinTreeNode* root)
{
if(root==NULL)
{
return ;
}
//定义一个队列,并初始化
SeqQueue q;
SeqQueueInit(&q);
//将根节点入队列
SeqQueuePush(&q,root);
//定义一个节点,保存队首元素
SeqQueue *cur=NULL;
//循环判断队列是否为空,不为空,则进行交换当前节点的左右子树
while(SeqQueueFront(&q,&cur))
{
Swap(&cur->pleft,&cur->pright);
//将当前元素出队列
SeqQueuePop(&q);
//将当前元素的左子树入队
if(cur->pleft)
{
SeqQueuePush(&q,cur->pleft);
}
//将当前元素的右子树入队
if(cur->pright)
{
SeqQueuePush(&q,cur->pright);
}
}
return ;
}
//判断是否是完全二叉树
int IsCompelteTree(BinTreeNode *root)
{
if(root==NULL)
{
return 0;
}
//定义一个队列,并初始化
SeqQueue q;
SeqQueueInit(&q);
//将根节点入队列
SeqQueuePush(&q,root);
//定义一个标志位,标志位为0,表示不需要进入第二阶段,标志位为1,需要进入第二阶段判断
int flag=0;
//定义一个cur,保存栈顶值
BinTreeNode* cur=NULL;
while(SeqQueueFront(&q,&cur))
{
SeqQueuePop(&q);
//阶段一判断
if(flag==0)
{
//如果左右子树均不为空,则说明是完全二叉树,不需要进入第二阶段
if(cur->pleft!=NULL&&cur->pright!=NULL)
{
//将左右子树入队
SeqQueuePush(&q,cur->pleft);
SeqQueuePush(&q,cur->pright);
}
//一旦出现一个节点只有右子树,则一定不是完全二叉树,返回0
else if(cur->pleft==NULL&&cur->pright!=NULL)
{
return 0;
}
//若当前节点只有左子树,将flags置为1,将cur的右子树入队,并进入第二阶段判断
else if(cur->pleft!=NULL&&cur->pright==NULL)
{
flag=1;
SeqQueuePush(cur->pleft);
}
// 若当前节点,没有左右子树,将flags置为1,也进入阶段二
else
{
flag=1;
}
}
//阶段二判断
else
{
//任何节点都必须没有左右子树,则是完全二叉树,否则不是完全二叉树
if(cur->pleft==NULL&&cur->pright==NULL)
{
;
}
else
{
return 0;
}
}
}
//当遍历结束,所有条件满足,没有出现返回值0,则一定是完全二叉树,返回1
return 1;
}
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
if(pNode==NULL)
{
return NULL;
}
TreeLinkNode* next=NULL;
//有右子树,返回该右子树的最左孩子
if(pNode->right!=NULL)
{
TreeLinkNode* RightNode=pNode->right;
while(RightNode->left!=NULL)
{
RightNode=RightNode->left;
}
next=RightNode;
}
//遍历父节点
else if(pNode->next!=NULL)
{
TreeLinkNode* parentnode=pNode->next;
TreeLinkNode* curnode=pNode;
while(curnode->next!=NULL&&curnode==parentnode->right)
{
curnode=parentnode;
parentnode=parentnode->next;
}
next=parentnode;
}
return next;
}
};
重构二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
1.创建根节点,根节点肯定是前序遍历的第一个数
2.找到中序遍历根节点所在位置,存放于变量gen中
3.//对于中序遍历,根节点左边的节点位于二叉树的左边,根节点右边的节点位于二叉树的右边
4.利用上述这点,对二叉树节点进行归并
和shell排序的思想类似,取出前序和中序遍历根节点左边和右边的子树
5.递归,再对其进行上述所有步骤,即再区分子树的左、右子子数,直到叶节点
class Solution {
public:
struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) {
int inlen=in.size();
if(inlen==0)
return NULL;
vector<int> left_pre,right_pre,left_in,right_in;
//创建根节点,根节点肯定是前序遍历的第一个数
TreeNode* head=new TreeNode(pre[0]);
//找到中序遍历根节点所在位置,存放于变量gen中
int gen=0;
for(int i=0;i<inlen;i++)
{
if (in[i]==pre[0])
{
gen=i;
break;
}
}
//对于中序遍历,根节点左边的节点位于二叉树的左边,根节点右边的节点位于二叉树的右边
//利用上述这点,对二叉树节点进行归并
for(int i=0;i<gen;i++)
{
left_in.push_back(in[i]);
left_pre.push_back(pre[i+1]);//前序第一个为根节点
}
for(int i=gen+1;i<inlen;i++)
{
right_in.push_back(in[i]);
right_pre.push_back(pre[i]);
}
//和shell排序的思想类似,取出前序和中序遍历根节点左边和右边的子树
//递归,再对其进行上述所有步骤,即再区分子树的左、右子子数,直到叶节点
head->left=reConstructBinaryTree(left_pre,left_in);
head->right=reConstructBinaryTree(right_pre,right_in);
return head;
}
};