赞
踩
(1)树是n(n>=0)个结点的有限集。当n = 0时,称为空树。在任意一棵非空树中应满足:
(2)树作为一种逻辑结构,同时也是一种分层结构,具有以下两个特点:
(1)下面结合图示来说明一下树的一些基本术语和概念。
(2)树的性质
1、二叉树的定义
二叉树是另一种树形结构,其特点是每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点),并且二叉树的子树有左右之分,其次序不能任意颠倒。
二叉树是n (n≥0) 个结点的有限集合:
二叉树是有序树,若将其左、右子树颠倒,则成为另一棵不同的二叉树。即使树中结点只有一棵子树,也要区分它是左子树还是右子树。二叉树的5种基本形态如图所示。
2、几个特殊的二叉树
(1)斜树
所有的结点都只有左子树的二叉树叫左斜树。所有结点都是只有右子树的二叉树叫右斜树。这两者统称为斜树。
(2)满二叉树
一棵高度为h ,且含有 2^h-1个结点的二叉树称为满二叉树,即树中的每层都含有最多的结点。满二叉树的叶子结点都集中在二叉树的最下一层,并且除叶子结点之外的每个结点度数均为2。可以对满二叉树按层序编号:约定编号从根结点(根结点编号为1 )起,自上而下,自左向右。这样,每个结点对应一个编号,对于编号为i的结点,若有双亲,则其双亲为i / 2 ,若有左孩子,则左孩子为2i;若有右孩子,则右孩子为 2i+1。
(3)完全二叉树
高度为h 、有n 个结点的二叉树,如图所示。其特点如下:
(4)二叉排序树
二叉排序树,又称二叉查找树。或者是一颗空树,或者是满足以下性质的二叉树:
(5)构造二叉排序树:
我们对于给定序列,取其第一个点为根结点,然后依次选择后续节点边比较边插入。如果比当前结点小,往该节点左子树移动比较,如果比当前结点大,则往该节点右子树移动比较。直到到一个待比较位置为空的位置,就是该节点的最终位置。
设输入序列为:(30,11,18,4,55,19,15,70,58)
(5)平衡二叉树
平衡二叉树,又称AVL树。 它或者是一颗空树,或者是具有以下性质的二叉树:它的左子树和右子树都是平衡树,且左子树和右子树的深度之差的绝对值不超过1。
平衡因子:又称BF,定义为该节点的左子树的深度减去它的右子树深度。则平衡二叉树的所有节点的平衡因子只可能是-1、0、1。只要二叉树上有一个结点的平衡因子BF绝对值大于1,那么二叉树就是不平衡的。
案例1:下图不是「平衡二叉树」因为有节点子树高度差大于 1 。
案例2:下图是「平衡二叉树」。
(1)任意一棵树,若结点数量为n,则边的数量为n − 1。
(2)非空二叉树上的叶子结点数等于度为2 的结点数加1,即n0 = n2 + 1。
(3)非空二叉树上第k 层上至多有 2^(k-1) 个结点( k ≥ 1 ) 。
(4)高度为h 的二叉树至多有 2^h-1个结点( h ≥ 1 )。
(5)对完全二叉树按从上到下、从左到右的顺序依次编号1 , 2.. ∗ , n ,则有以下关系:
(6)结点i 所在层次(深度)为 log 2(i) + 1。
(7)具有n 个(n > 0)结点的完全二叉树的高度为 log 2(n)+1。
先序遍历(PreOrder)的操作过程如下:
若二叉树为空,则什么也不做,否则,
1)访问根结点;
2)先序遍历左子树;
3)先序遍历右子树。
中序遍历( InOrder)的操作过程如下:
若二叉树为空,则什么也不做,否则,
1)中序遍历左子树;
2)访问根结点;
3)中序遍历右子树。
后序遍历(PostOrder) 的操作过程如下:
若二叉树为空,则什么也不做,否则,
1)后序遍历左子树;
2)后序遍历右子树;
3)访问根结点。
下图为二叉树的层次遍历,即按照箭头所指方向,按照1,2,3, 4的层次顺序,对二叉树中的各个结点进行访问。
要进行层次遍历,需要借助一个队列。先将二叉树根结点入队,然后出队,访问出队结点,若它有左子树,则将左子树根结点入队;若它有右子树,则将右子树根结点入队。然后出队,访问出队结…如此反复,直至队列为空。
(1)TreeNode类
- public class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
- TreeNode(){}
- TreeNode(int val,TreeNode left,TreeNode right){
- this.val = val;
- this.left = left;
- this.right = right;
- }
- }
(2)递归遍历方式
- public List<Integer> inorderTraversal(TreeNode root) {
- List<Integer> res = new ArrayList<Integer>();
- preorder(root, res);
- return res;
- }
-
- public void inorder(TreeNode root, List<Integer> res) {
- if (root == null)
- return;
- inorder(root.left, res);
- res.add(root.val);
- inorder(root.right, res);
- }
-
- public void preorder(TreeNode root, List<Integer> res) {
- if (root == null) {
- return;
- }
- res.add(root.val);
- preorder(root.left, res);
- preorder(root.right, res);
- }
-
- public void postorder(TreeNode root, List<Integer> res) {
- if (root == null)
- return;
- postorder(root.left, res);
- postorder(root.right, res);
- res.add(root.val);
- }

(3)非递归遍历方式
- public List<Integer> inorderTraversal(TreeNode root){
- List<Integer> res = new ArrayList<Integer>();
- Stack<TreeNode>stk = new Stack<>();
- while(root!=null || !stk.isEmpty()){
- while (root!=null){
- stk.push(root);
- root = root.left;
- }
- root = stk.pop();
- res.add(root.val);
- root = root.right;
- }
- return res;
- }
- // 根左右
- public List<Integer> preorderTraversal(TreeNode root){
- List<Integer> res = new ArrayList<Integer>();
- Stack<TreeNode>stk = new Stack<>();
- while (root != null || !stk.isEmpty()){
- while (root != null){
- res.add(root.val);
- stk.push(root);
- root = root.left;
- }
- TreeNode cur = stk.pop();
- root = cur.right;
- }
- return res;
- }
- /**
- *左右根 --> 根右左(翻转)
- * 对照前序遍历,为根左右,只需要把前序 left的地方改为 right
- * 即根左右(前序) ---将左右位置变换---> 根右左 ---再翻转---> 左右跟
- * */
- public List<Integer>postorderTraversal(TreeNode root) {
- List<Integer> res = new ArrayList<Integer>();
- Stack<TreeNode> stk = new Stack<>();
- while (root != null || !stk.isEmpty()) {
- while (root != null) {
- res.add(root.val);
- stk.push(root);
- root = root.right;
- }
- TreeNode cur = stk.pop();
- root = cur.left;
- }
- Collections.reverse(res);
- return res;
- }
- public List<List<Integer>> levelOrder(TreeNode root){
- List<List<Integer>>ret = new ArrayList<List<Integer>>();
- if(root == null)
- return ret;
-
- Queue<TreeNode>queue = new LinkedList<TreeNode>();
- queue.offer(root);
- while (!queue.isEmpty()){
- List<Integer>level = new ArrayList<Integer>();
- int curLevelSize = queue.size();
- for(int i=0;i<curLevelSize;i++){
- TreeNode node = queue.poll();
- level.add(node.val);
- if(node.left != null)
- queue.offer(node.left);
- if(node.right != null)
- queue.offer(node.right);
- }
- ret.add(level);
- }
- return ret;
- }
- public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
- List<List<Integer>>ret = new ArrayList<List<Integer>>();
- if(root == null)
- return ret;
- int curLevel = 0;
- Queue<TreeNode>queue = new LinkedList<TreeNode>();
- queue.offer(root);
- while (!queue.isEmpty()){
- List<Integer>level = new ArrayList<Integer>();
- int curLevelSize = queue.size();
- for(int i=0;i<curLevelSize;i++){
- TreeNode node = queue.poll();
- level.add(node.val);
- if(node.left != null)
- queue.offer(node.left);
- if(node.right != null)
- queue.offer(node.right);
- }
- curLevel ++;
- if(curLevel % 2 != 0)
- Collections.reverse(level);
- ret.add(level);
- }
- return ret;
- }

参考链接1:数据结构:树(Tree)【详解】_数据结构 树-CSDN博客
参考链接2:动态查找表之二叉排序树和平衡二叉树(图解+代码详解)-CSDN博客
参考链接3:二叉树三种遍历(递归+迭代)Java_java二叉树迭代遍历-CSDN博客
本文为学习笔记,所参考文章均已附上链接,若有疑问请私信!
创作不易,如果对你有点帮助的话麻烦点个赞支持一下!
新手小白,欢迎留言指正!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。