树结构
来源:互联网 发布:淘宝补单怎么收费 编辑:程序博客网 时间:2024/06/05 15:29
树的基本概念
除了根节点之外每个结点只有一个父节点,根节点没有父节点;除了叶子节点,所有节点都有一个或多个子节点,叶子节点没有子节点。
二叉树
在二叉树中每个节点最多只有两个子节点二叉树的性质:
a. 在非空二叉树的k层上,至多有2^(k-1)个节点(k>=1)
b. 高度为k的二叉树中,最多有2^k-1个节点(k>=1)
c. 对于任何一棵非空的二叉树,如果叶节点个数为n0,度数为2的节点个数为n2,则有: n0 = n2 + 1完全二叉树性质:
除最后一层外,每一层上的节点数均达到最大值;在最后一层上只缺少右边的若干结点
a. 具有n个节点的完全二叉树的高度k为[log2n]
b. 对于具有n个节点的完全二叉树,如果按照从上(根节点)到下(叶节点)和从左到右的顺序 对二叉树中的所有节点从0开始到n-1进行编号,则对于任意的下标为k的节点,有:如果k=0,则它是根节点,它没有父节点;如果k>0,则它的父节点的下标为[(i-1)/2];
如果2k+1 <= n-1,则下标为k的节点的左子结点的下标为2k+1;否则,下标为k的节点没有左子结点.
如果2k+2 <= n-1,则下标为k的节点的右子节点的下标为2k+2;否则,下标为k的节点没有右子节点
满二叉树
除最后一层无任何子节点外,每一层上的所有结点都有两个子结点或0个子节点的二叉树。
在满二叉树中,叶节点的个数比分支节点的个数多1
- 二叉树的遍历
(1)前序遍历
a:非递归
/** * 二叉树的前序遍历 非递归方式 * 算法思想: * (1)若当前节点不为空,则输出当前节点,并把该节点压入栈,如果当前节点左子树不为空,指向左子树, * * (2)若当前节点为空,但栈不为空,读取并删除栈顶元素,指向栈顶元素的右节点,依次循环 * @param root */ public static void preOrder_notrec(TreeNode root){ //定义栈,用来存放节点 Stack<TreeNode> s=new Stack<TreeNode>(); while(root!=null || !s.empty()){ if(root!=null ){ System.out.println(root.val); s.push(root); root=root.left; }else{ root=(TreeNode) s.pop(); root=root.right; } } }
b:递归
/** * 二叉树的前序遍历 递归方式 * @param root */ public static void preOrder_rec(TreeNode root){ if(root!=null){ System.out.println(root.val); if (root.left!=null) preOrder_rec(root.left); if(root.right!=null) preOrder_rec(root.right); } }
(2)中序遍历
a:非递归
/** * 二叉树的中序遍历的非递归实现方式 * 算法思路: * * @param root */ public static void midOrder_notrec(TreeNode root){ //定义栈,用来存放节点 Stack<TreeNode> s=new Stack<TreeNode>(); while(root!=null || !s.empty()){ if(root!=null ){ s.push(root); root=root.left; }else{ root=(TreeNode) s.pop(); System.out.println(root.val); root=root.right; } } }
b:递归
/** * 二叉树的中序遍历 递归方式 * @param root */ public static void midOrder_rec(TreeNode root){ if(root!=null){ if (root.left!=null) preOrder_rec(root.left); System.out.println(root.val); if(root.right!=null) preOrder_rec(root.right); } }
(3) 后序遍历
a:非递归
/** * 二叉树的后序遍历的非递归实现方式 * 算法思路: * * @param root */ public static void postOrder_notrec(TreeNode root){ Stack<TreeNode> s = new Stack<TreeNode>();//定义栈,用来存放节点 TreeNode p = root;//pre标记最近出栈的节点,用于判断是否是p节点的右孩子,如果是的话,就可以访问p节点 TreeNode pre = p;//flag标记是出栈还是继续将左孩子进栈 boolean flag = true; while(p!=null || !s.isEmpty()) { if(p!=null && flag) { s.push(p); p = p.left; }else { if(s.isEmpty()) return; p = (TreeNode)s.peek(); if(p.right != null && p.right!=pre) { p = p.right; flag = true; }else { p = (TreeNode)s.pop(); System.out.println(p.val);; flag = false; pre = p; } } } }
b:递归
/** * 二叉树的后序遍历 递归方式 * @param root */ public static void postOrder_rec(TreeNode root){ if(root!=null){ if (root.left!=null) preOrder_rec(root.left); if(root.right!=null) preOrder_rec(root.right); System.out.println(root.val); } }
3:已知二叉树的前序遍历和中序遍历,求该二叉树结构
/** * 已知二叉树的前序遍历和后序遍历,重新构造该二叉树 * 并返回根节点 * @param preOrder * @param begin 根节点开始的地方:从1开始 * @param inOrder * @param end 该子树结束的地方:起始节点从1开始 * @param len 该树的长度 * @param root * @return */ public static TreeNode ReBuild(String preOrder,int begin,String inOrder, int end,int len){ if(preOrder==null || preOrder.length()==0 || inOrder==null || inOrder.length()==0 || len<=0){ return null; } //简历根节点 /*int和char的转换可能跟char是宽度为16位的实体,用utf-8编码有关系*/ /*方法1:要通过Character的getNumericValue方法把char类型转换为int类型*/ TreeNode root=new TreeNode(Character.getNumericValue(preOrder.charAt(begin-1))); /*方法2:或者先把char转换为String,再讲String转换为int*/ //int temp=Integer.parseInt((String.valueOf(preOrder.charAt(begin-1)))); //递归终结条件:子树只有一个节点 if(len==1){ return root; } //分拆子树的左子树和右子树 int i=0; while(i<len){ if(preOrder.charAt(begin-1)==inOrder.charAt(end-i)) break; i++; } //建立子树的左子树 root.left=ReBuild(preOrder,begin+1,inOrder,end-i-1,len-1-i); //建立子树的右子树 root.right=ReBuild(preOrder,begin+len-i,inOrder,end,i); return root; }
/** * 已知二叉树的前序遍历和中序遍历,确定二叉树 * @param preOrder * @param start 开始的节点位置:起始节点从0开始 * @param inOrder * @param end 结束的位置,起始节点从0开始 * @param len 树的节点个数 * @param root * @return */ public static TreeNode buildTree(char[] preOrder, int start, char[] inOrder, int end, int length){ if (preOrder == null || preOrder.length == 0 || inOrder == null || inOrder.length == 0 || length <= 0) { return null; } //确定根节点 char value = preOrder[start]; TreeNode root = new TreeNode(value); System.out.println(root.val); //跳出循环条件:只有一个节点时 if (length == 1) return root; //确定左右子树 int i = 0; while (i < length) { if (value == inOrder[end - i]) { break; } i++; } //左子树 root.left = buildTree(preOrder, start + 1, inOrder, end - i - 1, length - 1 - i); //右子树 root.right = buildTree(preOrder, start + length - i, inOrder, end, i ); return root; }
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 模仿TreeView结构的树结构类
- 树结构做情节结构的问题
- 树结构--Trie树
- 树结构--二叉树
- 树结构查询
- 树型结构很重要
- LeetCode *** 303. Range Sum Query - Immutable
- 【bzoj4430】[Nwerc2015]Guessing Camels赌骆驼
- SDAU 搜索专题 23 Another Eight Puzzle
- hibernate注解初探
- iOS开发 ☞ Quartz2D详解
- 树结构
- 通过第三方平台shareSDK分享链接
- 关于Adapter的notifyDataSetChanged是否生效
- ScrollView与GridView滚动发生冲突
- WSDL UDDI SOAP与在webserver标准中的作用
- [python]使用txt保存和读取列表变量
- 响应式布局初设(二)
- POJ-3494 Largest Submatrix of All 1’s(单调栈)
- RStudio: Warning message: Setting LC_CTYPE failed, using "C" 浅析