树是一种非线性存储结构,存储具有“一对多”关系的数据元素集合
a. 满二叉树
叶子结点都集中于二叉树的最底层
b. 完全二叉树
叶子结点只会出现在层次最大的两层上,且对于最大层次的叶子结点,都依次排列在该层最左边的位置
c. 二叉搜索树
左子树上所有节点的值都小于根节点,右子树上所有节点的值都大于根节点,左右子树各自又是一颗二叉搜索树
d. 平衡二叉搜索树
一种特殊的二叉搜索树,任意节点的左右子树深度之差不超过1
e. 红黑树
一种自平衡的二叉搜索树,在原有的平衡二叉搜索树基础上要求:
前序遍历实现:
// 定义二叉树节点
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
// 前序遍历
public void preOrder(TreeNode root){
// 基于递归实现
List<Integer> preRecur = new ArrayList<>();
preOrderRecur(root, preRecur);
// 基于非递归实现
List<Integer> preNonRecur = new ArrayList<>();
preOrderNonRecur(root, preRecur);
}
// 前序遍历的递归实现
public void preOrderRecur(TreeNode node, List<Integer> res){
if(null == node){
return;
}
res.add(node.val);
preOrderRecur(node.left, res);
preOrderRecur(node.right, res);
}
// 前序遍历的非递归实现
// 借助栈,先存右节点,再存左节点(由于栈是先进后出,先要左节点,就后压入左节点),先进后出即可实现前序
public void preOrderNonRecur(TreeNode node, List<Integer> res){
if(null == node){
return;
}
Stack<TreeNode> stack = new Stack<>();
stacl.push(node);
while(!stack.empty()){
TreeNode cur = stack.pop();
res.add(cur.val);
if(null != cur.right){
stack.push(cur.right);
}
if(null != cur.left){
stack.push(cur.left);
}
}
}
中序遍历实现:
// 定义二叉树节点
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
// 中序遍历
public void midOrder(TreeNode root){
// 基于递归实现
List<Integer> preRecur = new ArrayList<>();
midOrderRecur(root, preRecur);
// 基于非递归实现
List<Integer> preNonRecur = new ArrayList<>();
midOrderNonRecur(root, preRecur);
}
// 中序遍历的递归实现
public void midOrderRecur(TreeNode node, List<Integer> res){
if(null == node){
return;
}
midOrderRecur(node.left, res);
res.add(node.val);
midOrderRecur(node.right, res);
}
// 中序遍历的非递归实现
// 借助栈,先一直将当前节点的左节点压入栈,直至没有左节点就弹出,弹出节点有右节点,则将右节点压入栈,循环实现中序遍历
public void midOrderNonRecur(TreeNode node, List<Integer> res){
if(null == node){
return;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode temp = node;
while(!stack.empty() || null != temp){
if(null != temp){
// 持续将左节点压入栈中,直至没有左节点
stack.push(temp);
temp = temp.left;
} else {
// 栈顶弹出节点,若该节点有右节点,则下个循环将该节点的右节点压入栈
temp = stack.pop();
res.add(temp.val);
temp = temp.right;
}
}
}
后续遍历实现:
// 定义二叉树节点
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
// 后序遍历
public void postOrder(TreeNode root){
// 基于递归实现
List<Integer> preRecur = new ArrayList<>();
postOrderRecur(root, preRecur);
// 基于非递归实现
List<Integer> preNonRecur = new ArrayList<>();
postOrderNonRecur(root, preRecur);
}
public void postOrderRecur(TreeNode node, List<Integer> res){
if(null != node){
return;
}
postOrderRecur(node.left, res);
postOrderRecur(node.right, res);
res.add(node.val);
}
// 后序遍历非递归实现
// 借助栈,存储前序遍历结果(但先压入左节点,后压入右节点),列表存储每次前一个栈弹出的节点
// 列表元素逆序结果,就是后序遍历结果
public void postOrderNonRecur(TreeNode node, List<Integer> res){
if(null != node){
return;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(node);
while(!stack.empty()){
TreeNode cur = stack.pop();
res.add(cur.val);
if(null != cur.left){
stack.push(cur.left);
}
if(null != cur.right){
stack.push(cur.right);
}
}
// 列表逆序
Collections.reverse(res);
}
// 定义二叉树节点
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public void levelOrder(TreeNode root, List<Integer> res){
if(null == root){
return;
}
Queue<TreeNode> queue = new ArrayDeque<>();
queue.offer(root);
while(queue.isEmpty()){
TreeNode cur = queue.poll();
res.add(cur.val);
if(null != cur.left){
queue.offer(cur.left);
}
if(null != cur.right){
queue.offer(cur.right);
}
}
}
public void levelOrder(TreeNode root, List<List<Integer>> res){
if(null == root){
return;
}
Queue<TreeNode> queue = new ArrayDeque<>();
queue.offer(root);
while(queue.isEmpty()){
List<Integer> subRes = new ArrayList<>();
int count = queue.size();
for(int i = 0; i < count; i++){
TreeNode cur = queue.poll();
subRes.add(cur.val);
if(null != cur.left){
queue.offer(cur.left);
}
if(null != cur.right){
queue.offer(cur.right);
}
}
res.add(subRes);
}
}
LL型 – 单向右旋平衡处理:在A的左子节点(L)的左子树(L)上插入新节点,需要进行一次右向顺时针旋转
RR型 – 单向左旋平衡处理:在A的右子节点®的右子树®上出入新节点,需要进行一次左向逆时针旋转
LR型 – 双向旋转(先左后右)平衡处理:在A的左子节点(L)的右子树®上插入新节点
RL型 – 双向旋转(先右后左)平衡处理:在A的右子节点®的左子树(L)上插入新节点