树型结构及二叉树(重点)

it2023-02-17  87

树形结构:树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 特点:有一个特殊的节点,称为根节点,根节点没有前驱节点 除根节点外,其余节点被分成M(M > 0)个互不相交的集合T1、T2、…、Tm,其中每一个集合 Ti (1 <= i<= m) 又是一棵与树类似的子树。每棵子树的根节点有且只有一个前驱,可以有0个或多个后继,树是递归定义的。 节点的度:一个节点含有的子树的个数称为该节点的度。 树的度:一棵树中,最大的节点的度称为树的度; 叶子节点或终端节点:度为0的节点称为叶节点; 双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; 根结点:一棵树中,没有双亲结点的结点; 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推; 树的高度或深度:树中节点的最大层次; 二叉树特点:1. 每个结点最多有两棵子树,即二叉树不存在度大于 2 的结点。 2. 二叉树的子树有左右之分,其子树的次序不能颠倒,因此二叉树是有序树。 特殊的二叉树:. . 1**.满二叉树**: 一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果 一个二叉树的层数为K,且结点总数是 ,则它就是满二叉树。 3. 完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。 4. 二叉树的性质:1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有 (i>0)个结点。 2. 若规定只有根节点的二叉树的深度为1,则深度为K的二叉树的最大结点数是 (k>=0) 3. 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1。 4. 具有n个结点的完全二叉树的深度k为 上取整。 5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i 的结点有: 若i>0,双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点 若2i+1<n,左孩子序号:2i+1,否则无左孩子 若2i+2<n,右孩子序号:2i+2,否则无右孩子 二叉树的前序中序后序遍历代码:

public class TreeTraversal { public static void preTraversal(TreeNode root){ if(root!=null){ //前序 System.out.printf("%c",root.v); preTraversal(root.left); preTraversal(root.right); } } public static void inTraversal(TreeNode root){ if(root!=null){ //后序 inTraversal(root.left); System.out.printf("%c",root.v); inTraversal(root.right); } } public static void postTraversal(TreeNode root){ if(root!=null){ //后序 postTraversal(root.left); postTraversal(root.right); System.out.printf("%c",root.v); } } public static void main(String[] args) { TreeNode a=BuildTree.buildTree(); System.out.printf("前序遍历: "); preTraversal(a); System.out.println(); System.out.printf("中序遍历: "); inTraversal(a); System.out.println(); System.out.printf("后序遍历: "); postTraversal(a); System.out.println(); } }

// 遍历思路-求结点个数;void getSize1(Node root); // 子问题思路-求结点个数;int getSize2(Node root); // 遍历思路-求叶子结点个数;void getLeafSize1(Node root); // 子问题思路-求叶子结点个数;int getLeafSize2(Node root); // 子问题思路-求第 k 层结点个数;int getKLevelSize(Node root); // 获取二叉树的高度;int getHeight(Node root); // 查找 val 所在结点;Node find(Node root, int val);

public class SomeMethod { private static int n; public static int sumTreeNodeSize(TreeNode root){ //求树的节点采用遍历思路 n=0; preOrder(root); return n; } public static int sumTreeNodeSize2(TreeNode root){ // 求树的节点采用汇集思路 if(root==null){ return 0; }else{ int nodeRootSize=1; int leftSubNodeSize=sumTreeNodeSize2(root.left); int rightSubNodeSize=sumTreeNodeSize2(root.right); return nodeRootSize+leftSubNodeSize+rightSubNodeSize;//根+左子树+右子树 } } private static void preOrder(TreeNode root) { if(root!=null){ n++; // 遍历这个过程会经过每个节点 preOrder(root.left); preOrder(root.right); } } private static int leafN; private static int sumTreeLeafNodeSize(TreeNode root){ //求树中叶子节点个数采用遍历思路 // 注意,每次计算叶子结点个数之前,都必须归零 leafN = 0; // 2. 使用前序遍历方式,经过每一个结点 preOrder2(root); return leafN; } private static int sumTreeLeafNodeSize2(TreeNode root){//求树中叶子节点个数采用汇集思路 if(root==null){ return 0; // 空树 }else if(root.left==null&&root.right==null){ return 1; //只有一个结点 }else{ // 至少一个以上的结点 // 整棵树的叶子结点个数 = 左子树的叶子节点个数 + 右子树的叶子结点个数 int leftSubTreeLeafSize = sumTreeLeafNodeSize2(root.left); int rightSubTreeLeafSize = sumTreeLeafNodeSize2(root.right); return leftSubTreeLeafSize + rightSubTreeLeafSize; } } private static void preOrder2(TreeNode root) { if(root!=null){ if(root.left==null&&root.right==null){ leafN++; } preOrder2(root.left); preOrder2(root.right); } } public static int sumKLevelNodeSize(TreeNode root, int k){ //求第k层节点个数 if(root==null){ return 0; }else if(k==1){ return 1; }else{ int leftSumK_1=sumKLevelNodeSize(root.left,k-1); int rightSumK_1=sumKLevelNodeSize(root.right,k-1); return leftSumK_1+rightSumK_1; } } public static int getHeight(TreeNode root){ //获取树的高度 if(root==null){ return 0; }else if(root.left==null&&root.right==null){ return 1; }else{ int leftSubTreeHeight = getHeight(root.left); int rightSubTreeHeight = getHeight(root.right); return Math.max(leftSubTreeHeight,rightSubTreeHeight)+1; } } public static boolean contains2(TreeNode root, int v){ //树中是否包含v 思路:三个大思路:一空树 // 二 判断根中节点是否为v if(root==null){ //三 根中节点部位不为v,先判断左树,在判断右树 return false; // 注意 若左树有不用判断右树 } if(root.v==v){ return true; } boolean left = contains2(root.left, v); if (left) { return true; } return contains2(root.right, v); } public static boolean contains1(TreeNode root, int v) { if (root == null) { // 空树 return false; } else { if (root.v == v) { // 根里找到了 // 没必要再去左右子树找了 return true; } else { // 根里没找到 boolean leftSubTreeContains = contains1(root.left, v); if (leftSubTreeContains) { // 左子树里找到了 // 没必要再去右子树里找了 return true; } else { // 左子树里也没找到 boolean rightSubTreeContains = contains1(root.right, v); if (rightSubTreeContains) { // 右子树里找到了 return true; } else { return false; } } } } } public static TreeNode contains4(TreeNode root, int v){ if(root==null){ return null; } if(root.v==v){ return root; } TreeNode leftTreeNode = contains4(root.left, v); if(leftTreeNode!=null){ return leftTreeNode; } return contains4(root.right,v); } public static boolean contains3(TreeNode root, TreeNode node){ if(root==null){ return false; } if(root==node){ return true; } boolean leftTreeNode = contains3(root.left, node); if(leftTreeNode){ return true; } return contains3(root.right, node); } public static void main(String[] args) { TreeNode root=BuildTree.buildTree(); int sum=sumTreeNodeSize2(root); System.out.println(sum); int sumLeaf=sumTreeLeafNodeSize2(root); System.out.println(sumLeaf); int sumK=sumKLevelNodeSize(root,4); System.out.println(sumK); int heightTree=getHeight(root); System.out.println(heightTree); System.out.println(contains2(root,'A')); TreeNode a=contains4(root,'B'); System.out.println(a); } }

二叉树的层序遍历,判断完全二叉树(层序遍历应用) 带层级的层序遍历代码

public class TreeLevelOrder { public static void levelOrderTraversal(TreeNode root){ if(root==null){ return; } //队列元素的元素是树的结点 Queue<TreeNode> queue=new LinkedList<>(); queue.add(root); while (!queue.isEmpty()){ //把树的结点拖入队列在删除时候在托入他的左右孩子 以此循环 TreeNode node = queue.remove(); System.out.println(node.val); if(node.left!=null){ queue.add(node.left); } if(node.right!=null){ queue.add(node.right); } } } public static boolean isCompleteTree(TreeNode root){ Queue<TreeNode> queue=new LinkedList<>(); queue.add(root); while (true){ TreeNode node = queue.remove(); if(node==null){ break; } queue.add(node.left); queue.add(node.right); } while (!queue.isEmpty()){ TreeNode node = queue.remove(); if(node==null){ } else{ return false; } } return true; } static class Nl{ int level; TreeNode node; public Nl(TreeNode node, int level) { this.level = level; this.node = node; } } public static void levelOrderWithLevel(TreeNode root){ if(root==null){ return; } Queue<Nl> queue=new LinkedList<>(); queue.add(new Nl(root,1)); while (!queue.isEmpty()){ Nl nl = queue.remove(); TreeNode node=nl.node; int level= nl.level; System.out.println(level); System.out.println(node.val); if (node.left != null) { queue.add(new Nl(node.left, level + 1)); } if (node.right != null) { queue.add(new Nl(node.right, level + 1)); } } } public static void main(String[] args) { TreeNode root=BuildTree.BuildTree1(); levelOrderTraversal(root); System.out.println(isCompleteTree(root)); levelOrderWithLevel(root); } }

前中后序遍历非递归实现

public class FeiDiGui { public static void preOrder(TreeNode node){ Deque<TreeNode> stack=new LinkedList<>(); TreeNode current=node; while (!stack.isEmpty()||current!=null){ while (current!=null){ System.out.println(current.v); stack.push(current); current=current.left; } TreeNode top = stack.pop(); current=top.right; } } public static void main(String[] args) { TreeNode root=BuildTree.buildTree(); preOrder(root); System.out.println("-------------"); inOrder(root); System.out.println("-------------"); postOrder(root); } public static void inOrder(TreeNode node){ Deque<TreeNode> stack=new LinkedList<>(); TreeNode current=node; while (!stack.isEmpty()||current!=null){ while (current!=null){ stack.push(current); current=current.left; } TreeNode top = stack.pop(); System.out.println(top.v); current=top.right; } } public static void postOrder(TreeNode node){ Deque<TreeNode> stack=new LinkedList<>(); TreeNode current=node; TreeNode last=null; while (!stack.isEmpty()||current!=null){ while (current!=null){ System.out.println(current.v); stack.push(current); current=current.left; } TreeNode top = stack.peek(); if(top.right==null){ stack.pop(); last=top; System.out.println(top.v); } else if (top.right == last) { // 第三次经过 top // 说明从右子树回来 stack.pop(); last = top; System.out.println(top.v); } else { // 第二次经过 top // 说明从左子树回来的 current = top.right; } } } }
最新回复(0)