1、二叉树
1.1、特点
(1)和链表一样,动态数据结构
(2)二叉搜索树每个节点最多有两个孩子
(3)二叉搜索树每个节点最多有一个父亲
(4)二叉搜索树具有天然的递归结构
(5)每个节点的左子树也是二叉树
(6)每个节点的柚子树也是二叉树
1.2、总结
(1)叶子结点出现在二叉树的最底层,除了叶子结点之外的其他节点都有两个孩子节点;
(2)一个层数为k的满二叉树节点数为:
(3)地i层上的节点数为:
(4)一个层数为k的满二叉树的叶子结点个数(最后一层):
2、二分搜索树
2.1、特点
(1)二叉搜索树是特殊的二叉树
(2)二分搜索树每个节点的值:大于其左子树的所有节点的值
(3小于其柚子树的所有节点的值
(3)每一课子树也是二分搜索树
(4)存储的元素必须具有可比性
2.2、遍历方式
(1)前序遍历:中 -> 左 -> 右
public List<T> preTravel() {
// 保存整棵树的所有元素值
List<T> resultList = new ArrayList<>();
preTravel(this.root, resultList);
return resultList;
}
private void preTravel(Node<T> root, List<T> result) {
// 递归终止条件
if (root == null) {
return;
}
// 递归操作
// 1、保存当前值
result.add(root.val);
// 2、遍历左子树
preTravel(root.left, result);
// 3、遍历右子树
preTravel(root.right, result);
}
(2)后序遍历:左 -> 右 -> 中
public List<T> sufTravel() {
List<T> resultList = new ArrayList<>();
sufTravel(this.root, resultList);
return resultList;
}
private void sufTravel(Node<T> root, List<T> result) {
// 递归终止条件
if (root == null) {
return;
}
// 递归操作
// 1、遍历左子树
sufTravel(root.left, result);
// 2、遍历右子树
sufTravel(root.right, result);
// 3、保存当前值
result.add(root.val);
}
(3)中序遍历:左 -> 中 -> 右
public List<T> midTravel() {
List<T> resultList = new ArrayList<>();
midTravel(this.root, resultList);
return resultList;
}
private void midTravel(Node<T> root, List<T> result) {
// 递归终止条件
if (root == null) {
return;
}
// 递归操作
// 1、遍历左子树
midTravel(root.left, result);
// 2、保存当前值
result.add(root.val);
// 3、遍历右子树
midTravel(root.right, result);
}
(4)层次遍历
广度优先搜索BFS(Breadth First Search) -> 层序遍历
规定:从左到右
知识点:队列(FIFO)先进先出
public List<String> levelTravel() {
// 一般返回什么变量,就创建什么类型变量
List<String> list = new ArrayList<>();
// 入参判断 判断树是否为空
if (this.root == null) {
return list;
}
// 1、创建队列 LinkedList:双端队列
Queue<Pair<T>> queue = new LinkedList<>();
// 2、将根节点入队
queue.offer(new Pair<>(1, this.root));
// 3、循环出队
while (!queue.isEmpty()) {
// 4、出队
Pair<T> pair = queue.poll();
// 获取结点
Node<T> node = pair.node;
// 获取结点对应的层
int level = pair.level;
// [value:10 ;level: 2]
list.add("[value:" + node.val.toString() + ";level:" + level + "]");
// 5、判断左右子树是否为空
if (node.left != null) {
// 先判断左边:若不为空,则入队
queue.offer(new Pair<>(level + 1, node.left));
} // 不能else,因为左右子树可能都为空
if (node.right != null) {
// 在判断右边:若不为空,则入队
queue.offer(new Pair<>(level + 1, node.right));
}
}
return list;
}