网站及微站建设合同验收网站开发word
网站及微站建设合同验收,网站开发word,做一家视频网站,济南网站建设套餐在学习二叉树之前.必须先要掌握一些树的重要概念:
结点的度:一个结点含有的子树个数称为该结点的度.树的度:一棵树中,所有节点度的最大值称为树的度.叶子结点:度为0的结点称为叶子节点.(也叫终端结点)双亲结点:若一个结点含有子结点,则这个结点称为其子结点的双亲结点(也叫父节…在学习二叉树之前.必须先要掌握一些树的重要概念:
结点的度:一个结点含有的子树个数称为该结点的度.树的度:一棵树中,所有节点度的最大值称为树的度.叶子结点:度为0的结点称为叶子节点.(也叫终端结点)双亲结点:若一个结点含有子结点,则这个结点称为其子结点的双亲结点(也叫父节点).孩子结点:一个结点含有的子树的根结点称为该结点的孩子结点(也叫子结点).根节点:一棵树中,没有双亲结点的结点.结点的层次:从根开始定义起,根为第一层;根的子结点为第二层,以此类推.树的高度或深度:树中结点的最大层次.
以下树的概念只需了解:
非终端结点或分支结点度不为0的结点兄弟结点具有相同父结点的结点互称为兄弟结点堂兄弟结点双亲在同一层的结点互为堂兄弟结点的祖先从根到该结点所经分支上的所有结点子孙以某结点为根的子树中任一结点都称为该结点的子孙森林由mm0棵互不相交的树组成的集合称为森林
二叉树:
一颗二叉树是结点的一个有限集合.二叉树不存在度大于2的结点,并且二叉树的子树有左右之分,且次序不能颠倒,因此二叉树是有序树.
两种特殊的二叉树:
满二叉树: 一棵二叉树如果 每层的结点数都达到最大值则这棵二叉树就是满二叉树 。也就是说 如果一棵 二叉树的层数为 K 且结点总数是 (2^k) -1 则它就是满二叉树 。 完全二叉树: 完全二叉树是效率很高的数据结构完全二叉树是由满二叉树而引出来的。对于深度为 K 的有 n 个结点的二叉树当且仅当其每一个结点都与深度为 K 的满二叉树中编号从 0 至 n-1 的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。 二叉树的性质: 1.若规定根结点的层数为1,则一颗非空二叉树的的i层上最多有2^(i-1)个结点.(i0) 2. 若规定只有 根结点的二叉树的深度为 1 则 深度为 K的二叉树的最大结点数是 2^k -1(k0) 3. 对任何一棵二叉树 , 如果其 叶子结点个数为 n0, 度为 2 的非叶子结点个数为 n2, 则有 n0 n2 1 4. 具有 n 个结点的完全二叉树的深度 k为log(n1) 向上取整 5. 对于具有n 个结点的完全二叉树 如果按照 从上至下从左至右的顺序对所有节点从 0 开始编号 则对于 序号为i 的结点有 若i0双亲序号(i-1)/2i0i为根结点编号无双亲结点 若2i1n左孩子序号2i1否则无左孩子 若2i2n右孩子序号2i2否则无右孩子 二叉树的存储: 二叉树的存储结构分为:顺序存储和类似于链表的链式存储. 二叉树的基本操作: 为了能够进行二叉树一些基本操作,我们先手动自己创建一颗二叉树.
//用一个内部类定义二叉树中的结点
//这用的是孩子表示法
static class TreeNode {public char val;public TreeNode left;//存储左孩子的引用public TreeNode right;//存储右孩子的引用public TreeNode(char val) {this.val val;}
}public TreeNode createTree() {TreeNode A new TreeNode(A);TreeNode B new TreeNode(B);TreeNode C new TreeNode(C);TreeNode D new TreeNode(D);TreeNode E new TreeNode(E);TreeNode F new TreeNode(F);TreeNode G new TreeNode(G);TreeNode H new TreeNode(H);A.left B;A.right C;B.left D;B.right E;C.left F;C.right G;E.right H;return A;
} 二叉树的遍历:遍历(Traversal)是指沿着某条搜索路线依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题. 前序遍历: 根节点-根的左子树-根的右子树 中序遍历:根的左子树-根结点-根的右子树 后序遍历:根的左子树-根的右子树-根结点 注意: 1.如果只给一个遍历,能不能创建一颗二叉树? 不能,因为有可能存在两颗不同的树,某一个遍历是一样的. 2.如果只给前序和后序遍历,能不能创建一颗二叉树? 不能,前序或者后序都是确定根的位置,无法确定左树和右树的位置,至少提供一个中序遍历前序或者后序. 代码实现:(递归实现) 前序遍历: public void preOrder(TreeNode root) {if (root null) {return;}System.out.print(root.val );preOrder(root.left);preOrder(root.right);} 中序遍历: public void inOrder(TreeNode root) {if (root null) {return;}inOrder(root.left);System.out.print(root.val );inOrder(root.right);} 后续遍历: public void postOrder(TreeNode root) {if (root null) {return;}postOrder(root.left);postOrder(root.right);System.out.print(root.val );} 关于遍历的oj题: 注意:与我们上面写的前序代码不同的是,这道题目中要求我们把结果放到List当中并返回. 解法1: ListInteger list new ArrayList();public ListInteger preorderTraversal(TreeNode root) {if(rootnull){return list;}list.add(root.val);preorderTraversal(root.left);preorderTraversal(root.right);return list;} 解法2:我们可以巧妙运用函数的返回值. public ListInteger preorderTraversal(TreeNode root) {ListInteger ret new ArrayList();if(rootnull){return ret;}ret.add(root.val);ListInteger leftTree preorderTraversal(root.left);ret.addAll(leftTree);ListInteger rightTree preorderTraversal(root.right);ret.addAll(rightTree);return ret;} 获取二叉树的结点个数: 两种思路: 遍历的思路,定义一个nodesize,每遍历一个结点就让nodesize;子问题的思路:root的结点个数root.left的结点个数root.right的结点个数1; 遍历: public static int nodeSize 0;public static int size(TreeNode root) {if (root null) {return 0;}nodeSize;size(root.left);size(root.right);return nodeSize;} 子问题: public int size2(TreeNode root) {if (root null) {return 0;}int tmp size2(root.left) size2(root.right) 1;return tmp;} 获取二叉树叶子结点的个数: 子问题的思想:叶子结点的个数左子树的叶子结点的个数右子树的叶子结点个数 int getLeafNodeCount(TreeNode root) {if (root null) {return 0;}if (root.right null root.left null) {return 1;}int tmp getLeafNodeCount(root.left) getLeafNodeCount(root.right);return tmp;} 遍历的思想: public static int leafSize 0;void getLeafNodeCount2(TreeNode root) {if (root null) {return;}if (root.left null root.right null) {leafSize;}getLeafNodeCount2(root.left);getLeafNodeCount2(root.right);} 获取第k层结点的个数: 倘若k3,让我们求第三层上结点的个数,可以采用子问题的思路. 对A来说,求的是第三层上的个数,对B来说求得是第二层上的个数,对D来说是第一层的个数. 相对于根结点的第K层,其实就是左树的K-1层右树的K-1层 int getKLevelNodeCount(TreeNode root, int k){if(root null || k 0){return 0;}if(k1){return 1;}int tmp getKLevelNodeCount(root.left,k-1)getKLevelNodeCount(root.right,k-1);return tmp;} 获取二叉树的高度: 树的高度左子树和右子树的最大值1; public int getHeight(TreeNode root) {if (root null) {return 0;}int leftHeight getHeight(root.left);int rightHeight getHeight(root.right);return leftHeight rightHeight ? leftHeight 1 : rightHeight 1;} 检测树中value值的元素是否存在: 1.判断根节点
2.判断root.left
3.判断root.right
4.不存在你要找的节点 public TreeNode find(TreeNode root, char val) {if (root null) {return null;}if (root.val val) {return root;}TreeNode ret1 find(root.left, val);if (ret1 ! null) {return ret1;}TreeNode ret2 find(root.right, val);if (ret2 ! null) {return ret2;}return null;} 层序遍历: 非递归层序遍历,利用队列这种数据结构. public void levelOrder(TreeNode root) {if (root null) {return;}QueueTreeNode qu new LinkedList();qu.offer(root);while (!qu.isEmpty()) {TreeNode cur qu.poll();System.out.print(cur.val );if (cur.left ! null) {qu.offer(cur.left);}if (cur.right ! null) {qu.offer(cur.right);}}} 判断一棵树是不是完全二叉树: public boolean isCompleteTree(TreeNode root){if (root null){return true;}QueueTreeNode qu new LinkedList();qu.offer(root);while(!qu.isEmpty()){TreeNode cur qu.poll();if (cur ! null){qu.offer(cur.left);qu.offer(cur.right);}else {break;}}//判断队列剩下的值是不是有 非null的存在while (!qu.isEmpty()){TreeNode pop qu.poll();if (pop ! null){return false;}}return true;} oj题: 题1:相同的树 首先相同,既要满足结构上相同又要满足数值上相同. 思路解析: 首先判断一个为空一个不为空的情况,如果满足条件直接返回false,不满足就剩下两种情况, 一种是两个都为空的情况,一种是两个都不为空的情况. 如果都为空,直接返回true. 都不为空就判断结点的数值是否相等.不相等直接返回false,如果相等就在去递归判断p的左树和q的左树p的右树和q的右树. 此题的时间复杂度: p:M q:N O(min(M,N)) class Solution {public boolean isSameTree(TreeNode p, TreeNode q) {if(pnullq!null ||p!nullqnull ){return false;}if(pnull q null){return true;}if(p.val!q.val){return false;}return (isSameTree(p.left,q.left)isSameTree(p.right,q.right));}
} 题2:另一颗树的子树 class Solution {public boolean isSameTree(TreeNode p, TreeNode q) {if(pnullq!null ||p!nullqnull ){return false;}if(pnull q null){return true;}if(p.val!q.val){return false;}return (isSameTree(p.left,q.left)isSameTree(p.right,q.right));}public boolean isSubtree(TreeNode root, TreeNode subRoot) {if(root null){return false;}//1.判断root和subRoot是不是两颗相同的树if(isSameTree(root,subRoot)){return true;}//2.判断subRoot是不是root.left的子树if(isSubtree(root.left,subRoot)){return true;}//3.判断subRoot是不是root.right的子树if(isSubtree(root.right,subRoot)){return true;}return false;}
} 题3:翻转二叉树 思路:要翻转整棵树,实际上是翻转整棵树的左树和右树 1.翻转root.left和root.right 2.处理root.left的子树 3.处理root.right的子树 class Solution {public TreeNode invertTree(TreeNode root) {if(root null){return null;}TreeNode tmp root.left;tmp root.left;root.left root.right;root.right tmp;invertTree(root.left);invertTree(root.right);return root;}
} 题4:平衡二叉树 要判断整棵树是高度平衡的二叉树,那么必须满足每棵子树都是平衡的二叉树. 思路:先求当前root结点是不是平衡的,在判断左树是不是平衡的,再去判断右树是不是平衡的. class Solution {public int maxDepth(TreeNode root){if(root null){return 0;}int leftHeight maxDepth(root.left);int rightHeight maxDepth(root.right);return leftHeight rightHeight ? leftHeight1 : rightHeight1;} public boolean isBalanced(TreeNode root) {if(root null){return true;}int leftH maxDepth(root.left);int rightH maxDepth(root.right);return Math.abs(leftH-rightH) 2 isBalanced(root.left) isBalanced(root.right);}
} 当前代码的时间复杂度达到了:O(N^2),最坏的情况下每个结点都要求高度. 如果要让时间复杂度控制在O(N),如何操作?? 在上述代码当中,再求根节点的高度时,根据高度的代码,其实它的子树的高度都被计算了一遍,这就说明,高度被重复计算了,况且,在求根节点的高度时,我们其实已经知道当前树的子树是不是平衡二叉树了. class Solution {public int maxDepth(TreeNode root){if(root null){return 0;}int leftH maxDepth(root.left);int rightH maxDepth(root.right);if(leftH0 rightH0 Math.abs(leftH-rightH)1){return Math.max(leftH,rightH)1;}else{return -1;}}public boolean isBalanced(TreeNode root) {if(root null){return true;}return maxDepth(root)0;}
} 上述代码在求根节点高度的过程中就实现了对其子树是否是平衡二叉树的判断,整个过程只需要对整棵树遍历一次.时间复杂度达到了O(N). 题5:对称二叉树 class Solution {public boolean isSymmetric(TreeNode root) {if(root null) return true;return isSymmetricChild(root.left,root.right);}private boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree){if((leftTree null rightTree ! null) || (leftTree ! null rightTree null)){return false;}if(leftTreenull rightTree null){return true;}if(leftTree.val ! rightTree.val){return false;}return isSymmetricChild(leftTree.left,rightTree.right) isSymmetricChild(leftTree.right,rightTree.left);}
} 题6:二叉树的分层遍历 class Solution {public ListListInteger levelOrder(TreeNode root) {ListListInteger list new ArrayList();if(root null){return list;}QueueTreeNode qu new LinkedList();qu.offer(root);while(!qu.isEmpty()){int size qu.size();ListInteger list2 new ArrayList(); while(size 0){TreeNode cur qu.poll();list2.add(cur.val);size--;if(cur.left ! null){qu.offer(cur.left);}if(cur.right ! null){qu.offer(cur.right);}}list.add(list2);}return list;}
} 题7:二叉树遍历 import java.util.Scanner;
class TreeNode {public char val;public TreeNode left;//存储左孩子的引用public TreeNode right;//存储右孩子的引用public TreeNode(char val) {this.val val;}
}
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseString str in.nextLine();TreeNode root createTree(str);inorder(root);}}private static void inorder(TreeNode root){if(root null){return;}inorder(root.left);System.out.print(root.val );inorder(root.right);}public static int i 0;private static TreeNode createTree(String str){TreeNode root null;if(str.charAt(i)!#){root new TreeNode(str.charAt(i));i;root.left createTree(str);root.right createTree(str);}else{i;}return root;}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88905.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!