二叉树的种类
在我们解题过程中二叉树有两种主要的形:满二叉树和完全二叉树。
满二叉树
满二叉树:如果一棵二叉树只有度为0的结点和度为 2 的结点,并且度为 0 的结点在同一层上,则这棵二叉树为满二叉树。
这棵二叉树为满二叉树,也可以说深度为 k,有2^k-1个节点的二叉树。
完全二叉树
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第h层(h从1开始),则该层包含1~ 2^(h-1)个节点。
二叉搜索树
前⾯介绍的树,都没有数值的,而二叉搜索树是有数值的了,二叉搜索树是⼀个有序树。
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树
二叉树的存储方式
链式存储
顺序存储
如果父节点的数组下标是 i,那么它的左孩子就是 i * 2 + 1,右孩⼦就是 i * 2 + 2。
二叉树的遍历方式
二叉树的递归顺序
二叉树的迭代遍历
前序遍历
前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。
为什么要先加入右孩子,再加入左孩子呢?因为这样出栈的时候才是中左右的顺序。
中序遍历
分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢,因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。
那么再看看中序遍历,中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了处理顺序和访问顺序是不一致的。
那么在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。
后序遍历
叉树层序遍历
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
题目一
这是二叉搜索树吗?
代码:
# include <stdio.h>
struct node
{
int val;
struct node * left;
struct node * right;
};
int n;
int num[1000];
int treemade(int l, int r, struct node* root)//二叉搜索树
{
if (l > r)
return 1;
int stand = num[l];
int help = l + 1;
while (help < r && num[help] < stand)
help++;
int mid = help;
while (help < r && num[help] >= stand)
help++;
if (help < r )//若大与小与部分拼不成一个完整序列,则说明不符合
return 0;
root = (struct node*) malloc(sizeof(struct node));
root->val = num[l];
root->left = NULL;
root->right = NULL;
return (treemade(l+1, mid-1, root->left) && treemade(mid, r, root->right));
}
void cmp(struct node* root, int cnt)
{
if (root->left != NULL)
cmp(root->left, cnt+1);
if (root->right != NULL);
cmp(root->right, cnt+1);
if (cnt == 0) //特判
printf("%d", root->val);
else
printf("%d ", root->val);
}
int main()
{
scanf("%d", &n);
for (int i=0; i<n; ++i)
scanf("%d");
struct node* root;
root = NULL;
if (treemade(0, n, root));//判断能否建成二叉搜索树
{
printf("YES\n");
cmp(root);
}
}
题目二
解题
在后序遍历序列中,根节点总是在最后一个位置,而在中序遍历序列中,根节点将序列分为左右两部分,分别对应左子树和右子树。
因此,我们可以利用两个数组的信息,递归构建二叉树,然后再进行层序遍历。
# include <stdio.h>
int n;
int num1[31];
int num2[31];
struct node
{
int val;
struct node* left;
struct node* right;
};
void treemade(int l, int r, struct node* root, int k)
{
int flag = 0;
if (k < 0)
return;
int help = num1[k];
int mid;
for (int i=l; i<=r; ++i)
{
if (num[i] == help)
{
mid = i;
flag = 1;
break;
}
}
if (flag == 1)
{
root = (struct node*)malloc(sizeof(struct node));
root->val = help;
root->left = NULL;
root->right = NULL;
treemade(l, mid-1, root->left, k-1);
treemade(mid+1, r, root->right, k-1);
}
else
{
treemade(l, r, root, k-1);
}
}
int main()
{
scanf("%d", &n);
for (int i=0; i<n; ++i)
scanf("%d", &num1[i]);
for (int i=0; i<n; ++i)
scanf("%d", &num2[i]);
int k = n-1;
struct node* root = NULL;
}