算法与数据结构(六)二叉树基础篇

共 1598字,需浏览 4分钟

 ·

2022-03-16 21:51

不同于数组、队列等线性表的数据结构,树是一种非线性结构。除了树之外,图也是一种非线性结构。

二叉树如下所示。

节点和边

在树中由节点和连接节点的边组成,二叉树最多有两个子节点。关于节点有几个概念:

1.父节点:节点 1 为节点 2 和 3 的父节点;2.子节点:节点 4 和 5 为节点 2 的子节点;3.兄弟节点:节点 2 和 3 为兄弟节点;4.叶子节点:没有子节点的节点为叶子节点,如节点 4 和 5;5.根节点:没有父节点的节点为根节点,如节点 1。

关于树的层级有如下几个概念:

1.节点的高度:该节点到叶子节点的最长路径,即边数;2.节点的深度:根节点到该节点经历的边数;3.节点的层数:深度 + 1;4.树的高度:等于根节点的高度。

以下图为例,可以帮助理解节点高度、深度、层的概念。

特殊的二叉树

如果一个二叉树叶子节点都在同一层级,而且除了叶子节点每个节点都有两个子节点,这种二叉树叫做满二叉树。上文中的图例即为满二叉树。

如果一个二叉树,最后一层的叶子节点都在左侧,其他层的节点数量达到最大,这种二叉树叫做完全二叉树。上文图中我们把节点 7 去掉,就符合满二叉树的条件。

二叉树的存储

二叉树的存储也离不开最基础的数据结构:

数组链表

对于数组存储,我们可以使用以下规则约定每个节点在数组中存储的位置。

1.假设父节点存储索引为 i;2.该节点左子节点的位置为 2 * i,右子节点为 2 * i + 1;3.根节点存储在 1 号位。

下图可以帮助理解二叉树数组存储的方式。可以看到,完全二叉树使用数组存储能够充分利用数组空间。非完全二叉树则会导致数组空间的浪费。

对于链表存储,我们使用如下结构进行构建二叉树。

class Node {    Node leftChild;    Node rightChild;}

二叉树的遍历

树和图的遍历分为两种:

1.深度优先遍历:如果存在层级更深的子节点,优先遍历该节点,否则遍历同层级的其他节点;2.广度优先遍历:如果存在同层级的兄弟节点,优先遍历兄弟节点,否则遍历子节点。

对于树的深度优先遍历,又分为三种:

1.前序遍历:访问当前节点——访问左子树——访问右子树;2.中序遍历:访问左子树——访问当前节点——访问右子树;3.后序遍历:访问左子树——访问右子树——访问当前节点。

仍以下图为例,其遍历序列分别如下:

1.前序遍历:1, 2, 4, 5, 3, 6, 7;2.中序遍历:4, 2, 5, 1, 6, 3, 7;3.后序遍历:4, 5, 2, 6, 7, 3, 1。

三种遍历的递归代码如下。

void preOrder(Node root) {  if (root == null) return;
print(root) preOrder(root.left); preOrder(root.right);}
void inOrder(Node root) { if (root == null) return;
inOrder(root.left); print(root) inOrder(root.right);}
void postOrder(Node root) { if (root == null) return;
postOrder(root.left); postOrder(root.right); print(root)}

总结

本次我们了解了二叉树的基础知识,有二叉树的特征、二叉树的数组和链表存储方式、二叉树的遍历。有时间我们聊聊二叉树的应用,它是如何优化搜索算法复杂度的。


浏览 44
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报