Authur Whywait 做一块努力吸收知识的海绵
想看博主的其他所有leetcode卡片学习笔记链接?传送门点这儿
关于树和二叉树的介绍
树
是一种经常用到的数据结构,用来模拟具有树状结构性质的数据集合。
树里的每一个节点有一个根植和一个包含所有子节点的列表。从图的观点来看,树也可视为一个拥有N 个节点
和N-1 条边
的一个有向无环图。
二叉树
是一种更为典型的树树状结构。如它名字所描述的那样,二叉树是每个节点最多有两个子树
的树结构,通常子树被称作“左子树”和“右子树”。
树的遍历 - 介绍
前序遍历 - 前序遍历首先访问根节点,然后遍历左子树,最后遍历右子树。
中序遍历 - 中序遍历是先遍历左子树,然后访问根节点,然后遍历右子树。
后序遍历 - 后序遍历是先遍历左子树,然后遍历右子树,最后访问树的根节点。
通常来说,对于二叉搜索树,我们可以通过中序遍历得到一个递增的有序序列。 我们将在另一张卡片(数据结构介绍 – 二叉搜索树)中再次提及。
值得注意的是,当你删除树中的节点时,删除过程将按照后序遍历的顺序进行。 也就是说,当你删除一个节点时,你将首先删除它的左节点和它的右边的节点,然后再删除节点本身。
后序在数学表达中被广泛使用。 编写程序来解析后缀表示法更为容易…
二叉树的前序遍历 - 练习
给定一个二叉树,返回它的 前序 遍历.
输入: [1,null,2,3]
输出: [1,2,3]
递归算法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
void preorder(struct TreeNode* root, int* array, int* returnSize){
if(!root) return;
array[(*returnSize)++] = root->val;
preorder(root->left, array, returnSize);
preorder(root->right, array, returnSize);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
* returnSize = 0;
if(!root) return NULL;
int* array = (int *)malloc(sizeof(int) * 100000);
preorder(root, array, returnSize);
return array;
}
二叉树的中序遍历 - 练习
给定一个二叉树,返回它的中序 遍历。
输入: [1,null,2,3]
输出: [1,3,2]
递归算法
void inorder(struct TreeNode* root, int* array, int* returnSize){
if(!root) return;
inorder(root->left, array, returnSize);
array[(*returnSize)++] = root->val;
inorder(root->right, array, returnSize);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
* returnSize = 0;
if(!root) return NULL;
int* array = (int *)malloc(sizeof(int) * 100000);
inorder(root, array, returnSize);
return array;
}
二叉树的后序遍历 - 练习
给定一个二叉树,返回它的 后序 遍历。
输入: [1,null,2,3]
输出: [3,2,1]
递归算法
void postorder(struct TreeNode* root, int* array, int* returnSize){
if(!root) return;
postorder(root->left, array, returnSize);
postorder(root->right, array, returnSize);
array[(*returnSize)++] = root->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
* returnSize = 0;
if(!root) return NULL;
int* array = (int *)malloc(sizeof(int) * 100000);
postorder(root, array, returnSize);
return array;
}
前序中序后序 - 比较
比较上面三种遍历的递归方法,我们可以发现:
在程序实现的时候,不同遍历方式的唯一区别就在函数里三条语句的顺序而已。
postorder(root->left, array, returnSize);
postorder(root->right, array, returnSize);
array[(*returnSize)++] = root->val;
也就是根、左子树和右子树三者谁先将其的val
写入数组array
中。
记忆小技巧
左子树总是先比右子树遍历,“前中后”指的是根结点的位置。
解释:
左子树总是比右子树先入数组;
如果根节点在比左子树先入数组array,则为前序;
如果根节点在左右子树之间入数组array,则为中序;
如果根节点在比右子树先入数组array,则为后序;【注】"入数组array"这种表达方式显得更直观一些,而array是我们最后要返回的数组,数组里元素的顺序就是遍历的顺序。
层序遍历
层序遍历就是逐层遍历树结构。
广度优先搜索 (BFS算法)是一种广泛运用在树或图这类数据结构中,遍历或搜索的算法。 该算法从一个根节点开始,首先访问节点本身。 然后遍历它的相邻节点,其次遍历它的二级邻节点、三级邻节点,以此类推。
当我们在树中进行广度优先搜索时,我们访问的节点的顺序是按照层序遍历顺序的。
二叉树的层序遍历 - 练习
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
二叉树:[3,9,20,null,null,15,7],
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
BFS算法
代码用的是之前在队列和栈卡片中(点这里是传送门)中提到的模板,也没有用什么循环队列,只是把空间开得足够大罢了,这样的作法是省时间。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
# define MAXSIZE 10000
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes){
* returnSize=0;
if(!root) return NULL;
int **array = (int **)malloc(sizeof(int*) * MAXSIZE);
struct TreeNode Root = *root;
struct TreeNode* queue = (struct TreeNode *)malloc(sizeof(struct TreeNode) * MAXSIZE);
int front=0, tail=0;
* returnColumnSizes = (int *)malloc(sizeof(int) * MAXSIZE);
array[* returnSize] = (int *)malloc(sizeof(int));
array[* returnSize][0] = root->val;
(* returnColumnSizes)[* returnSize] = 1;
queue[tail++] = *root;
while(front<tail){
(* returnSize)++;
int counter=0;
int size=tail-front;
array[* returnSize] = (int *)malloc(sizeof(int) * MAXSIZE);
for(int i=0; i<size; i++){
if(!queue[front].left && !queue[front].right){
front++;
continue;
}
if(queue[front].left){
queue[tail++] = *(queue[front].left);
array[* returnSize][counter++] = queue[front].left->val;
}
if(queue[front].right){
queue[tail++] = *(queue[front].right);
array[* returnSize][counter++] = (*(queue[front].right)).val;
}
front++;
}
(* returnColumnSizes)[* returnSize] = counter;
}
return array;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200402183051962.png)
>都看到了这里,不点个👍再走?(╯‵□′)╯︵┻━┻