一、定义
1 二叉树
1、定义:每个结点最多能够有两个子节点
2、性质:
- 二叉树的第i层上至多有2i-1(i≥1)个节点。
- 深度为h的二叉树中至多含有2h-1个节点 。
- 若在任意一棵二叉树中,有n0个叶子节点,有n2个度为2的节点,则必有n0=n2+1 。
4
2 满二叉树
如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树 。
3 完全二叉树
1、定义
深度为k,有n个结点的二叉树当且仅当其每一个结点都与深度为k的满二叉树中编号从1到n的结点一一对应时,称为完全二叉树 。
2、性质
- 具有n个节点的完全二叉树深为log2x+1(其中x表示不大于n的最大整数)。
- 若对一棵有n个节点的完全二叉树进行顺序编号(1≤i≤n),那么,对于编号为i(i≥1)的节点:
A、当i=1时,该节点为根,它无双亲节点 [6] 。
B、当i>1时,该节点的双亲节点的编号为i/2 [6] 。
C、若2i≤n,则有编号为2i的左节点,否则没有左节点 [6] 。
D、若2i+1≤n,则有编号为2i+1的右节点,否则没有右节点 [6] 。
4 二叉搜索树
- 或者是一棵空树
- 或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
- 二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势
5 平衡二叉树
平衡二叉树的提出就是为了保证树不至于太倾斜,尽量保证两边平衡。因此它的定义如下:
- 平衡二叉树要么是一棵空树
- 要么保证左右子树的高度之差不大于 1
- 子树也必须是一颗平衡二叉树
6 平衡二叉查找树
平衡二叉搜索树是一种结构平衡的二叉搜索树,特点:
- 叶节点高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
- 它能在O(n)内完成插入、查找和删除操作
7 B树
即二叉搜索树:
- 所有非叶子结点至多拥有两个儿子(Left和Right);
- 所有结点存储一个关键字;
- 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树
8、 B-树
是一种多路搜索树(并不是二叉的):
- 定义任意非叶子结点最多只有M个儿子;且M>2;
- 根结点的儿子数为[2, M];
- .除根结点以外的非叶子结点的儿子数为[M/2, M];
- 每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)
- 非叶子结点的关键字个数=指向儿子的指针个数-1;
- .非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
- 非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1],K[i])的子树;
- 所有叶子结点位于同一层;
9
9、B+树
B+树是B-树的变体,也是一种多路搜索树:
1.其定义基本与B-树同,除了:
2.非叶子结点的子树指针与关键字个数相同;
3.非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间);
5.为所有叶子结点增加一个链指针;
6.所有关键字都在叶子结点出现;
10、B*树
B*树是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;
二、算法题
2.1 二叉树前序、中序和后序遍历
1、递归:
public class Solution {
public int[][] threeOrders (TreeNode root) {
List<Integer> preList = new ArrayList<Integer>();
preOrder(root, preList);
List<Integer> inList = new ArrayList<Integer>();
inOrder(root, inList);
List<Integer> postList = new ArrayList<Integer>();
postOrder(root, postList );
int[][] resArray = new int[3][preList.size()];
for(int i=0; i< preList.size(); i++) {
resArray[0][i] = preList.get(i);
resArray[1][i] = inList.get(i);
resArray[2][i] = postList.get(i);
}
return resArray;
}
void preOrder(TreeNode root, List<Integer> list) {
if(root == null) {
return ;
}
list.add(root.val);
preOrder(root.left, list);
preOrder(root.right, list);
}
void inOrder(TreeNode root, List<Integer> list) {
if(root == null) {
return ;
}
inOrder(root.left, list);
list.add(root.val);
inOrder(root.right, list);
}
void postOrder(TreeNode root, List<Integer> list) {
if(root == null) {
return ;
}
postOrder(root.left, list);
postOrder(root.right, list);
list.add(root.val);
}
}
2、栈
public int[][] threeOrders(TreeNode root) {
List<Integer> preList = new ArrayList<Integer>();
preOrder(root, preList);
List<Integer> inList = new ArrayList<Integer>();
inOrder(root, inList);
List<Integer> postList = new ArrayList<Integer>();
postOrder(root, postList);
int[][] resArray = new int[3][preList.size()];
for (int i = 0; i < preList.size(); i++) {
resArray[0][i] = preList.get(i);
resArray[1][i] = inList.get(i);
resArray[2][i] = postList.get(i);
}
return resArray;
}
void preOrder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
list.add(node.val);
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
}
void inOrder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode curr = root;
while (!stack.isEmpty() || curr != null) {
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
list.add(curr.val);
curr = curr.right;
}
}
void postOrder(TreeNode root, List<Integer> list) {
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode curr = stack.pop();
list.add(0, curr.val);
if (curr.left != null) {
stack.push(curr.left);
}
if (curr.right != null) {
stack.push(curr.right);
}
}
}
2.4、二叉树层次遍历bfs
描述
给定一个二叉树,返回该二叉树层序遍历的结果,(从左到右,一层一层地遍历)
例如:
给定的二叉树是{3,9,20,#,#,15,7},
该二叉树层序遍历的结果是
[ [3], [9,20], [15,7] ]
public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
ArrayList<ArrayList<Integer>> resultList = new ArrayList<ArrayList<Integer>>();
if(root == null) {
return resultList;
}
// write code here
ArrayDeque<TreeNode> queue = new ArrayDeque<TreeNode>();
queue.addLast(root);
ArrayDeque<TreeNode> tmpQueue = new ArrayDeque<TreeNode>();
ArrayList<Integer> tmpList = new ArrayList<Integer>();
while(!queue.isEmpty()) {
TreeNode node = queue.pollFirst();
tmpList.add(node.val);
if(node.left != null) {
tmpQueue.addLast(node.left);
}
if(node.right != null) {
tmpQueue.addLast(node.right);
}
if(queue.isEmpty()) {
queue = tmpQueue;
tmpQueue = new ArrayDeque<TreeNode>();
resultList.add(tmpList);
tmpList = new ArrayList<Integer>();
}
}
return resultList;
}
2.5、二叉树深度遍历dfs
描述
给定一棵二叉树,判断其是否是自身的镜像(即:是否对称)
例如:下面这棵二叉树是对称的
1
/ \
2 2
/ \ / \
3 4 4 3
下面这棵二叉树不对称。
1
/ \
2 2
\ \
3 3
备注:
希望你可以用递归和迭代两种方法解决这个问题
示例1
输入:{1,2,2}
返回值:true
示例2
输入:{1,2,3,3,#,2,#}
返回值:false
public class Solution {
boolean flag = true;
public boolean IsBalanced_Solution(TreeNode root) {
depth(root);
return flag;
}
private int depth(TreeNode node) {
if(node == null) {
return 0;
}
int leftDepth = depth(node.left);
int rightDepth = depth(node.right);
if( Math.abs(leftDepth-rightDepth) > 1 ) {
flag = false;
}
return Math.max(leftDepth, rightDepth) +1;
}
}