/*****************************算法思想:使用的是栈结构
步骤一:如果节点有左子树,则将该节点入栈;如果该节点没有左子树,则访问该节点
步骤二:如果节点有右子树,则重复步骤一;如果没有右子树(则说明该节点文访问完毕),则根据栈顶指示回退,访问栈顶元素,并访问右子树,重复步骤一
若栈为空,表示遍历完成。*******************************/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
#include <stack>
#include <stdlib.h>
#include <queue>
using namespace std;
typedef struct BiNode
{
int data;
struct BiNode *Lchild, *Rchild;
}BiNode,*BinTree;
typedef struct node
{
BinTree btnode;
bool isFirst;
}BtNnode;
BinTree Creat(BinTree T)
{
int num = 0;
scanf("%d",&num);
if (num == 0)
{ T = NULL;
return T;
}
T = (BinTree)malloc(sizeof(BiNode));
T->data = num;
T->Lchild = Creat(T->Lchild);
T->Rchild = Creat(T->Rchild);
return T;
}
/*
对于任何一个节点均可将其看做是根节点,因此可以直接访问。访问后,按照相同的规则访问其左孩子,其次再访问其右孩子。
对任何一个节点P:
1)访问它,并将它入栈;
2)然后判断其左孩子是否是空,若不为空,则将其左孩子置为当前的P节点,并循环步骤1)
若为空,则取出栈顶节点,并将栈顶的右孩子置为当前节点p,循环步骤1),并出栈。
3)直至到P为空或者栈为空。
*/
void preorder1(BinTree T)
{
stack<BinTree> s;
BinTree root = T;
while (root != NULL || (!s.empty()))
{
while (root != NULL)
{
cout << root->data << endl;
s.push(root);
root = root->Lchild;
}
if (!s.empty())
{
root = s.top();
s.pop();
root = root->Rchild;
}
}
}
void Inoder1(BinTree T)
{
stack<BinTree>s;
BinTree root = T;
while (root != NULL ||(!s.empty()))
{
while (root != NULL)
{
s.push(root);
root = root->Lchild;
}
if (!s.empty())
{
root = s.top();
cout << root->data << endl;
s.pop();
root = root->Rchild;
}
}
}
/*对任意一个节点P,将其入栈,然后沿着其左子树的方向遍历,直至搜素到没有左孩子的节点,此时该节点第一次出现在栈顶。但是还不能将其弹出,因为
她的右孩子还没有遍历,所以接下来对其右孩子按照相同的规则进行处理,当访问问其右孩子节点时,该节点有一次出现在栈顶,此时就可以访问并弹出该节点了。
也就是说当该节点第二次出现在栈顶时,才可以访问并弹出。因此需要设置一个访问的标志。
*/
void postorder1(BinTree T)
{
stack<BtNnode*>s;
BinTree p = T;
BtNnode* temp = NULL;
while ((p != NULL) || !s.empty())
{
while (p != NULL)
{
BtNnode* btn = (BtNnode*)malloc(sizeof(BtNnode));
btn->btnode = p;
btn->isFirst = true;
s.push(btn);
p = p->Lchild;
}
if (!s.empty())
{
temp = s.top();
s.pop();
if (temp->isFirst == true)
{
temp->isFirst = false;
s.push(temp);
p = temp->btnode->Rchild;
}
else
{
cout << temp->btnode->data;
p = NULL;
}
}
}
}
/*要保证根节点在其左右孩子节点都被访问过后,或者其左子树和右子树均为空时,才可以访问该 根节点*/
void postorder2(BinTree T)
{
stack<BinTree>s;
BinTree cur = NULL;
BinTree pre = NULL;
s.push(T);
while (!s.empty())
{
cur = s.top();
if ((cur->Lchild == NULL&&cur->Rchild == NULL) || (pre != NULL && (pre == cur->Lchild || pre == cur->Rchild)))
{
cout << cur->data << endl;
s.pop();
pre = cur;
}
else
{
if (cur->Rchild != NULL)
s.push(cur->Rchild);
if (cur->Lchild != NULL)
s.push(cur->Lchild);
}
}
}
int Getnumleaf(BinTree T)
{
int num = 0;
BinTree p = T;
if (p == NULL) return 0;
if (p->Lchild == NULL&&p->Rchild == NULL)
{
return 1;
}
return Getnumleaf(p->Lchild) + Getnumleaf(p->Rchild);
}
int Getdepth(BinTree T)
{
if (T == NULL){ return 0; }
int leftdepth = Getdepth(T->Lchild);
int rightdepth = Getdepth(T->Rchild);
return (leftdepth > rightdepth) ? (leftdepth + 1): (rightdepth + 1);
}
int Getdepth1(BinTree T)
{
queue<BinTree>q;
q.push(T);
int level = 0;
int layersize = 0;
int cnt = 0;
BinTree temp = NULL;
while (!q.empty())
{
level++;
layersize = q.size();
cnt = 0;
while (cnt < layersize)
{
cnt++;
temp = q.front();
q.pop();
if (temp->Lchild != NULL)
q.push(temp->Lchild);
if (temp->Rchild != NULL)
q.push(temp->Rchild);
}
}
return level;
}
void printree(BinTree T) // 按层次遍历树
{
if (T == NULL)return;
queue<BinTree>q;
q.push(T);
while (!q.empty())
{
BinTree temp = q.front();
cout << temp->data << endl;
q.pop();
if (temp->Lchild != NULL)
q.push(temp->Lchild);
if (temp->Rchild != NULL)
q.push(temp->Rchild);
}
}
/*判断一个节点是否在树中*/
bool Searchnode(BinTree T,BiNode* r)
{
bool res = false;
BinTree p = T;
stack<BinTree>s;
if (T == NULL)return false;
while (p!=NULL||!s.empty())
{
while (p != NULL)
{
if (p==T)
{
res = true;
break;
}
s.push(p);
p = p->Lchild;
}
if (!s.empty())
{
p = s.top();
s.pop();
p = p->Rchild;
}
}
return res;
}
/*
根据前序和中序序列重建二叉树
*/
vector<int> preorder = {1,2,4,7,3,5,6,8};
vector<int>inorder= {4,7,2,1,5,3,8,6};
BinTree reconstructree(vector<int>pre, int prebegin, int preend, vector<int>inorder, int inbegin, int inend)
{
BiNode* root = new BiNode();
root->data = pre[prebegin];
if (preend < prebegin || inend < inbegin)return NULL;
for (int i = inbegin; i <= inend; i++)
{
if (inorder[i] == preorder[prebegin])
{
root->Lchild = reconstructree(preorder, prebegin + 1, prebegin + i - inbegin, inorder, inbegin, i - 1);
root->Rchild = reconstructree(preorder, prebegin + 1 + i - inbegin, preend, inorder, i + 1, inend);
}
}
return root;
}
BinTree reConstructBinaryTree(vector<int>pre, vector<int>vin)
{
BinTree root = reconstructree(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1);
return root;
}
void main()
{
/*BiNode t1, t2, t3, t4, t5, t6;
memset(&t1, 0, sizeof(BiNode));
memset(&t2, 0, sizeof(BiNode));
memset(&t3, 0, sizeof(BiNode));
memset(&t4, 0, sizeof(BiNode));
memset(&t5, 0, sizeof(BiNode));
memset(&t6, 0, sizeof(BiNode));
t1.data = 1;
t2.data = 2;
t3.data = 3;
t4.data = 4;
t5.data = 5;
t6.data = 6;
t1.Lchild = &t2;
t1.Rchild = &t3;
t2.Lchild = &t4;
t3.Lchild = &t5;
t3.Rchild = &t6;*/
//preorder1(&t1);
/*BinTree T=NULL;
BinTree Root = Creat(T);
preorder1(Root);
printf("\n\n");
Inoder1(Root);
printf("\n\n");
postorder1(Root);
printf("\n\n");
postorder2(Root);
printf("\n\n");
int number = Getnumleaf(Root);
printf("%d\n",number);
printf("\n\n");
int depth = Getdepth1(Root);
printf("%d\n", depth);
printf("\n\n");
printree(Root);*/
/*inorder(&t1);
printf("\n");
postorder(&t1);
printf("\n");
//int r=countleafnum(&t1);
//printf("%d", r);
int sum = 0;
countleafnum1(&t1,&sum);
printf("%d", sum);*/
/*for (vector<int>::iterator it = preorder.begin(); it != preorder.end(); it++)
{
cout << *it << endl;
}
printf("\n\n");
for (vector<int>::iterator it = inorder.begin(); it != inorder.end(); it++)
{
cout << *it << endl;
}*/
BinTree T = NULL;
T = reConstructBinaryTree(preorder, inorder);
Inoder1(T);
system("pause");
}
常见的二叉树面试题
原文作者:luckystar_sai
原文地址: https://blog.csdn.net/qq_33573235/article/details/79488468
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/qq_33573235/article/details/79488468
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。