【王道数据结构】第五章(下) | 树 | 二叉树

news2025/1/16 2:51:28

目录

        一、树的存储结构

1、双亲表示法(顺序存储):

2、孩子表示法(顺序+链式) 

3、孩子兄弟表示法(链式存储)

二、树、森林的遍历

1、树的先根遍历

2、树的后根遍历

3、层序遍历(队列实现)

4、森林的遍历

三、二叉排序树

1、二叉排序树定义

2、二叉排序树的操作

四、平衡二叉树

​编辑1、平衡二叉树定义 

2、平衡二叉树的插入

 五、哈夫曼树

1、哈夫曼树定义

2、哈夫曼树的构造(重点)

3、哈杜曼编码(重点)


一、树的存储结构

 

1、双亲表示法(顺序存储):

  • 每个结点中保存指向双亲的指针
//数据域:存放结点本身信息。
//双亲域:指示本结点的双亲结点在数组中的位置。
#define MAX_TREE_SIZE 100  //树中最多结点数

typedef struct{      //树的结点定义
   ElemType data; 
   int parent;      //双亲位置域
}PTNode;

typedef struct{                   //树的类型定义
   PTNode nodes[MAX_TREE_SIZE];   //双亲表示
   int n;                         //结点数
}PTree;

增:新增数据元素,无需按逻辑上的次序存储;(需要更改结点数n)
删:(叶子结点):

  • ① 将伪指针域设置为-1;
  • ②用后面的数据填补;(需要更改结点数n)

查询:

  • ①优点-查指定结点的双亲很方便;
  • ②缺点-查指定结点的孩子只能从头遍历,空数据导致遍历更慢;

优点: 查指定结点的双亲很方便
缺点:查指定结点的孩子只能从头遍历

2、孩子表示法(顺序+链式) 

  • 孩子表示法:顺序存储各个节点,每个结点中保存孩子链表头指针。
struct CTNode{
   int child;    //孩子结点在数组中的位置
   struct CTNode *next;    // 下一个孩子
};

typedef struct{
   ElemType data;
   struct CTNode *firstChild;    // 第一个孩子
}CTBox;

typedef struct{
   CTBox nodes[MAX_TREE_SIZE];
   int n, r;   // 结点数和根的位置
}CTree;

3、孩子兄弟表示法(链式存储)

typedef struct CSNode{
   ElemType data;                               //数据域
   struct CSNode *firstchild, *nextsibling;     //第一个孩子和右兄弟指针, *firstchild 看作左指针,*nextsibling看作右指针
}CSNode. *CSTree;

二、树、森林的遍历

1、树的先根遍历

  • 若树非空,先访问根结点,再依次对每棵子树进行先根遍历;(与对应二叉树的先序遍历序列相同)
void PreOrder(TreeNode *R){
   if(R!=NULL){
      visit(R);    //访问根节点
      while(R还有下一个子树T)
         PreOrder(T);      //先跟遍历下一个子树
   }
}

2、树的后根遍历

  • 若树非空,先依次对每棵子树进行后根遍历,最后再返回根节点;(与对应二叉树的中序遍历序列相同)
void PostOrder(TreeNode *R){
   if(R!=NULL){
      while(R还有下一个子树T)
         PostOrder(T);      //后跟遍历下一个子树
      visit(R);    //访问根节点
   }
}

3、层序遍历(队列实现)

  • 若树非空,则根结点入队;
  • 若队列非空,队头元素出队并访问,同时将该元素的孩子依次入队;
  • 重复以上操作直至队尾为空;

4、森林的遍历

  • 先序遍历:等同于依次对各个树进行先根遍历;也可以先转换成与之对应的二叉树,对二叉树进行先序遍历;
  • 中序遍历:等同于依次对各个树进行后根遍历;也可以先转换成与之对应的二叉树,对二叉树进行中序遍历;

三、二叉排序树

 

1、二叉排序树定义

二又排序树,又称二叉查找树(BST,Binary Search Tree)棵二叉树或者是空二叉树,或者是具有如下性质的二叉树:

  • 左子树上所有结点的关键字均小于根结点的关键字;
  • 右子树上所有结点的关键字均大于根结点的关键字。
  • 左子树和右子树又各是一棵二叉排序树。
  • 左子树结点值< 根结点值< 右子树结点值。
  • 进行中序遍历,可以得到一个递增的有序序列。

2、二叉排序树的操作

【二叉排序树的查找】

  • 若树非空,目标值与根结点的值比较:
  • 若相等,则查找成功;
  • 若小于根结点,则在左子树上查找,
  • 否则在右子树上查找。
  • 查找成功,返回结点指针;查找失败返回NULL 
typedef struct BSTNode{
   int key;
   struct BSTNode *lchild, *rchild;
}BSTNode, *BSTree;

//在二叉排序树中查找值为key的结点(非递归)
//最坏空间复杂度:O(1)
BSTNode *BST_Search(BSTree T, int key){
   while(T!=NULL && key!=T->key){        //若树空或等于跟结点值,则结束循环
      if(key<T->key)       //值小于根结点值,在左子树上查找
         T = T->lchild;
      else                  //值大于根结点值,在右子树上查找
         T = T->rchild;
   }
   return T;
}

//在二叉排序树中查找值为key的结点(递归)
//最坏空间复杂度:O(h)
BSTNode *BSTSearch(BSTree T, int key){
   if(T == NULL)
      return NULL;
   if(Kry == T->key)
      return T;
   else if(key < T->key)
      return BSTSearch(T->lchild, key);
   else 
      return BSTSearch(T->rchild, key);
}

【二叉排序树的插入操作】

  • 若原二叉排序树为空,则直接插入结点;否则,
  • 若关键字k小于根结点值,则插入到左子树,
  • 若关键字k大于根结点值,则插入到右子树 
//在二叉排序树中插入关键字为k的新结点(递归)
//最坏空间复杂度:O(h)
int BST_Insert(BSTree &T, int k){
   if(T==NULL){           //原树为空,新插入的结点为根结点
      T = (BSTree)malloc(sizeof(BSTNode));
      T->key = k;
      T->lchild = T->rchild = NULL;
      return 1;                       //插入成功
   }
   else if(K == T->key)               //树中存在相同关键字的结点,插入失败
      return 0;
   else if(k < T->key)                 
      return BST_Insert(T->lchild,k);
   else 
      return BST_Insert(T->rchild,k);
}

【二叉排序树的构造】

//按照str[]中的关键字序列建立二叉排序树
void Crear_BST(BSTree &T, int str[], int n){
   T = NULL;                     //初始时T为空树
   int i=0;
   while(i<n){
      BST_Insert(T,str[i]);     //依次将每个关键字插入到二叉排序树中
      i++;
   }
}

【二叉排序树的删除】

先搜索找到目标结点:

  • 若被删除结点z是叶结点则直接删除,不会破坏二叉排序树的性质 
  • 若结点z只有一棵左子树或右子树,则让z的子树成为z父结点的子树,替代z的位置
  • 若结点z有左、右两棵子树,则令z的直接后继 (或直接前驱) 替代z,然后从二叉排序树中删去这个直接后继(或直接前驱),这样就转换成了第一或第二种情况。

查找长度--在查找运算中,需要对比关键字的次数称为查找长度,反映了查找操作时间复杂度

四、平衡二叉树

1、平衡二叉树定义 

 

  • 平衡二叉树(Balanced Binary Tree),简称平衡树(AVL树)--上任一结点的左子树和右子树的高度之差不超过1。
//平衡二叉树结点
typedef struct AVLNode{
   int key;         //数据域
   int balance;     //平衡因子
   struct AVLNode *lchild; *rchild; 
}AVLNode, *AVLTree;


2、平衡二叉树的插入

  • 每次调整的对象都是“最小不平衡子树“
  • 在插入操作中,只要将最小不平衡子树调整平衡,则其他祖先结点都会恢复平衡。

 

 五、哈夫曼树

1、哈夫曼树定义

  1. 结点的权:有某种现实含义的数值(如:表示结点的重要性等)
  2. 结点的带权路径长度:从树的根到该结点的路径长度(经过的边数)与该结点上权值的乘积。
  3. 树的带权路径长度:树中所有叶结点的带权路径长度之和 (WPL,Weighted Path Length)。
  4. 哈夫曼树的定义:在含有n个带权叶结点的二叉树中,其中带权路径长度(WPL) 最小的二叉树,也称最优二叉树。

2、哈夫曼树的构造(重点)

给定n个权值分别为w1, W2,..., w,的结点,构造哈夫曼树的算法描述如下:

  • 1.将这n个结点分别作为n棵仅含一个结点的二叉树,构成森林F。
  • 2.构造一个新结点,从F中选取两棵根结点权值最小的树作为新结点的左、右子树,并且将新     结点的权值置为左、右子树上根结点的权值之和。
  • 3.从F中删除刚才选出的两棵树,同时将新得到的树加入F中
  • 4.重复步骤2和3,直至F中只剩下一棵树为止。

  • 每个初始结点最终都成为叶结点,且权值越小的结点到根结点的路径长度越大
  • 哈夫曼树的结点总数为2n - 1
  • 哈夫曼树中不存在度为1的结点。
  • 哈夫曼树并不唯一,但WPL必然相同且为最优

3、哈杜曼编码(重点)

  • 固定长度编码:每个字符用相等长度的二进制位表示
  • 可变长度编码:允许对不同字符用不等长的二进制位表示
  • 若没有一个编码是另一个编码的前缀,则称这样的编码为前缀编码

曼树得到哈夫曼编码--字符集中的每个字符作为一个叶子结点,各个字符出现的频度作为结点的权值,根据之前介绍的方法构造哈夫曼树 。


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/273595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电子技术——IC偏置-电流源、电流镜、电流舵

电子技术——IC偏置-电流源、电流镜、电流舵 IC偏置设计基于恒流源技术。在IC中的一个特定的区域&#xff0c;会生成一个精确的DC电流&#xff0c;这称为 参考电流 &#xff0c;之后通过电流镜复制到各个所需支路&#xff0c;并且通过电流舵进行电流转向。这项技术为IC的多级放…

知识图谱实战(01):从0-1搭建图片服务器

作者&#xff1a;艾文编程职业&#xff1a;程序员&#xff0c;BAT大厂资深工程师摘要&#xff1a;搜索/推荐场景下给用户展示大量的图片信息&#xff0c;那么这些数据是通过专门的图片服务器来访问的。 我们在基于知识图谱的智能搜索系统中&#xff0c;对搜索出来的每条记录都有…

支付系统核心架构设计思路(万能通用)

文章目录1. 支付系统总览核心系统交互业务图谱2. 核心系统解析交易核心交易核心基础交易类型抽象多表聚合 & 订单关联支付核心支付核心总览支付行为编排异常处理渠道网关资金核算3. 服务治理平台统一上下文数据一致性治理CAS校验幂等 & 异常补偿对账准实时对账DB拆分异…

fpga图像处理(sobel算子)

【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 关于sobel算子,前面已经讲过计算方法了。一种是上下的sobel算子,一种是左右的sobel算子,两者都相当于prewitt算子的进一步拓展。当然,之前的实现方法都是基于python和opencv实现…

【Leetcode】面试题 16.05. 阶乘尾数、HJ7 取近似值

作者&#xff1a;小卢 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 面试题 16.05. 阶乘尾数 HJ7 取近似值 面试题 16.05. 阶乘尾数 面试题 16.05. 阶乘尾数 …

这才是计算机科学_计算机大量应用

文章目录一、编译原理1.1 早期编译方式1.2 编程语言二、算法&数据结构2.1 Sort2.2 图搜索2.3 Array2.4 Node三、软件工程起源2.1分解打包三 、摩尔定律3.1 发展历3.1.1 电子管3.1.2 晶体管3.1.3 集成电路 IC3.2 刻蚀工艺3.2.2 光刻负责电路一、编译原理 之前讲的例子中 &am…

46 理论计算机科学基础-北京大学

P10 课程介绍05:46P21-1 预备知识07:43P31-2 确定型有穷自动机例子11:23P41-3 确定型有穷自动机的形式化定义17:51P51-4 设计确定型有穷自动机05:57P61-5 正则运算与封闭性28:16P71-6 非确定型有穷自动机37:43P81-7 DFA与NFA的等价性17:41P91-8 正则语言的封闭性10:30P102-1 正…

第九章(13):STL之常用排序算法

文章目录前情回顾常用排序算法sortrandom_shufflemergereverse下一座石碑&#x1f389;welcome&#x1f389; ✒️博主介绍&#xff1a;一名大一的智能制造专业学生&#xff0c;在学习C/C的路上会越走越远&#xff0c;后面不定期更新有关C/C语法&#xff0c;数据结构&#xff0…

Java 面向对象三大特性之三——接口(面试、学习、工作必备技能)

目录 一、接口概述(interface) 二、接口的成员 三、继承和实现 四、单继承和多实现 五、接口的优点 六、接口与抽象类 七、接口的思想 八、接口案例——运动员 ​​​​​​​ 接口概述(interface) 定义&#xff1a;是抽象方法和常量值的集合。 本质&#xff1a;从…

【C++修行之路】类和对象

面向对象编程详解目录前言面向对象和面向过程类和结构体构造函数和析构函数拷贝构造和赋值重载结语前言 好久不见&#xff0c;首先祝大家元宵节快乐&#xff0c;万家元夕宴&#xff0c;一路太平歌&#xff0c;今天执此佳节&#xff0c;一起来学习一下类和对象吧~ 面向对象和面…

系列分享 |《最强的 VLC 多媒体开发教程》

作者&#xff1a; 一去、二三里 个人微信号&#xff1a; iwaleon 微信公众号&#xff1a; 高效程序员 专栏介绍 《VLC 多媒体开发》&#xff0c;是一个专注于 libVLC 开发的专栏&#xff0c;里面共包含几十个章节&#xff0c;从 0 到 1&#xff0c;图文并茂&#xff0c;详细地…

【Linux】冯诺依曼体系与操作系统(OS)概念

文章目录冯诺依曼体系结构为什么是这样的结构局部性原理操作系统(Operator System)设计OS的目的定位如何理解管理 (精髓:先描述再组织)总结系统调用和库函数概念冯诺依曼体系结构 我们常见的计算机,如笔记本.我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系 为什么是这…

C++深入浅出(八)—— 继承

文章目录1. 继承的概念及定义&#x1f351; 继承的概念&#x1f351; 继承的定义&#x1f345; 定义格式&#x1f345; 继承关系和访问限定符&#x1f345; 继承基类成员访问方式的变化2. 基类和派生类对象赋值转换3. 继承中的作用域4. 派生类的默认成员函数5. 继承与友元6. 继…

jsp 校园网系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp 校园网系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统采用web模式开发&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数…

C#,入门教程(39)——C#语言的概念与知识点摘要

本文归纳整理C#的一些知识点&#xff0c;便于快速浏览与掌握C#语言的一些基本概念。本文并没有很好地层次与组织&#xff0c;抄了不少&#xff0c;写了不少&#xff0c;想到什么&#xff0c;就写什么。01 类 class类是C#等面向对象编程语言&#xff08;Object-oriented program…

常用API、Lambda、常见算法

目录 日期与时间 Date SimpleDateFormat Calendar JDK8新增日期类 概述、LocalTime/LocalDate/LocalDateTime Instant DateTimeFormatter Duration/Period ChronoUnit 包装类 包装类练习 正则表达式 正则表达式概述、初体验 正则表达式的匹配规则 正则表达式的…

Zookeeper注册中心

zookeeper的使用场景 分布式协调、分布式锁、元数据/配置信息管理、HA高可用性 分布式协调 A系统发送个请求到mq,然后B系统消息消费之后处理了,那A系统如何知道B系统的处理结果?A系统发送请求之后在zookeeper上对某个节点的值注册个监听器,一旦B系统处理完了就修改zooke…

C语言高级教程-C语言数组(七):数组综合实例之井字棋游戏问题

C语言高级教程-C语言数组&#xff08;七&#xff09;&#xff1a;数组综合实例之井字棋游戏问题一、本文的编译环境二、井字棋游戏的问题三、井字棋游戏的分析四、井字棋游戏的程序编写步骤4.1、添加主要的游戏循环和显示这个方格4.2、让玩家选择-一个方格&#xff0c; 并确定那…

Android 设置可抓包

在ren目录下新建xml文件夹&#xff0c;在xml下新建network_security_config.xml<?xml version"1.0" encoding"utf-8"?><!--<network-security-config>--><!-- <base-config cleartextTrafficPermitted"true" />--&…

MySQL面试:MySQL事务,内附详细视频教程,以及sql事务演示

文章目录一、事务&#xff08;提出事务&#xff09;二、四个特性&#xff08;事务要实现的特性&#xff09;三、一致性问题&#xff08;事务可以解决这些问题&#xff09;四、解决&#xff08;事务解决部分或全部一致性问题&#xff09;五、实现&#xff08;事务实现ACID的机制…