目录
1 非递归遍历二叉树
1.1 先序非递归
void PreTravel(BiTree root)
{
if (!root)
return;
BiNode * temp = root;
stack<BiNode*> s;
while (!s.empty()||temp)
{
while (temp)
{
s.push(temp);
cout<<temp->data;
temp = temp->left;
}
if (!temp)
{//左子树遍历完了或者右孩子为空,所以这里肯定要转右子树,也就是把访问过的节点干掉,转向他的右子树
temp = s.top();
s.pop();
temp = temp->right;
}
}
}
2.2 中序非递归
void InTravel1(BiTree root)
{
if (!root)
return;
stack<BiNode*> s;
BiNode* temp = root;
while (!s.empty()||temp)
{
while (temp)
{
s.push(temp);
temp = temp->left;
}
if (!temp)
{//走到左下角或者右孩子为空
temp = s.top();
s.pop();
cout<<temp->data;
temp = temp->right;
}
}
}
1.3 后序非递归
思想:顺着左边往下走,并记录最近访问过的节点,走到头的时候,拿出栈顶节点作为当前节点,看看右边有没有被访问过,若被访问,则输出该节点,并把当前节点置空;否则当前节点设为右孩子。
void PostTravel(BiTree root)
{
if (!root)
return;
stack<BiNode*> s;
BiNode* temp = root;
BiNode* recent = root;
while (!s.empty()||temp)
{
while (temp)
{
s.push(temp);
temp = temp->left;
recent = temp;
}
if (!temp)
{//走到最左边或输出元素后
temp = s.top();
if (temp->right==recent||!temp->right)
{//右边为空或者右边已经访问过
cout<<temp->data;
s.pop();
recent = temp;
temp = NULL;
}
else
{
temp = temp->right;
}
}
}
}
1.4 层次遍历
void LevelTravel(BiTree root)
{
queue<BiNode *> q;
if (!root)
return;
q.push(root);
while (!q.empty())
{
BiNode * temp = q.front();
cout<<temp->data;
q.pop();
if (temp->left)
q.push(temp->left);
if (temp->right)
q.push(temp->right);
}
}
2 二叉树深度
2.1 最大深度
2.1.1 返回值为深度
int MaxDepth(BiTree root)
{
if (!root)
return 0;
else
{
int ld = MaxDepth(root->left);
int rd = MaxDepth(root->right);
return (ld>rd?ld:rd)+1;
}
}
2.1.2 函数参数为深度
void getDepth(BiTree root,int &depth)
{
if (!root)
{
depth=0;
return;
}
int ld,rd;
getDepth(root->left,ld);
getDepth(root->right,rd);
depth = (ld>rd?ld:rd)+1;
}
2.2 最小深度
2.2.1 基于层次遍历
int MinDepth(BiTree root)
{
queue<BiNode *> q;
int count=0;
if (!root)
return count;
q.push(root);
count++;
while (!q.empty())
{
int x = q.size();
for (int i = 0; i < x; ++i) {
BiNode * temp = q.front();
q.pop();
if (!temp->left&&!temp->right)
{
return count;
}
if (temp->left)
q.push(temp->left);
if (temp->right)
q.push(temp->right);
}
count++;
}
}
2.2.1 基于递归遍历
思想:若左子树为空,则返回右子树的最小深度+1;若右子树为空,则返回左子树的最小深度+1;其他情况,则返回左右子树高度最小值+1。
int MinDepth(BiTree root)
{
if (!root)
return 0;
int ld = MinDepth(root->left);
int rd = MinDepth(root->right);
if (root->left&&root->right)
return (ld<rd?ld:rd)+1;
if(!root->left)
return rd+1;
else
return ld+1;
}
3 判断特殊二叉树
3.1 平衡二叉树
思想:平衡二叉树要么为空树,要么每个节点都是二叉树。判断的同时加入高度的判断,其实就是后序遍历的应用。
bool isAVL(BiTree root,int *depth)
{
if (!root)
{
*depth = 0;
return true;
}
int ld;
int rd;
if (isAVL(root->left,&ld)&&isAVL(root->right,&rd))
{
int balance = ld-rd;
if (balance<=1&&balance>=-1)
{
*depth = (ld>rd?ld:rd)+1;
return true;
}
}
return false;
}
3.2 二叉排序树
思路:定义一个局部变量保存上一个节点,看看当前节点是否大于该节点的值,若小于,则不是BST
bool isBST(BiTree root)
{
static BiNode* pre;
if (!root)
{
return true;
}
if (!isBST(root->left))
return false;
if (pre&&root->data<pre->data)
return false;
pre = root;
if (!isBST(root->right))
return false;
return true;
}
3.3 完全二叉树
bool isCompleteTree(BiTree root)
{//层次遍历,并让空节点也入队列,输出第一个空值后,后面若全空,则为完全二叉树;若出现非空,则不是完全二叉树
queue<BiNode*> q;
int count = 0;
if (!root)
return true;
q.push(root);
while (!q.empty())
{
BiNode* temp = q.front();
q.pop();
if (!temp)
{
count++;
}
else
{
if (count>=1)
return false;
q.push(temp->left);
q.push(temp->right);
}
}
return true;
}
4 给定两个遍历序列重建二叉树
4.1 给定前序和中序
- 前序数组中第一个为根节点
- 在中序数组中找到此节点的位置,则左半部分为左子树,右半部分为右子树,计算左右子树的长度,递归划分数组边界
- 重复1,2步
template <typename T> BiNode *Recreate(vector<T> pre,vector<T> in,int l1,int h1,int l2,int h2)
{
BiNode *root = new BiNode;
root->data = pre[l1];
int i;
for (i = l2; i < h2&&in[i]!=pre[l1]; ++i);
int llen = i-l2;
int rlen = h2-i;
if (llen)
root->left = Recreate(pre,in,l1+1,l1+llen,l2,l2+llen-1);
else
root->left = NULL;
if (rlen)
root->right = Recreate(pre,in,h1-rlen+1,h1,h2-rlen+1,h2);
else
root->right = NULL;
return root;
}
4.2 给定后序和中序
template <typename T> BiNode *PostInRecreate(vector<T> post,vector<T> in,int l1,int h1,int l2,int h2)
{
BiNode* root = new BiNode;
root->data = post[h1];
int i;
for (i = l2; i < h2&&in[i]!=post[h1]; ++i);
int llen = i-l2;
int rlen = h2-i;
if (llen)
{
root->left = PostInRecreate(post,in,l1,l1+llen-1,l2,l2+llen-1);
} else
root->left = NULL;
if (rlen)
{
root->right = PostInRecreate(post,in,h1-rlen,h1-1,h2-rlen+1,h2);
} else
root->right = NULL;
return root;
}