C++策略技术:编译期多态与高性能组件设计
2026/8/29 8:03:07
树的概念
树是⼀种非线性的数据结构,它是由n(n>=0)个有限结点组成⼀个具有层次关系的集合
相关概念
二叉树
二叉树的模拟实现
packageDataStructure.DS_BinaryTree;publicinterfaceITree{/** * 判断是否为完全二叉树 * @param root 根节点 * @return true 完全二叉树 */booleanisCompleteBinaryTree(TreeNoderoot);/** * 根据值查找节点 * @param root 根 * @param val 待查找值 * @return 找到的TreeNode,null未找到 */TreeNodefind(TreeNoderoot,intval);/** * 获取树高度 * @param root 根 * @return 高度 */intgetHeight(TreeNoderoot);/** * 获取第k层节点数量 * @param root 根 * @param k 层数,从1开始 * @return 节点数 */intgetKLevelNodeCount(TreeNoderoot,intk);/** * 获取叶子结点个数 * @param root 根 * @return 叶子数量 */intgetLeafNodeCount(TreeNoderoot);/** * 二叉树总节点个数 * @param root 根 * @return 总节点数 */intsize(TreeNoderoot);/** * 先序遍历 * @param root 根 */voidpreOrderTraverse(TreeNoderoot);/** * 中序遍历 * @param root 根 */voidinOrderTraverse(TreeNoderoot);/** * 后序遍历 * @param root 根 */voidpostOrderTraverse(TreeNoderoot);/** * 层序遍历 * @param root 根 */voidlevelOrderTraverse(TreeNoderoot);}前序遍历
/** * 先序遍历:根 -> 左 -> 右 * 递归实现,直接打印节点数据 * @param root 根节点 */publicvoidpreOrderTraverse(TreeNoderoot){if(root==null)return;System.out.print(root.data+" ");preOrderTraverse(root.lchild);preOrderTraverse(root.rchild);}中序遍历
/** * 中序遍历:左 -> 根 -> 右 * 递归实现,直接打印节点数据 * @param root 根节点 */publicvoidinOrderTraverse(TreeNoderoot){if(root==null)return;inOrderTraverse(root.lchild);System.out.print(root.data+" ");inOrderTraverse(root.rchild);}后序遍历
/** * 后序遍历:左 -> 右 -> 根 * 递归实现,直接打印节点数据 * @param root 根节点 */publicvoidpostOrderTraverse(TreeNoderoot){if(root==null)return;postOrderTraverse(root.lchild);postOrderTraverse(root.rchild);System.out.print(root.data+" ");}层序遍历
/** * 层序遍历(广度优先遍历) * 使用队列完成,从上到下,同一层从左到右打印 * @param root 根节点 */publicvoidlevelOrderTraverse(TreeNoderoot){if(root==null)return;Queue<TreeNode>queue=newLinkedList<>();queue.offer(root);while(!queue.isEmpty()){TreeNodecur=queue.poll();System.out.print(cur.data+" ");// 左孩子不为空入队if(cur.lchild!=null)queue.offer(cur.lchild);// 右孩子不为空入队if(cur.rchild!=null)queue.offer(cur.rchild);}}获取树中节点的个数
/** * 统计二叉树结点总个数 * @param root 根节点 * @return 全部节点数量,空树返回0 */publicintsize(TreeNoderoot){if(root==null)return0;// 当前节点1个 + 左子树节点数 + 右子树节点数return1+size(root.lchild)+size(root.rchild);}获取叶⼦节点的个数
/** * 获取叶子结点的个数 * 叶子节点:左右孩子都为null的节点 * @param root 根节点 * @return 叶子节点总数,空树返回0 */publicintgetLeafNodeCount(TreeNoderoot){if(root==null)return0;// 当前是叶子节点,计数+1if(root.lchild==null&&root.rchild==null)return1;// 左子树叶子 + 右子树叶子returngetLeafNodeCount(root.lchild)+getLeafNodeCount(root.rchild);}获取第K层节点的个数
/** * 获取第K层的节点个数,层数从1开始 * @param root 根节点 * @param k 目标层数,k>=1 * @return 第k层节点数量,root为null或k非法返回0 */publicintgetKLevelNodeCount(TreeNoderoot,intk){// 树为空 或者层数不合法直接返回0if(root==null||k<=0)return0;// k=1代表当前就是目标层,节点数为1if(k==1)return1;// 左子树k-1层 + 右子树k-1层节点之和returngetKLevelNodeCount(root.lchild,k-1)+getKLevelNodeCount(root.rchild,k-1);}获取⼆叉树的⾼度
/** * 获取二叉树的高度(深度) * 递归:当前树高度 = max(左子树高度,右子树高度) + 1 * @param root 根节点 * @return 树的高度,空树返回0 */publicintgetHeight(TreeNoderoot){if(root==null)return0;intleftHeight=getHeight(root.lchild);intrightHeight=getHeight(root.rchild);returnMath.max(leftHeight,rightHeight)+1;}检测值为value的元素是否存在
/** * 在二叉树中查找值为val的节点 * 先序递归遍历查找 * @param root 根节点 * @param val 需要查找的目标数值 * @return 找到返回对应TreeNode,找不到返回null */publicTreeNodefind(TreeNoderoot,intval){// 递归终止条件:当前节点为空if(root==null)returnnull;// 当前节点就是目标节点,直接返回if(root.data==val)returnroot;// 递归查找左子树TreeNodeleft=find(root.lchild,val);// 左子树找到,直接返回if(left!=null)returnleft;// 左子树没找到,去右子树查找returnfind(root.rchild,val);}判断⼀棵树是不是完全⼆叉树
/** * 判断一棵树是否为完全二叉树 * 思路:层序遍历,遇到null节点后,后续不能再出现非null节点 * @param root 二叉树根节点 * @return true:是完全二叉树;false:不是完全二叉树 */publicbooleanisCompleteBinaryTree(TreeNoderoot){// 空树认为是完全二叉树if(root==null)returntrue;Queue<TreeNode>que=newLinkedList<>();que.offer(root);// 标记是否已经遇到空节点booleanflag=false;while(!que.isEmpty()){TreeNodenode=que.poll();if(node==null){// 遇到空节点,置标记为trueflag=true;}else{// 如果之前已经遇到过null,现在又出现非空节点,说明不是完全二叉树if(flag)returnfalse;// 无论孩子是否为null,全部入队que.offer(node.lchild);que.offer(node.rchild);}}returntrue;}二叉树模拟实现完整代码
packageDataStructure.DS_BinaryTree;importjava.util.LinkedList;importjava.util.Queue;/** * 二叉树基础实现类 * 提供二叉树遍历、统计节点、高度、查找、判断完全二叉树等基础功能 */publicclassMyBinaryTree{/** * 判断一棵树是否为完全二叉树 * 思路:层序遍历,遇到null节点后,后续不能再出现非null节点 * @param root 二叉树根节点 * @return true:是完全二叉树;false:不是完全二叉树 */publicbooleanisCompleteBinaryTree(TreeNoderoot){// 空树认为是完全二叉树if(root==null)returntrue;Queue<TreeNode>que=newLinkedList<>();que.offer(root);// 标记是否已经遇到空节点booleanflag=false;while(!que.isEmpty()){TreeNodenode=que.poll();if(node==null){// 遇到空节点,置标记为trueflag=true;}else{// 如果之前已经遇到过null,现在又出现非空节点,说明不是完全二叉树if(flag)returnfalse;// 无论孩子是否为null,全部入队que.offer(node.lchild);que.offer(node.rchild);}}returntrue;}/** * 在二叉树中查找值为val的节点 * 先序递归遍历查找 * @param root 根节点 * @param val 需要查找的目标数值 * @return 找到返回对应TreeNode,找不到返回null */publicTreeNodefind(TreeNoderoot,intval){// 递归终止条件:当前节点为空if(root==null)returnnull;// 当前节点就是目标节点,直接返回if(root.data==val)returnroot;// 递归查找左子树TreeNodeleft=find(root.lchild,val);// 左子树找到,直接返回if(left!=null)returnleft;// 左子树没找到,去右子树查找returnfind(root.rchild,val);}/** * 获取二叉树的高度(深度) * 递归:当前树高度 = max(左子树高度,右子树高度) + 1 * @param root 根节点 * @return 树的高度,空树返回0 */publicintgetHeight(TreeNoderoot){if(root==null)return0;intleftHeight=getHeight(root.lchild);intrightHeight=getHeight(root.rchild);returnMath.max(leftHeight,rightHeight)+1;}/** * 获取第K层的节点个数,层数从1开始 * @param root 根节点 * @param k 目标层数,k>=1 * @return 第k层节点数量,root为null或k非法返回0 */publicintgetKLevelNodeCount(TreeNoderoot,intk){// 树为空 或者层数不合法直接返回0if(root==null||k<=0)return0;// k=1代表当前就是目标层,节点数为1if(k==1)return1;// 左子树k-1层 + 右子树k-1层节点之和returngetKLevelNodeCount(root.lchild,k-1)+getKLevelNodeCount(root.rchild,k-1);}/** * 获取叶子结点的个数 * 叶子节点:左右孩子都为null的节点 * @param root 根节点 * @return 叶子节点总数,空树返回0 */publicintgetLeafNodeCount(TreeNoderoot){if(root==null)return0;// 当前是叶子节点,计数+1if(root.lchild==null&&root.rchild==null)return1;// 左子树叶子 + 右子树叶子returngetLeafNodeCount(root.lchild)+getLeafNodeCount(root.rchild);}/** * 统计二叉树结点总个数 * @param root 根节点 * @return 全部节点数量,空树返回0 */publicintsize(TreeNoderoot){if(root==null)return0;// 当前节点1个 + 左子树节点数 + 右子树节点数return1+size(root.lchild)+size(root.rchild);}/** * 先序遍历:根 -> 左 -> 右 * 递归实现,直接打印节点数据 * @param root 根节点 */publicvoidpreOrderTraverse(TreeNoderoot){if(root==null)return;System.out.print(root.data+" ");preOrderTraverse(root.lchild);preOrderTraverse(root.rchild);}/** * 中序遍历:左 -> 根 -> 右 * 递归实现,直接打印节点数据 * @param root 根节点 */publicvoidinOrderTraverse(TreeNoderoot){if(root==null)return;inOrderTraverse(root.lchild);System.out.print(root.data+" ");inOrderTraverse(root.rchild);}/** * 后序遍历:左 -> 右 -> 根 * 递归实现,直接打印节点数据 * @param root 根节点 */publicvoidpostOrderTraverse(TreeNoderoot){if(root==null)return;postOrderTraverse(root.lchild);postOrderTraverse(root.rchild);System.out.print(root.data+" ");}/** * 层序遍历(广度优先遍历) * 使用队列完成,从上到下,同一层从左到右打印 * @param root 根节点 */publicvoidlevelOrderTraverse(TreeNoderoot){if(root==null)return;Queue<TreeNode>queue=newLinkedList<>();queue.offer(root);while(!queue.isEmpty()){TreeNodecur=queue.poll();System.out.print(cur.data+" ");// 左孩子不为空入队if(cur.lchild!=null)queue.offer(cur.lchild);// 右孩子不为空入队if(cur.rchild!=null)queue.offer(cur.rchild);}}}