赞
踩
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
树型结构的特点
节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A节点的度为6
树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6
叶子节点或终端节点:度为0的节点称为叶节点; 如上图:B、C、H、I…等节点为叶节点
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节点
根结点:一棵树中,没有双亲结点的结点;如上图:A
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
树的高度或深度:树中节点的最大层次; 如上图:树的高度为4
非终端节点或分支节点:度不为0的节点; 如上图:D、E、F、G…等节点为分支节点
兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点
堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:H、I互为兄弟节点
节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
森林:由m(m>=0)棵互不相交的树的集合称为森林
一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
二叉树的特点:
1. 满二叉树: 一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。
结论:
2. 完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
结论:
二叉树的存储结构分为:顺序存储和类似于链表的链式存储
二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有二叉和三叉表示方式,具体如下:
// 孩子表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
}
// 孩子双亲表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
Node parent; // 当前节点的根节点
}
1.前序遍历:访问根结点—>递归访问根的左子树—>递归访问根的右子树。(根左右)
2.前序遍历:根的左子树—>根节点—>根的右子树。(左根右)
3.前序遍历:根的左子树—>根的右子树—>根节点。(左右根)
前序遍历结果:ABDEHCFG
前序特点:前序遍历结果集中,第一个输出的一定是当前树的根节点
中序遍历结果:DBEHAFCG
中序特点:中序遍历结果中,左子树的遍历结果在根节点的左侧,右子树的的遍历结果在根的右侧
后序遍历结果:DHEBFGCA
后序特点:后序遍历结果中,最后一个输出根节点
注:
package bin_tree; /** * 基础二叉树实现 * 左右孩子表示法 */ public class MyBinTree { private static class TreeNodes{ char val; // 节点值 TreeNodes left; // 左子树根节点 TreeNodes right; // 右子树根节点 // 构造方法 public TreeNodes(char val) { this.val = val; } } /** * 创建一个二叉树,返回根节点 */ public static TreeNodes build(){ // 创建8个节点 TreeNodes nodeA=new TreeNodes('A'); TreeNodes nodeB=new TreeNodes('B'); TreeNodes nodeC=new TreeNodes('C'); TreeNodes nodeD=new TreeNodes('D'); TreeNodes nodeE=new TreeNodes('E'); TreeNodes nodeF=new TreeNodes('F'); TreeNodes nodeG=new TreeNodes('G'); TreeNodes nodeH=new TreeNodes('H'); // 将这8个节点进行连接 nodeA.left=nodeB; nodeA.right=nodeC; nodeB.left=nodeD; nodeB.right=nodeE; nodeE.right=nodeH; nodeC.left=nodeF; nodeC.right=nodeG; return nodeA; } }
递归实现
/** * 先序遍历二叉树,传入一个二叉树的根节点,就可以按照先序遍历的方式遍历节点 * 根左右 * @param root */ public static void preOrder(TreeNodes root){ // 判空 if(root==null){ return; } // 输出根节点 System.out.println(root.val + " "); // 递归左子树 preOrder(root.left); // 递归右子树 preOrder(root.right); }
前序遍历代码——非递归实现(根左右)
package bin_tree.leetcode; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; /** * 前序遍历 非递归实现 */ class Num144_preOrderTraversal { // 将节点值存储在List集合中 List<Character> ret = new ArrayList<>(); public List<Character> preorderTraversal(TreeNode root) { // 1.判空 if (root == null) { return ret; } Deque<TreeNode> stack = new ArrayDeque<>(); stack.push(root); while (!stack.isEmpty()) { TreeNode cur = stack.pop(); // 先访问根节点 ret.add(cur.val); // 压入右孩子 if (cur.right != null) { stack.push(cur.right); } // 压入左孩子 if (cur.left != null) { stack.push(cur.left); } } return ret; } /** * 创建一个二叉树,返回根节点 */ public static TreeNode build() { // 创建8个节点 TreeNode nodeA = new TreeNode('A'); TreeNode nodeB = new TreeNode('B'); TreeNode nodeC = new TreeNode('C'); TreeNode nodeD = new TreeNode('D'); TreeNode nodeE = new TreeNode('E'); TreeNode nodeF = new TreeNode('F'); TreeNode nodeG = new TreeNode('G'); TreeNode nodeH = new TreeNode('H'); // 将这8个节点进行连接 nodeA.left = nodeB; nodeA.right = nodeC; nodeB.left = nodeD; nodeB.right = nodeE; nodeE.right = nodeH; nodeC.left = nodeF; nodeC.right = nodeG; return nodeA; } public static class TreeNode { char val; TreeNode left; TreeNode right; TreeNode() { } TreeNode(char val) { this.val = val; } TreeNode(char val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } public static void main(String[] args) { TreeNode root = build(); Num144_preOrderTraversal a = new Num144_preOrderTraversal(); System.out.println(a.preorderTraversal(root)); } }
中序遍历——递归实现(左根右)
/** * 中序遍历二叉树,传入一个二叉树的根节点,就可以按照中序遍历的方式遍历节点 * 左根右 * @param root */ public static void inOderTraversal(TreeNodes root){ // 判空 if(root==null){ return; } // 递归左子树 inOderTraversal(root.left); // 输出根节点 System.out.println(root.val + " "); // 递归右子树 inOderTraversal(root.right); }
中序遍历——非递归实现
package bin_tree.leetcode; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; /** * 中序遍历 非递归实现 */ class Num94_InorderTraversal { // 将节点值存储在List集合中 List<Character> ret = new ArrayList<>(); public List<Character> inorderTraversal(TreeNode root) { // 1.判空 if (root == null) { return ret; } // 当前走到的节点 TreeNode cur=root; Deque<TreeNode> stack = new ArrayDeque<>(); while(cur!=null || !stack.isEmpty()){ // 访问左子树,一直走到最底 while(cur!=null){ stack.push(cur); cur=cur.left; } // 此时已经走到左子树为空的位置 cur=stack.pop(); ret.add(cur.val); // 继续访问右子树 cur=cur.right; } return ret; } /** * 创建一个二叉树,返回根节点 */ public static TreeNode build() { // 创建8个节点 TreeNode nodeA = new TreeNode('A'); TreeNode nodeB = new TreeNode('B'); TreeNode nodeC = new TreeNode('C'); TreeNode nodeD = new TreeNode('D'); TreeNode nodeE = new TreeNode('E'); TreeNode nodeF = new TreeNode('F'); TreeNode nodeG = new TreeNode('G'); TreeNode nodeH = new TreeNode('H'); // 将这8个节点进行连接 nodeA.left = nodeB; nodeA.right = nodeC; nodeB.left = nodeD; nodeB.right = nodeE; nodeE.right = nodeH; nodeC.left = nodeF; nodeC.right = nodeG; return nodeA; } public static class TreeNode { char val; TreeNode left; TreeNode right; TreeNode() { } TreeNode(char val) { this.val = val; } TreeNode(char val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } public static void main(String[] args) { TreeNode root = build(); Num94_InorderTraversal a = new Num94_InorderTraversal(); System.out.println(a.inorderTraversal(root)); } }
后序遍历:左右根
传入一个二叉树的根节点,就可以按照中序遍历的方式遍历节点
/** * 后序遍历:左右根 * 传入一个二叉树的根节点,就可以按照中序遍历的方式遍历节点 */ public static void postOderTraversal(TreeNodes root){ // 判空 if(root==null){ return; } // 递归左子树 postOderTraversal(root.left); // 递归右子树 postOderTraversal(root.right); // 输出根节点 System.out.println(root.val + " "); }
后续遍历——非递归实现(左右根)
package bin_tree.leetcode; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; /** * 后序遍历 非递归实现 */ class Num145_PostorderTraversal { // 将节点值存储在List集合中 List<Character> ret = new ArrayList<>(); public List<Character> postorderTraversal(TreeNode root) { // 1.判空 if (root == null) { return ret; } // 当前走到的节点 TreeNode cur=root; // 上一个完全访问的节点(左右根都处理完了) TreeNode prev=null; Deque<TreeNode> stack = new ArrayDeque<>(); while(cur!=null || !stack.isEmpty()){ // 访问左子树,一直走到最底 while(cur!=null){ stack.push(cur); cur=cur.left; } // 此时已经走到左子树为空的位置,cur取栈顶元素 cur=stack.pop(); // 判断右树是否为空,或者被访问过 if (cur.right==null||prev==cur.right){ ret.add(cur.val); // 当前节点cur就是最后处理的根节点,更新prev引用,变为cur节点 prev=cur; cur=null; }else{ //此时右树不为空且没有处理过,将根节点压入栈中继续处理右子树 stack.push(cur); cur=cur.right; } } return ret; } /** * 创建一个二叉树,返回根节点 */ public static TreeNode build() { // 创建8个节点 TreeNode nodeA = new TreeNode('A'); TreeNode nodeB = new TreeNode('B'); TreeNode nodeC = new TreeNode('C'); TreeNode nodeD = new TreeNode('D'); TreeNode nodeE = new TreeNode('E'); TreeNode nodeF = new TreeNode('F'); TreeNode nodeG = new TreeNode('G'); TreeNode nodeH = new TreeNode('H'); // 将这8个节点进行连接 nodeA.left = nodeB; nodeA.right = nodeC; nodeB.left = nodeD; nodeB.right = nodeE; nodeE.right = nodeH; nodeC.left = nodeF; nodeC.right = nodeG; return nodeA; } public static class TreeNode { char val; TreeNode left; TreeNode right; TreeNode() { } TreeNode(char val) { this.val = val; } TreeNode(char val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } public static void main(String[] args) { TreeNode root = build(); Num145_PostorderTraversal a = new Num145_PostorderTraversal(); System.out.println(a.postorderTraversal(root)); } }
完整代码+测试
package bin_tree; /** * 基础二叉树实现 * 左右孩子表示法 */ public class MyBinTree { private static class TreeNodes{ char val; // 节点值 TreeNodes left; // 左子树根节点 TreeNodes right; // 右子树根节点 // 构造方法 public TreeNodes(char val) { this.val = val; } } /** * 创建一个二叉树,返回根节点 */ public static TreeNodes build(){ // 创建8个节点 TreeNodes nodeA=new TreeNodes('A'); TreeNodes nodeB=new TreeNodes('B'); TreeNodes nodeC=new TreeNodes('C'); TreeNodes nodeD=new TreeNodes('D'); TreeNodes nodeE=new TreeNodes('E'); TreeNodes nodeF=new TreeNodes('F'); TreeNodes nodeG=new TreeNodes('G'); TreeNodes nodeH=new TreeNodes('H'); // 将这8个节点进行连接 nodeA.left=nodeB; nodeA.right=nodeC; nodeB.left=nodeD; nodeB.right=nodeE; nodeE.right=nodeH; nodeC.left=nodeF; nodeC.right=nodeG; return nodeA; } /** * 先序遍历二叉树,传入一个二叉树的根节点,就可以按照先序遍历的方式遍历节点 * 根左右 * @param root */ public static void preOrder(TreeNodes root){ // 判空 if(root==null){ return; } // 输出根节点 System.out.print(root.val + " "); // 递归左子树 preOrder(root.left); // 递归右子树 preOrder(root.right); } /** * 中序遍历二叉树,传入一个二叉树的根节点,就可以按照中序遍历的方式遍历节点 * 左根右 * @param root */ public static void inOderTraversal(TreeNodes root){ // 判空 if(root==null){ return; } // 递归左子树 inOderTraversal(root.left); // 输出根节点 System.out.print(root.val + " "); // 递归右子树 inOderTraversal(root.right); } /** * 后序遍历:左右根 * 传入一个二叉树的根节点,就可以按照中序遍历的方式遍历节点 */ public static void postOderTraversal(TreeNodes root){ // 判空 if(root==null){ return; } // 递归左子树 postOderTraversal(root.left); // 递归右子树 postOderTraversal(root.right); // 输出根节点 System.out.print(root.val + " "); } public static void main(String[] args) { TreeNodes root=build(); System.out.print("前序遍历结果为:"); preOrder(root); System.out.println(); System.out.print("中序遍历结果为:"); inOderTraversal(root); System.out.println(); System.out.print("后序遍历结果为:"); postOderTraversal(root); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。