当前位置: 首页 > news >正文

【数据结构】二叉树的顺序结构实现

目录

1 树的概念与结构

1.1 树的概念

1.2 树的相关概念 

2 二叉树概念及结构

2.1 概念

2.2 特殊的二叉树

2.3 二叉树的性质

2.4 二叉树的存储结构 

3 二叉树的顺序结构及实现

3.1 堆的概念及结构

3.2 堆的实现 

3.2.1 堆向下调整算法

3.2.2堆的代码实现 


1 树的概念与结构

1.1 树的概念

树是一种非线性的数据结构,是通过n个有限节点组成一个具有层次关系的集合。看起来是一个倒挂的树,它是根朝上,叶子朝下的。

注意:树形结构中,子树之间不能有交集,否则就不是树形结构 

1.2 树的相关概念 

节点的度:一个节点含有的子树的个数称为该节点的度;如上图:A的度是6。

叶节点或终端节点:度为0的节点称为叶节点;如上图:J、K、L等节点为叶节点。

非终端节点或分支节点:度不为0的节点;如上图:B、C、D、E、G是分支节点。

子节点或孩子节点:一个节点含有的子树的根节点称为该节点的子节点;如上图:B是A的孩子节点。

双亲结点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;如上图:A是B的父节点。

兄弟节点:具有相同父节点的节点互称为兄弟节点;如上图:B、C是兄弟节点。

树的度:一棵树中,最大的节点的度称为树的度;如上图:树的度是3。

节点的层次:从根开始定义起,根为第一层,根的子节点为第二层,以此类推。

树的高度或深度:树中节点的最大层次。如上图:树的高度为4。

堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:J、K互为兄弟节点。

节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先。

子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙。

森林:由m(m>0)棵互不相交的树的集合称为森林。

2 二叉树概念及结构

2.1 概念

一棵二叉树是节点的一个有限集合,该集合要么为空,要么由一个根节点加上两棵别称为左子树和右子树的二叉树组成。

从上图可以看出:

  • 二叉树不存在度大于2的节点。
  • 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树。 

2.2 特殊的二叉树

满二叉树:一个二叉树,如果每一层的节点数都达到最大值,则这个数是满二叉树。如果一个二叉树的层数为k,节点总数是2^k-1,它就是满二叉树。

完全二叉树:完全二叉树是由满二叉树引出的。一个二叉树的叶节点是连续的,这个数就是完全二叉树。满二叉树是一种特殊的完全二叉树。

2.3 二叉树的性质

 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个节点。

若规定根节点的层数为1,则深度为h的二叉树的最大节点数是2^h-1。

若规定根节点的层数为1,具有n个节点的满二叉树的深度,h=log(n+1),(log(n+1)是log以2为底,n+1为对数)

对于具有n个节点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的节点有:

  • 若i>0,i位置节点的双亲序号:(i-1)/2; i=0时,i为根节点编号,无双亲节点。
  • 若2i+1<n,左孩子节点序号:2i+1,2i+1>=n时无左孩子节点。
  • 若2i+2<n,右孩子节点序号:2i+2,2i+2>=n时无右孩子节点。

2.4 二叉树的存储结构 

(1)顺序存储

顺序结构存储就是用数组来存储,一般使用数组只适合表示完全二叉树,不是完全二叉树会有空间的浪费。二叉树顺序存储在物理上是一个数组,逻辑上是一颗二叉树。

(2)链式存储

二叉树的链式存储是用链表表示一棵二叉树。通常的方法是链表中每个节点由三个域组成,数据域和左右指针域。左右指针分别用来给出该节点的左孩子和右孩子所在的链节点的存储地址。链式结构又分为二叉链和三叉链。

 

3 二叉树的顺序结构及实现

3.1 堆的概念及结构

序结普通的二叉树不适合用数组存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺构存储。我们通常把堆(一种二叉树)使用顺序结构的数组来存储。根节点最大的堆叫做大根堆,根节点最小的堆叫做小根堆。

堆的性质:

  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树。

3.2 堆的实现 

3.2.1 堆向下调整算法

我们给出一个数组,逻辑上看做是一棵完全二叉树。我们可以从根节点开始向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。

int arr[]={27,15,19,18,28,34,65,49,25,37};

3.2.2堆的代码实现 

#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>typedef int HPDataType;typedef struct Heap
{HPDataType* arr;int size;int capacity;
}HP;//初始化
void HPInit(HP* php);
//销毁
void HPDestroy(HP* php);
//插入数据
void HPPush(HP* php, HPDataType x);
//交换数据
void Swap(HPDataType* p1, HPDataType* p2);
void AdjustUp(HPDataType* arr, int child);
void AdjustDown(HPDataType* arr, int n, int parent);
//删除数据
void HPPop(HP* php);
//返回堆顶元素
HPDataType HPTop(HP* php);
//判空
bool HPEmpty(HP* php);
#include "Heap.h"
//初始化
void HPInit(HP* php)
{assert(php);php->arr = NULL;php->size = 0;php->capacity = 0;
}
//销毁
void HPDestroy(HP* php)
{assert(php);free(php->arr);php->arr = NULL;php->size = 0;php->capacity = 0;
}
//插入数据
void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void AdjustUp(HPDataType* arr, int child)
{int parent = (child - 1) / 2;//双亲节点位置while (child > 0){if (arr[child] < arr[parent]){Swap(&arr[child], &arr[parent]);//交换child = parent;parent = (child - 1) / 2;}else{break;}}
}
void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->arr, sizeof(HPDataType) * newcapacity);if (tmp == NULL){perror("realloc");exit(1);}php->arr = tmp;php->capacity = newcapacity;}php->arr[php->size] = x;//插入数据php->size++;//和双亲节点比较,看是否交换AdjustUp(php->arr, php->size - 1);//向上调整
}
//删除堆顶数据
void AdjustDown(HPDataType* arr, int n, int parent)
{//假设左孩子节点小int child = parent * 2 + 1;while (child < n)//child>=n说明孩子节点不存在了{//找出小的那个孩子节点if (child + 1 < n && arr[child + 1] < arr[child]){child++;}//交换if (arr[child] < arr[parent]){Swap(&arr[child], &arr[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
void HPPop(HP* php)
{assert(php);assert(php->size > 0);Swap(&php->arr[0], &php->arr[php->size - 1]);//第一个数据和最后一个数据交换php->size--;//删除堆顶数据//向下调整AdjustDown(php->arr, php->size, 0);
}
//返回堆顶元素
HPDataType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->arr[0];
}
//判空
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

以上就是有关树的概念和堆的实现,如果这篇文章对你有用,可以点点赞哦,你的支持就是我写下去的动力,后续会不断地分享知识。

http://www.dtcms.com/a/312665.html

相关文章:

  • SQL注入SQLi-LABS 靶场less31-38详细通关攻略
  • 托福阅读38-3
  • 使用AssemblyAI将音频数据转换成文本
  • AI生成图片工具分享!
  • Linux的权限概念
  • 关于Web前端安全之XSS攻击防御增强方法
  • 【视频内容创作】PR的关键帧动画
  • 机器学习第三课之逻辑回归(三)LogisticRegression
  • Python-初学openCV——图像预处理(五)
  • 团队独立思考的力量
  • 论文阅读:DMD蒸馏 | One-step Diffusion with Distribution Matching Distillation
  • Python 动态属性和特性(定义一个特性工厂函数)
  • 「源力觉醒 创作者计划」_文心大模型4.5系列开源模型, 从一行代码到一个生态:聊聊开源战略那些事儿,顺便扯扯文心大模型 4.5 的使用心得
  • zookeeper分布式锁 -- 读锁和写锁实现方式
  • gpu instancer crowd 使用自定义材质并且只修改单个物体的材质参数
  • 【领域热点】【Vue】Vue 与 WebAssembly:前端性能优化的黄金搭档
  • 渗透高级-----应急响应
  • 机器翻译的分类:规则式、统计式、神经式MT的核心区别
  • 新电脑上GitHub推送失败?全面排查与解决指南
  • 第三章-提示词-高级:开启智能交互新境界(13/36)
  • Flutter Dart类的使用
  • WebMvc自动配置流程讲解
  • 【MySQL】MySQL的安全风险与安装安全风险
  • GraphRAG:基于知识图谱的检索增强生成技术解析
  • OSPF HCIP
  • RAG 中常见的文本分块(chunk)方法及实战代码示例
  • 基于开源AI智能客服、AI智能名片与S2B2C商城小程序的餐饮行业私域流量运营策略研究
  • JavaEE初阶第十三期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(十一)
  • 最新Android Studio汉化教程--兼容插件包
  • 日产轩逸全面评测:可靠性高十万公里无大修,科技配置落后