赞
踩
目录
树是一种非线性数据结构,它由节点和边组成。树的每个节点可以有零个或多个子节点,其中一个节点被指定为根节点。树的节点之间通过边连接。另外,树形结构中,子树之间不能有交集,否则就不是树形结构。
树的结构具有层级关系,根节点位于最顶层,而叶节点位于最底层。树的形状可以类比于现实生活中的树,根节点相当于树的根部,而分支和叶子节点则相当于树的枝干和叶子。
在计算机科学中,树被广泛用于各种应用,例如文件系统、数据库索引、编译器中的抽象语法树等。树的常见特点是具有唯一的根节点、没有循环的边、可以有任意数量的子节点等。
树的常见操作包括插入新节点、删除节点、查找节点、遍历节点等。常见的树结构包括二叉树、红黑树、AVL树等。树的设计和使用在算法和数据结构领域中非常重要,它可以提供高效的数据存储和检索方式。
笔者就以下图作为例子进行说明:
二叉树是一种常见的树状数据结构,在二叉树中,每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树的特点是每个节点最多只有两个子节点,且子节点的位置是有序的,即左子节点在右子节点之前。
二叉树可以为空,如果一个二叉树不为空,则它一定由根节点、左子树和右子树组成。每个节点都有一个值,可以是任意类型的数据。
二叉树也可以只有一个节点,如下图所示,根节点不为空,但是左子树和右子树为空,这样的二叉树也是允许存在的
总的来说,对于任意一颗二叉树,它都是由以下几部分复合而成的:
二叉树可以用来表示许多实际问题,例如计算机科学中的排序和搜索算法。在二叉树中,有一些特殊的类型,如满二叉树、完全二叉树和平衡二叉树等。二叉树还可以通过遍历算法来访问其中的节点,最常见的遍历算法有前序遍历、中序遍历和后序遍历。
二叉树中还有以下俩个常见的特殊的二叉树
一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵二叉树的层数为 k ,且结点总数是 ,则它就是满二叉树。
完全二叉树是由满二叉树而引出来的,对于深度为 k 的,有 n 个结点的二叉树,当且仅当其每一个结点都与深度为 k 的满二叉树中编号从0至n-1的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树
对于任意一个节点,我们最多只能知道它的左右孩子节点和根节点,以及自己保存的数据,由此我们引申出许多种表示二叉树的方法,常见的有孩子表示法,孩子双亲表示法,兄弟节点表示法...
- // 孩子表示法
- class Node {
- int val; // 数据域
- Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
- Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
- }
-
- // 孩子双亲表示法
- class Node {
- int val; // 数据域
- Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
- Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
- Node parent; // 当前节点的根节点
- }
笔者以下图举例:
我们使用孩子表示法,然后依次按照图示组成一颗二叉树(后文的遍历都是基于此树)
- public class MyBinaryTree {
- public class TreeNode {
- public char val;//记录当前节点的值
- public TreeNode leftNode;//记录当前节点的左孩子节点
- public TreeNode rightNode;//记录当前节点的右孩子节点
- public TreeNode(char val) {//初始化节点的值
- this.val = val;
- }
- }
- //生成每一个节点,然后连起来
- public TreeNode CreatTree() {
- 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.leftNode = B;
- A.rightNode = C;
- B.leftNode = D;
- C.leftNode = E;
- C.rightNode = F;
- //最后返回根节点
- return A;
- }
- }
二叉树的遍历是指按照一定的规则,将二叉树中的所有节点访问一次,并且每个节点只访问一次。常见的二叉树遍历方式有前序遍历、中序遍历和后序遍历。
前序遍历(preorder traversal):先访问根节点,然后遍历左子树,最后遍历右子树。具体步骤如下:
代码实现如下:
- //前序遍历
- public void preOrder(TreeNode root) {
- if (root == null) {
- return;//空树不需要遍历
- }
- System.out.print(root.val + " ");//访问根节点
- preOrder(root.leftNode);//前序遍历左子树
- preOrder(root.rightNode);//前序遍历右子树
- }
对于上述的代码,程序运行起来的具体逻辑是如下图这样的,反复的递归和回退进行实现
中序遍历(inorder traversal):先遍历左子树,然后访问根节点,最后遍历右子树。具体步骤如下:
代码实现如下:
- //中序遍历
- public void inOrder(TreeNode root) {
- if (root == null) {
- return;//空树不需要遍历
- }
- inOrder(root.leftNode);//中序遍历左子树
- System.out.print(root.val + " ");//访问根节点
- inOrder(root.rightNode);//中序遍历右子树
- }
后序遍历(postorder traversal):先遍历左子树,然后遍历右子树,最后访问根节点。具体步骤如下:
代码实现如下:
- //后序遍历
- public void postOrder(TreeNode root) {
- if (root == null) {
- return;//空树不需要遍历
- }
- postOrder(root.leftNode);//后序遍历左子树
- postOrder(root.rightNode);//后序遍历右子树
- System.out.print(root.val + " ");//访问根节点
- }
我们可以写个测试来看看遍历的结果:
- public class Test {
- public static void main(String[] args) {
- MyBinaryTree myBinaryTree = new MyBinaryTree();
- MyBinaryTree.TreeNode rootNode = myBinaryTree.CreatTree();
-
- System.out.println();
- System.out.println("前序遍历:");
- myBinaryTree.preOrder(rootNode);
-
- System.out.println();
- System.out.println("中序遍历:");
- myBinaryTree.inOrder(rootNode);
-
- System.out.println();
- System.out.println("后序遍历:");
- myBinaryTree.postOrder(rootNode);
- }
- }
输出:
也就是说:
其实不管是前序,中序,后序遍历,他们整体的搜索过程都是一样的,不同的地方在于对当前根节点的处理时间不一样:前序遍历是先处理根节点;中序遍历是先遍历当前节点的左子树再处理当前根节点;而后序遍历则是最后再处理根节点,就像下图一样
以上是三种最基本的二叉树遍历方式。除了这三种,还有一些其他的二叉树遍历方式,比如层序遍历、螺旋遍历等。不同的遍历方式适用于不同的场景和问题,可以根据具体的需求选择合适的遍历方式。
本次的分享就到此为止了,希望我的分享能给您带来帮助,也欢迎大家三连支持,你们的点赞就是博主更新最大的动力!如有不同意见,欢迎评论区积极讨论交流,让我们一起学习进步!有相关问题也可以私信博主,评论区和私信都会认真查看的,我们下次再见
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。