UU们度过愉快的周末,我们继续学习二叉树~
一、理论基础
关于二叉树,你该了解这些!| 二叉树理论基础一网打尽,二叉树的种类、二叉树的存储方式、二叉树节点定义、二叉树的遍历顺序_哔哩哔哩_bilibili
1、 二叉树的种类
①满二叉树
如果一棵二叉树只有度为0的节点和度为2的节点,并且度为0的节点在同一层上。
②完全二叉树
除了底层节点可能没填满,其余每层的节点数都达到最大值,并且底层的节点都集中在该层的最左边的若干位置。若底层为第h层,则该层包含1~2的h-1次方个节点。
③二叉搜索树
二叉搜索树是一个有序数,满足:若左子树不空,则左子树上所有节点的值都小于它的根节点的值;若右子树不空,则右子树上所有节点的值都大于它的根节点的值;它的左、右子树也分别为二叉搜索树。
④平衡二叉搜索树
平衡二叉搜索树也称为AVL(Adelson-Velsky and Landis)树,是一棵空树,或者它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
在C++中map、set、multiset的底层实现都是平衡二叉搜索树,所以map、set的增删操作的时间复杂度是O(logn), 而unordered_map、unordered_set的底层实现是哈希表。
2、二叉树的存储方式
①链式存储-->使用指针
②顺序存储-->使用数组
如果父节点的数组的下标是i,那么它的左孩子就是2i + 1,右孩子就是2i + 2,但是使用链表表示的二叉树更利于我们理解,所以一般使用链式存储的方式。
3、二叉树的遍历方式
(1)深度优先遍历-->先往深处遍历,遇到叶子结点再往回遍历
一 前序遍历(递归法、迭代法)
一 中序遍历(递归法、迭代法)
一 后序遍历(递归法、迭代法)
前中后指的就是中间节点的遍历顺序,只要记住前序、中序、后序指的是中间节点的位置即可。
不难发现:
- 前序遍历:中->左->右
- 中序遍历:左->中->右
- 后序遍历:左->右->中
(2)广度优先遍历-->一层一层地遍历
一 层次遍历(迭代法)
前中后序三种遍历的逻辑都可以借助栈这种数据结构使用非递归的方式实现,而广度优先搜索一般使用队列来实现,这也是由队列“先进先出”的特点所决定的,所以通过队列才能实现一层一层地遍历二叉树。
4、如何定义二叉树
C
struct TreeNode{
int val;
TreeNode *Left;
TreeNode *Right;
TreeNode{int val} : val(val), Left(nullptr), Right(nullptr) ()
};
Python
class TreeNode:
def __init__(self, val, left = None, right = None):
self.val = val
self.left = left
self.right = right
二、前、中、后序的递归遍历
每次写递归都要靠直觉? 这次带你学透二叉树的递归遍历!| LeetCode:144.前序遍历,145.后序遍历,94.中序遍历_哔哩哔哩_bilibili
写递归函数三步走:
- 确定递归函数的参数和返回值
- 确定终止条件
- 确定单层递归的逻辑
1.因为我们需要打印出前序遍历节点的数值,所以参数中需要传入数组来存放节点的数值,除了这一点,就不需要再处理其他数据了,也不需要有返回值,所以递归函数的返回类型是void
void traversal(TreeNode* cur, vector<int>& vec)
2.如何确定递归结束呢?当目前遍历到的节点为空时,说明本层递归就要结束了。如果当前遍历的这个节点为空,就直接返回
if (cur == NULL) return;
3.前序遍历是中->左->右,所以单层递归的逻辑就是先取中间节点的数值,再处理左右子树
ec.push_back(cur->val); // 中 traversal(cur->left, vec); // 左 traversal(cur->right, vec); // 右
CPP
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == NULL) return;
vec.push_back(cur->val); // 中
traversal(cur->left, vec); // 左
traversal(cur->right, vec); // 右
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root, result);
return result;
}
};
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == NULL) return;
traversal(cur->left, vec); // 左
vec.push_back(cur->val); // 中
traversal(cur->right, vec); // 右
}
后序遍历:
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == NULL) return;
traversal(cur->left, vec); // 左
traversal(cur->right, vec); // 右
vec.push_back(cur->val); // 中
}
C
//前序遍历:
void preOrder(struct TreeNode* root, int* ret, int* returnSize) {
if(root == NULL)
return;
ret[(*returnSize)++] = root->val;
preOrder(root->left, ret, returnSize);
preOrder(root->right, ret, returnSize);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
int* ret = (int*)malloc(sizeof(int) * 100);
*returnSize = 0;
preOrder(root, ret, returnSize);
return ret;
}
//中序遍历:
void inOrder(struct TreeNode* node, int* ret, int* returnSize) {
if(!node)
return;
inOrder(node->left, ret, returnSize);
ret[(*returnSize)++] = node->val;
inOrder(node->right, ret, returnSize);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
int* ret = (int*)malloc(sizeof(int) * 100);
*returnSize = 0;
inOrder(root, ret, returnSize);
return ret;
}
//后序遍历:
void postOrder(struct TreeNode* node, int* ret, int* returnSize) {
if(node == NULL)
return;
postOrder(node->left, ret, returnSize);
postOrder(node->right, ret, returnSize);
ret[(*returnSize)++] = node->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
int* ret= (int*)malloc(sizeof(int) * 100);
*returnSize = 0;
postOrder(root, ret, returnSize);
return ret;
}
Python
# 前序遍历-递归-LC144_二叉树的前序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
res = []
def dfs(node):
if node is None:
return
res.append(node.val)
dfs(node.left)
dfs(node.right)
dfs(root)
return res
#中序遍历
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
res = []
def dfs(node):
if node is None:
return
dfs(node.left)
res.append(node.val)
dfs(node.right)
dfs(root)
return res
#后序遍历
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
res = []
def dfs(node):
if node is None:
return
dfs(node.left)
dfs(node.right)
res.append(node.val)
dfs(root)
return res
二叉树的层序遍历,会在后面的内容分享
参考内容链接:代码随想录 (programmercarl.com)