数据结构复习指导之树、森林

2024-05-12 15:20

本文主要是介绍数据结构复习指导之树、森林,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

树、森林

考纲内容

复习提示

1.树的存储结构

1.1双亲表示法

1.2孩子表示法

1.3孩子兄弟表示法

2.树、森林、与二叉树的转换

2.1树转换为二叉树

2.2森林转换为二叉树

2.3二叉树转换为森林

3.树和森林的遍历

3.1树的遍历

3.2森林的遍历


树、森林

考纲内容

(一)树的基本概念
(二)二叉树
           二叉树的定义及其主要特征;二叉树的顺序存储结构和链式存储结构;
           二叉树的遍历;线索二叉树的基本概念和构造
(三)树、森林
           树的存储结构;森林与二叉树的转换;树和森林的遍历
(四)树与二叉树的应用
           哈夫曼(Huffman)树和哈夫曼编码;并查集及其应用

复习提示

本章内容多以选择题或综合题的形式考查,但统考也会出涉及树遍历相关的算法题。树和二叉树的性质、遍历操作、转换、存储结构和操作特性等,满二叉树、完全二叉树、线索二叉树、哈夫曼树的定义和性质,都是选择题必然会涉及的内容。

1.树的存储结构

树的存储方式有多种,既可采用顺序存储结构,又可采用链式存储结构,但无论采用何种存储方式,都要求能唯一地反映树中各结点之间的逻辑关系,这里介绍3种常用的存储结构。

1.1双亲表示法

这种存储结构采用一组连续空间来存储每个结点,同时在每个结点中增设一个伪指针,指示其双亲结点在数组中的位置。如图5.21所示,根结点下标为0,其伪指针域为-1。

双亲表示法的存储结构描述如下:

#define MAX_TREE_SIZE 100        //树中最多结点数
typedef struct{                  //树的结点定义ElemType data;               //数据元素int parent;                  //双亲位置域
}PTNode ;
typedef struct{                  //树的类型定义PTNode nodes[MAX_TREE_SIZE]; //双亲表示int n;                       //结点数
}PTree;

双亲表示法利用了每个结点(根结点除外)只有唯一双亲的性质,可以很快地得到每个结点的双亲结点,但求结点的孩子时则需要遍历整个结构。

注意:区别树的顺序存储结构与二叉树的顺序存储结构。在树的顺序存储结构中,数组下标代表结点的编号,下标中所存的内容指示了结点之间的关系。而在二叉树的顺序存储结构中,数组下标既代表了结点的编号,又指示了二叉树中各结点之间的关系。当然,二叉树属于树,因此二叉树也可用树的存储结构来存储,但树却不都能用二叉树的存储结构来存储。

1.2孩子表示法

孩子表示法是将每个结点的孩子结点视为一个线性表,且以单链表作为存储结构,则n个结点就有n个孩子链表(叶结点的孩子链表为空表)。而n个头指针又组成一个线性表,为便于查找,可采用顺序存储结构。图5.22(a)是图 5.21(a)中的树的孩子表示法。

与双亲表示法相反,孩子表示法寻找孩子的操作非常方便,而寻找双亲的操作则需要遍历n个结点中孩子链表指针域所指向的n个孩子链表。

1.3孩子兄弟表示法

孩子兄弟表示法又称二叉树表示法,即以二叉链表作为树的存储结构。孩子兄弟表示法使每个结点包括三部分内容:结点值、指向结点第一个孩子结点的指针,以及指向结点下一个兄弟结点的指针(沿此域可以找到结点的所有兄弟结点),如图5.22(b)所示。
孩子兄弟表示法的存储结构描述如下:

typedef struct CsNode{ElemType data;                            //数据域struct CSNode *firstchild,*nextsibling;   //第一个孩子和右兄弟指针
}CSNode,*CsTree;

孩子兄弟表示法比较灵活,其最大的优点是可以方便地实现树转换为二叉树的操作,易于查找结点的孩子等,但缺点是从当前结点査找其双亲结点比较麻烦。若为每个结点增设一个 parent域指向其父结点,则查找结点的父结点也很方便。

2.树、森林、与二叉树的转换

二叉树和树都可以用二叉链表作为存储结构。从物理结构上看,树的孩子兄弟表示法与二叉树的二叉链表表示法是相同的,因此可以用同一存储结构的不同解释将一棵树转换为二叉树。

2.1树转换为二叉树

命题追踪——树和二叉树的转换及相关性质的推理

树转换为二叉树的规则:每个结点的左指针指向它的第一个孩子,右指针指向它在树中的相邻右兄弟,这个规则又称“左孩子右兄弟”。由于根结点没有兄弟,因此树转换得到的二叉树没有右子树,如图 5.23 所示。

树转换为二叉树的画法:

1) 在兄弟结点之间加一连线;

2) 对每个结点,只保留它与第一个孩子的连线,而与其他孩子的连线全部抹掉:

3) 以树根为轴心,顺时针旋转 45°。

2.2森林转换为二叉树

命题追踪——森林和二叉树的转换及相关性质的推理

将森林转换为二叉树的规则与树类似。先将森林中的每棵树转换为二叉树,由于任意一棵树对应的二叉树的右子树必空,若把森林中第二棵树根视为第一棵树根的右兄弟,即将第二棵树对应的二叉树当作第一棵二叉树根的右子树,将第三棵树对应的二叉树当作第二棵二叉树根的右子树,以此类推,就可以将森林转换为二叉树。

森林转换为二叉树的画法:

1) 将森林中的每棵树转换成相应的二叉树;

2) 每棵树的根也可视为兄弟关系,在每棵树的根之间加一根连线:

3) 以第一棵树的根为轴心顺时针旋转 45°。

2.3二叉树转换为森林

命题追踪——由遍历序列构造一棵二叉树并转换为对应的森林

二叉树转换为森林的规则:

若二叉树非空,则二叉树的根及其左子树为第一棵树的二叉树形式,所以将根的右链断开。

二叉树根的右子树又可视为一个由除第一棵树外的森林转换后的二叉树,应用同样的方法,直到最后只剩一棵没有右子树的二叉树为止,最后将每棵二叉树依次转换
成树,就得到了原森林,如图5.24所示。二叉树转换为树或森林是唯一的。

3.树和森林的遍历

3.1树的遍历

命题追踪——树与二叉树遍历方法的对应关系

树的遍历是指用某种方式访问树中的每个结点,且仅访问一次。主要有两种方式:

1) 先根遍历。若树非空,则按如下规则遍历:

  • 先访问根结点。
  • 再依次遍历根结点的每棵子树,遍历子树时仍遵循先根后子树的规则

其遍历序列与这棵树相应二叉树的先序序列相同。

2) 后根遍历。若树非空,则按如下规则遍历:

  • 先依次遍历根结点的每棵子树,遍历子树时仍遵循先子树后根的规则。
  • 再访问根结点。

其遍历序列与这棵树相应二叉树的中序序列相同。

图5.23 的树的先根遍历序列为ABEFCDG,后根遍历序列为 EFBCGDA。

另外,树也有层次遍历,与二叉树的层次遍历思想基本相同,即按层序依次访问各结点。

3.2森林的遍历

按照森林和树相互递归的定义,可得到森林的两种遍历方法。

1) 先序遍历森林。若森林为非空,则按如下规则遍历:

  • 访问森林中第一棵树的根结点。
  • 先序遍历第一棵树中根结点的子树森林。
  • 先序遍历除去第一棵树之后剩余的树构成的森林。

2) 中序遍历森林。森林为非空时,按如下规则遍历:

  • 中序遍历森林中第一棵树的根结点的子树森林。
  • 访问第一棵树的根结点。
  • 中序遍历除去第一棵树之后剩余的树构成的森林。

图5.24的森林的先序遍历序列为ABCDEFGHI,中序遍历序列为 BCDAFEHIG。

命题追踪——森林与二叉树遍历方法的对应关系

当森林转换成二叉树时,其第一棵树的子树森林转换成左子树,剩余树的森林转换成右子树,可知森林的先序和中序遍历即为其对应二叉树的先序和中序遍历。
树和森林的遍历与二叉树的遍历关系见表。

森林二叉树
先根遍历

先序遍历

先序遍历
后根遍历中序遍历中序遍历

注意:部分教材也将森林的中序遍历称为后序遍历,称中序遍历是相对其二叉树而言的,称后序遍历是因为根确实是最后才访问的,若遇到这两种称谓,则可理解为同一种遍历方法。

这篇关于数据结构复习指导之树、森林的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/982995

相关文章

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

理解分类器(linear)为什么可以做语义方向的指导?(解纠缠)

Attribute Manipulation(属性编辑)、disentanglement(解纠缠)常用的两种做法:线性探针和PCA_disentanglement和alignment-CSDN博客 在解纠缠的过程中,有一种非常简单的方法来引导G向某个方向进行生成,然后我们通过向不同的方向进行行走,那么就会得到这个属性上的图像。那么你利用多个方向进行生成,便得到了各种方向的图像,每个方向对应了很多

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

浙大数据结构:树的定义与操作

四种遍历 #include<iostream>#include<queue>using namespace std;typedef struct treenode *BinTree;typedef BinTree position;typedef int ElementType;struct treenode{ElementType data;BinTree left;BinTre

Python 内置的一些数据结构

文章目录 1. 列表 (List)2. 元组 (Tuple)3. 字典 (Dictionary)4. 集合 (Set)5. 字符串 (String) Python 提供了几种内置的数据结构来存储和操作数据,每种都有其独特的特点和用途。下面是一些常用的数据结构及其简要说明: 1. 列表 (List) 列表是一种可变的有序集合,可以存放任意类型的数据。列表中的元素可以通过索

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

【数据结构入门】排序算法之交换排序与归并排序

前言         在前一篇博客,我们学习了排序算法中的插入排序和选择排序,接下来我们将继续探索交换排序与归并排序,这两个排序都是重头戏,让我们接着往下看。  一、交换排序 1.1 冒泡排序 冒泡排序是一种简单的排序算法。 1.1.1 基本思想 它的基本思想是通过相邻元素的比较和交换,让较大的元素逐渐向右移动,从而将最大的元素移动到最右边。 动画演示: 1.1.2 具体步

CSDN:OpenStack镜像制作教程指导(全)

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录,涉及基本环境准备、常见类型操作系统的镜像制作。 让你可以从零开始安装一个操作系统,并支持个性化制作OpenStack镜像。 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows