数据结构与算法-10高级数据结构_树论(树论基础)

avatar
作者
猴君
阅读量:0

树论基础&二叉树

1 什么是树

概念

  • 数据结构中的“树”(Tree)是一种非常重要的非线性数据结构,它模拟了具有树状结构特点的数据集合。在树形结构中,每个元素被称为一个节点(Node),节点之间通过特定的关系连接,这些关系通常被描述为“父子”关系。

  • 树是由n(n≥0)个有限节点组成一个具有层次关系的集合。它有一个特殊的节点,称为根节点(Root Node),其余节点分成m(m≥0)个互不相交的有限集T1, T2, …, Tm,其中每一个子集Ti(1≤i≤m)又是一棵符合本定义的树,称为根的子树(Subtree)

特性

  1. 层次性:树中的节点按照层次组织,根节点位于最顶层,叶子节点位于最底层。
  2. 无环性:在树中,除了根节点外,每个节点有且仅有一个父节点;没有节点是其自身的祖先或后代。
  3. 子树不相交性:任意两个子树的节点之间没有交集。

2 重要术语

  1. 节点(Node)
    • 树的每个元素都是一个节点。
    • 节点可能包含一个值或一组值,以及指向其子节点的链接。
  2. 根节点(Root Node)
    • 树中唯一没有父节点的节点。
    • 它通常是树的入口点。
  3. 子节点(Child Node)
    • 一个节点可以有零个或多个子节点。
    • 子节点通过边(Edge)与父节点相连。
  4. 父节点(Parent Node)
    • 子节点的上一级节点。
    • 除了根节点外,每个节点都有一个父节点。
  5. 兄弟节点(Sibling Nodes)
    • 具有相同父节点的节点。
  6. 叶子节点(Leaf Node)
    • 没有子节点的节点。
    • 它们位于树的最低层
  7. (Degree)
    • 一个节点的子节点数。
    • 叶子节点的度为0。
    • 示例:在二叉树中,每个节点最多有两个子节点(一个左子节点和一个右子节点),因此二叉树中节点的度最大为2。但在一般的树(也称为N叉树)中,节点的度可以大于2,具体取决于树的定义和上下文。
  8. 树的度(Degree of a Tree)
    • 树中所有节点的度的最大值。
  9. 层次(Level)
    • 从根节点开始,根节点为第1层,它的子节点为第2层,依此类推。
  10. 深度(Depth)或高度(Height)
    • 树中节点的最大层次数。
    • 根节点的深度为0,其直接子节点的深度为1,依此类推。
  11. 路径(Path)
    • 从一个节点到另一个节点所经过的节点序列。
    • 路径长度是路径上的节点数减一。
  12. 森林(Forest)
    • 一个或多个互不相交的树的集合。
  13. 结点的高度:结点到叶子结点的最长路径
  14. 结点的深度:根结点到该结点的边个数
  15. 结点的层数:结点的深度加1
  16. 树的高度:根结点的高度

3 不同的树

  1. 二叉树:每个节点最多有两个子节点的树。
    1. 每个节点最多有两个子节点,通常称为左子节点和右子节点。
    2. 子树之间不能相交。
    3. 除了根节点外,每个节点有且仅有一个父节点。
    4. 一颗N个结点的树有N-1条边。
    5. 一个节点的子树的个数称为节点的度,普通二叉树中节点的度最大为2。
  2. 二叉搜索树(BST):二叉树的一种特殊形式,其中对于树中的每个节点,其左子树上所有节点的值都小于它的值,而右子树上所有节点的值都大于它的值。
  3. 平衡二叉树:一种特殊的二叉搜索树,其中任意节点的两个子树的高度差最多为1。常见的平衡二叉树有AVL树和红黑树。
  4. 完全二叉树:除最后一层外,每一层上的节点数均达到最大值;在最后一层上只缺少右边的若干节点。
    1. 编号性质:对于深度为h的完全二叉树,它的节点从1到2^h-1依次编号。其中,对于任意节点i,如果它的编号为i,则它的左子节点编号为2i,右子节点编号为2i+1。
    2. 父子关系:对于任意节点i,如果它的编号为i,则它的父节点编号为i/2(向下取整)。
    3. 高度:完全二叉树的高度为log(n+1)(以2为底),其中n为节点数。
    4. 存储方式:完全二叉树可以使用数组来存储,从而实现快速的访问和修改。
  5. 满二叉树:除叶子结点外,每个结点都有左右两个子结点。
    1. 每一层的节点数都达到了最大值。
    2. 节点要么是叶子节点(没有子节点),要么是度为2的节点(有两个子节点)。
  6. N叉树:每个节点可以有N个子节点的树,其中N是一个大于1的整数。
  7. B树和B+树:用于数据库和文件系统的平衡多路搜索树,它们允许每个节点有多个子节点和关键字,用于高效地插入、删除和搜索数据。
  8. 堆(Heap):一种特殊的树形数据结构,通常用于实现优先队列。堆是一种完全二叉树,它满足堆的性质:父节点的值总是大于或等于(大顶堆)或小于或等于(小顶堆)其子节点的值。

4 二叉树的遍历

4.1 前序遍历

前序遍历顺序:根节点、左节点、右节点

/** * 前序遍历 * @param node */ public void preOrder(MyBinaryTreeNode<T> node){     print(node);     if (node.left != null){         preOrder(node.left);     }     if (node.right != null){         preOrder(node.right);     } } 
4.2 中序遍历

中序遍历顺序:左节点、跟节点、右节点

/** * 中序遍历 */ public void middleOrder(MyBinaryTreeNode<T> node){     if (node == null){         return;     }     if (node.left != null){         middleOrder(node.left);     }     print(node);     if (node.right != null){         middleOrder(node.right);     } } 
4.3 后续遍历

后续遍历顺序:左节点、右节点、根节点

/**  * 后续遍历 */ public void postOrder(MyBinaryTreeNode<T> node){     if (node == null){         return;     }     if (node.left != null){         postOrder(node.left);     }     if (node.right != null){         postOrder(node.right);     }     print(node); } 
4.4 层次遍历

层次遍历:也叫横向遍历

/** * 层级遍历 */ public void transverseSort(MyBinaryTreeNode<T> node){     if (node == null){         return;     }     print(node);     ArrayQueue<MyBinaryTreeNode<T>> queue = new ArrayQueue<>(10);     queue.add(node);     while (!queue.isEmpty()){         MyBinaryTreeNode<T> remove = queue.remove(0);         if (remove.left != null){             print(remove.left);             queue.add(remove.left);         }         if (remove.right != null){             print(remove.right);             queue.add(remove.right);         }     } } 
4.5 完整代码
package cn.zxc.demo.leetcode_demo.advanced_data_structure;  import com.sun.jmx.remote.internal.ArrayQueue;  /**  * 二叉树  *              A  *            /   \  *           B     E  *            \     \  *            C      F  *           /      /  *          D      G  *               /  \  *              H    K  * 前序遍历:  * A B C D E F G H K  * 中序遍历:  * B D C A E H G K F  * 后序遍历:  * D C B H K G F E A  * 层级遍历:  * A B E C F D G H K  */ public class MyBinaryTreeDemo<T> {       /**      * 前序遍历      * @param node      */     public void preOrder(MyBinaryTreeNode<T> node){         print(node);         if (node.left != null){             preOrder(node.left);         }         if (node.right != null){             preOrder(node.right);         }     }      /**      * 中序遍历      */     public void middleOrder(MyBinaryTreeNode<T> node){         if (node == null){             return;         }         if (node.left != null){             middleOrder(node.left);         }         print(node);         if (node.right != null){             middleOrder(node.right);         }     }      /**      * 后续遍历      */     public void postOrder(MyBinaryTreeNode<T> node){         if (node == null){             return;         }         if (node.left != null){             postOrder(node.left);         }         if (node.right != null){             postOrder(node.right);         }         print(node);     }      /**      * 层级遍历      */     public void transverseSort(MyBinaryTreeNode<T> node){         if (node == null){             return;         }         print(node);         ArrayQueue<MyBinaryTreeNode<T>> queue = new ArrayQueue<>(10);         queue.add(node);         while (!queue.isEmpty()){             MyBinaryTreeNode<T> remove = queue.remove(0);             if (remove.left != null){                 print(remove.left);                 queue.add(remove.left);             }             if (remove.right != null){                 print(remove.right);                 queue.add(remove.right);             }         }     }      /**      * 打印      * @param node      */     public void print(MyBinaryTreeNode<T> node){         if(node == null){             return;         }         System.out.print(node.data + " ");     }      public static void main(String[] args) {         MyBinaryTreeNode<String> D = new MyBinaryTreeNode<String>("D", null, null);         MyBinaryTreeNode<String> H = new MyBinaryTreeNode<String>("H", null, null);         MyBinaryTreeNode<String> K = new MyBinaryTreeNode<String>("K", null, null);         MyBinaryTreeNode<String> C = new MyBinaryTreeNode<String>("C", D, null);         MyBinaryTreeNode<String> G = new MyBinaryTreeNode<String>("G", H, K);         MyBinaryTreeNode<String> B = new MyBinaryTreeNode<String>("B", null, C);         MyBinaryTreeNode<String> F = new MyBinaryTreeNode<String>("F", G, null);         MyBinaryTreeNode<String> E = new MyBinaryTreeNode<String>("E", null, F);         MyBinaryTreeNode<String> A = new MyBinaryTreeNode<String>("A", B, E);         MyBinaryTreeDemo<String> myBinaryTreeDemo = new MyBinaryTreeDemo<>();         System.out.println("前序遍历:");         myBinaryTreeDemo.preOrder(A); // A B C D E F G H K         System.out.println();         System.out.println("中序遍历:"); // B D C A E H G K F         myBinaryTreeDemo.middleOrder(A);         System.out.println();         System.out.println("后序遍历:"); // D C B H K G F E A         myBinaryTreeDemo.postOrder(A);         System.out.println();         System.out.println("层级遍历:");         myBinaryTreeDemo.transverseSort(A);         System.out.println();     } } class MyBinaryTreeNode<T> {     T data;     MyBinaryTreeNode<T> left;     MyBinaryTreeNode<T> right;     public MyBinaryTreeNode(T data) {         this.data = data;     }     public MyBinaryTreeNode(T data, MyBinaryTreeNode<T> left, MyBinaryTreeNode<T> right) {         this.data = data;         this.left = left;         this.right = right;     }      public T getData() {         return data;     }      public void setData(T data) {         this.data = data;     }      public MyBinaryTreeNode<T> getLeft() {         return left;     }      public void setLeft(MyBinaryTreeNode<T> left) {         this.left = left;     }      public MyBinaryTreeNode<T> getRight() {         return right;     }      public void setRight(MyBinaryTreeNode<T> right) {         this.right = right;     } }  

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!