开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情
树之习题选讲-Tree Traversals Again
树习题-TTA.1 题意理解
非递归中序遍历的过程
- Push的顺序为先序遍历(pre)
- Pop的顺序给出中序遍历(in)
树习题-TTA.2 核心算法
上图分别是先序、中序、后序遍历通过规律我们可以看到他们之间的位置分配
//伪代码
void solve(int preL,int inL,int n)
{
if(n == 0) return;//n等于0的时候什么都不做(n真的会右等于0的时候吗?为什么写他?)调用完了之后右边没有元素,此时n等于0,进行判断正常结束进程
if(n == 1){post[postL] == pre[preL];return;}//只有一个结点的时候,pre、in、post都应该等于同一个数字
root = pre[preL];
post[postL+n-1] = root;
for(i = 0; i < n; i++)
if(in[inL+i] == root) break; //判断in这个位置上的元素是不是等于根结点。结合上图看就是要找根结点在图中的哪里,找到了就跳出循环
//在跳出循环之后我们就同时知道了左子树包含了多少元素,然后递归的去解决左边跟右边的问题
L = i;R = n - L -1//得出左右两边的元素个数
solve(preL+1,inL,postL,L);//左边的
solve(preL+L+1,inL+L+1,postL+L,R)//右边的。第一个是蓝色的第一个位置,第二个也是蓝色一个的位置,第三个是蓝色的第一个位置(和前两个不同的是这个时候1在蓝色的后面,所以不用加上1了,第四个参数是右边子问题的总个数)
}
树之习题选讲-Complete Binary Search Tree(完全 二叉 搜索 树)
树习题-CBST.1 数据结构的选择
题意理解
题目要求:
输入一系列整数,要填入一个完全二叉树里面,同时这颗树还需要满足二叉搜索树的性质。也就是说左边的结点的键值都比根结点要小,右边的全部都比他要大,左右子树也都满足二叉搜索树递归的定义
经过修改后的图片如下:
树的表示法:链表 vs 数组
在这道题目中我们需要的操作:
1.填写数字(某种遍历),意思就是说对这棵树里面的每一个结点访问一次填写一个数字
2.层序遍历
为什么在很多情况下我们宁愿用链表去表示一颗树而不用数组呢?
用数组是可以的,好处是不涉及任何指针的操作。指针的操作通常是比较危险又比较耗时的
缺点:用数组去存,遇到左右不完全相等的树的时候,需要把中间那些不存在的结点的空间保留下来,要是树极端一点就非常耗费空间,在链表就没有这个问题
在这个问题中我们需要解决的问题:
- 完全二叉树,不浪费空间(从根结点到最后一个叶子结点一层层走下来没有一个是空的,没有一个元素是浪费的)
- 层序遍历 == 直接顺序输出(按照下标顺序输出就结束了,用数组的话)所以我们决定用数组解决这个问题