二叉树的种类
1.满二叉树
如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。
深度:k
节点数量:(2^k)-1
2.完全二叉树
在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置(从左到右连续)。
3.二叉搜索树
节点便于搜索,搜索一个节点的时间复杂度是logn级别的。
二叉搜索树是有数值的,二叉搜索树是一个有序树。
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树
下面这两棵树都是搜索树
4.平衡二叉搜索树
它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
C++中map、set、multimap,multiset的底层实现都是平衡二叉搜索树,所以map、set的增删操作时间时间复杂度是logn,且元素都是有序的。而unordered_map、unordered_set底层实现是哈希表。
二叉树的存储方式
二叉树可以链式存储(用指针),也可以顺序存储(用数组)。
链式存储用左右指针分别指向左右孩子节点:
如果父节点的数组下标是 i,那么它的左孩子就是 i * 2 + 1,右孩子就是 i * 2 + 2。
用链式表示的二叉树更有利于理解,所以一般用链式存储二叉树。构造二叉树的时候可以用链表构造。
二叉树的遍历
二叉树的遍历与图论类似,分为深度优先遍历和广度优先遍历。
1.深度优先遍历
深度优先遍历一般都用递归的方式来实现。前序遍历、中序遍历、后序遍历都属于深度优先遍历。栈其实就是递归的一种实现结构,也就说前中后序遍历的逻辑其实都是可以借助栈使用递归的方式来实现的。迭代法也可以实现前中后序遍历。
2.广度优先遍历
广度优先遍历是一层一层地遍历(二叉树)或一圈一圈地遍历(图论)。层次遍历属于广度优先遍历,可以用迭代法实现。
前中后序遍历的区别就在于中的位置:
前序遍历:中左右
中序遍历:左中右
后序遍历:左右中
二叉树的定义
用链表构造二叉树:
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};