好好学数据结构-二叉树的遍历

181 阅读2分钟

这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战

二叉树的遍历

面试之前,对实现中序、后序和前序遍历,你要做到轻车熟路,其中在面试中最常见的是中序遍历。

中序遍历

中序遍历是指先访问(通常也会打印)左子树,然后访问当前节点,最后访问右子树。

1.   void inOrderTraversal(TreeNode node) {
2.     if (node != null) {
3.       inOrderTraversal(node.left);
4.       visit(node);
5.       inOrderTraversal(node.right);
6.     }
7.   }

当在二叉搜索树上执行遍历时,它以升序访问节点。因此命名为“中序遍历”。

前序遍历

前序遍历先访问当前节点,再访问其子节点。因此命名为“前序遍历”。

1.   void preOrderTraversal(TreeNode node) {
2.     if (node != null) {
3.       visit(node);
4.       preOrderTraversal(node.left);
5.       preOrderTraversal(node.right);
6.     }
7.   }

前序遍历中,根节点永远第一个被访问。

后序遍历

后序遍历于访问子节点之后访问当前节点。因此命名为“后序遍历”。

1.   void postOrderTraversal(TreeNode node) {
2.     if (node != null) {
3.       postOrderTraversal(node.left);
4.       postOrderTraversal(node.right);
5.       visit(node);
6.     }
7.   }

后序遍历中,根节点永远最后一个被访问。

二叉堆(小顶堆与大顶堆)

本书只讨论小顶堆。大顶堆实际上是一样的,只是其元素是以降序排列而不是升序排列的。

一个小顶堆是一棵完整二叉树(也就是说,除了底层最右边的元素,树的每层都被填满了),其中每个节点都小于其子节点。因此,根是树中的最小元素。

在最小堆中有两个关键操作:insertextract_min

插入操作

当我们向一个最小堆插入元素时,总是从底部开始。从最右边的节点开始插入操作以保持树的完整性。

然后,通过与其祖先节点进行交换来“修复”树,直到找到新元素的适当位置。我们基本上是在向上传递最小的元素。

此操作时间复杂度为O(\log n),其中n是堆中节点的个数。

提取最小元素

找到小顶堆的最小元素是小菜一碟:它总是在顶部。颇为棘手的是如何删除该元素(其实也不是那么棘手)。

首先,删除最小元素并将其与堆中的最后一个元素(位于最底层、最右边的元素)进行交换。然后,向下传递这个元素,不断使其与自身子节点之一进行交换,直到小顶堆的属性得以恢复。

是和左边的孩子节点还是右边的孩子节点进行交换取决于它们的值。左右元素之间没有固定的顺序,但是为了保持小顶堆的元素有序,你需要选择两者中较小的元素。

该算法的时间复杂度同样为O(\log n)