数据结构--《二叉树》

news2024/11/17 5:36:29

二叉树

1、什么是二叉树

二叉树(Binar Tree)是n(n>=0)个结点的优先集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两颗互不相交的、分别称为根结点的左子树和右子树的二叉树构成。

这里给张图,能更直观的感受二叉树:

  2、二叉树的特点

从上图可以看出二叉树的几个特点:

  1. 二叉树不存在度大于2的结点,每个结点最多有两颗子树;
  2. 左子树和右子树是有顺序的,次序不能颠倒;
  3. 即使树中的某个结点只有一颗子树,那也要区分它是左子树还是右子树。

讲到这那就不得不提及二叉树的五种基本形态:

  1. 空二叉树;
  2. 只有一个根节点;
  3. 根结点只有左子树;
  4. 根结点只有右子树;
  5. 根结点既有左子树又有右子树。

 

如下图所示,这棵树就不符合二叉树的条件,所以它就不是一颗二叉树。

 

3、几种特殊的二叉树

  1. 斜树:顾名思义,斜树一定是要斜的,但是往哪斜是有讲究的。所有结点只有左子树的二叉树叫左斜树。所有结点只有右子树的二叉树叫右斜树。这两者统称为斜树。
  2. 满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
  3. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编从1n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

 

4、二叉树的性质

4.1 满二叉树的性质

  1. 叶子只能出现在最下一层。出现在其他层就不可能达到平衡;
  2. 非叶子节点的度一定是2,否则就是“缺胳膊少腿”了;
  3. 在同样深度的二叉树中,满二叉树的结点个数最多,叶子最多。

4.2 完全二叉树的性质

  1. 叶子结点只能出现在最下两层;
  2. 最下层的叶子一定集中在左部连续位置;
  3. 倒数两层,若有叶子结点,一定都在右部连续位置;
  4. 如果结点度为1,则该结点只有左孩子,即不存在只有右孩子的情况;
  5. 同样结点数的二叉树,完全二叉树的深度最小。

4.3 二叉树的性质

  1. 若规定根节点的层数为 1 ,则一棵非空二叉树的 i 层上最多有2^(i-1) 个结点.
  2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2^h - 1.
  3. 若规定根节点的层数为 1 ,具有 n 个结点的满二叉树的深度 h= log2(n+1). (ps:是log 2 为底,n+1 为对数 ).
  4. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对 于序号为i的结点有:
    1. i>0 i 位置节点的双亲序号: (i-1)/2 i=0 i 为根节点编号,无双亲节点
    2. 2i+1<n ,左孩子序号: 2i+1 2i+1>=n 否则无左孩子
    3. 2i+2<n ,右孩子序号: 2i+2 ,2i+2>=n否则无右孩子
  5. 对任何一棵二叉树, 如果度为 0 其叶结点个数为n0  , 度为 2 的分支结点个数为n2  , 则有 n0=n2 + 1.

5、现实中的二叉树

6、二叉树的存储结构

二叉树一般可以使用两种存储结构,一种是顺序存储结构,另一种则是链式存储结构。 

6.1 顺序存储结构

二叉树的顺序存储结构计算用一个一维数组存储二叉树中的结点。一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储。

6.2 链式存储结构

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

 

typedef int BTDataType;
// 二叉链
struct BinaryTreeNode
{
 struct BinTreeNode* _pLeft; // 指向当前节点左孩子
 struct BinTreeNode* _pRight; // 指向当前节点右孩子
 BTDataType _data; // 当前节点值域
}
// 三叉链
struct BinaryTreeNode
{
 struct BinTreeNode* _pParent; // 指向当前节点的双亲
 struct BinTreeNode* _pLeft; // 指向当前节点左孩子
 struct BinTreeNode* _pRight; // 指向当前节点右孩子
 BTDataType _data; // 当前节点值域
};

 

7、二叉树的顺序存储结构

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结 构存储。现实中我们通常把堆 ( 一种二叉树 ) 使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

7.1 堆的概念和结构

如果有一个关键码的集合 K = { k0 ,k1 ,k2 , ,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足: ki<=k2i+2 且 ki<=k2i+1 (ki >=k2i+1 且 ki>=k2i+2 ) i = 0, 1, 2…,则称为小堆 ( 或大堆 ) 。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。

 

 

7.2 堆的实现

 实现堆的接口函数:
 

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include<time.h>
#include<string.h>


typedef int HPDataType;
typedef struct Heap
{
	//数组存储
	HPDataType* a;	//数组
	int size;	//数据的个数
	int capacity;	//数组长度
}HP;

//初始化
void HeapInit(HP* php);

//释放空间
void HeapDestory(HP* php);

//插入数据
void HeapPush(HP* php, HPDataType x);

//打印数据
void HeapPrint(HP* php);

//删除数据
void HeapPop(HP* php);

//获取第一个数据
HPDataType HeapTop(HP* php);

//判断是否为空
bool HeapEmpty(HP* php);

函数的具体实现

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"

//初始化
void HeapInit(HP* php)
{
	assert(php);

	php->a = NULL;
	php->size = php->capacity = 0;
}

//释放空间
void HeapDestory(HP* php)
{
	assert(php);

	free(php->a);
	php->a = NULL;
	php->size = php->capacity = 0;
}

//交换数据
void Swap(HPDataType* x, HPDataType* y)
{
	HPDataType tmp = *x;
	*x = *y;
	*y = tmp;
}

//结点向上调整 -- 小堆
void AdJustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;

	//循环判定条件为孩子结点下标大于0
	while (child > 0)
	{	
		//如果孩子结点值小于父亲节点就相互交换
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		//如果孩子结点值大于或等于父亲节点值就直接跳出循环
		else
		{
			break;
		}
	}

}

//向下调整
void AdJustDown(HPDataType* a, int n, int parent)
{
	int child = 2 * parent + 1;
	
	while (child < n )
	{
		//找出左孩子和右孩子中较小的那个
		if (child+1 < n && a[child + 1] > a[child])
		{
			++child;
		}

		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			//继续向下调整
			parent = child; 
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

//插入数据
void HeapPush(HP* php, HPDataType x)
{
	assert(php);

	//扩容
	if (php->capacity == php->size)
	{
		int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}

		php->a = tmp;
		php->capacity = newcapacity;
	}

	php->a[php->size] = x;
	php->size++;

	//插入新元素后,要使原来的堆还是小堆,就得向上调整
	AdJustUp(php->a , php->size-1);
}

//打印数据
void HeapPrint(HP* php)
{
	assert(php);

	for (int i = 0; i < php->size; i++)
	{
		printf("%d ", php->a[i]);
	}
}

//删除数据
void HeapPop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	//交换第一个和最后一个数据
	Swap(&php->a[0], &php->a[php->size - 1]);

	--php->size;

	AdJustDown(php->a, php->size, 0);
}

//获取第一个数据
HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	return php->a[0];
}

//判断是否为空
bool HeapEmpty(HP* php)
{
	assert(php);

	return php->size == 0;
}

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

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

相关文章

AJAX初级

AJAX的概念&#xff1a; 使用浏览器的 XMLHttpRequest 对象 与服务器通信 浏览器网页中&#xff0c;使用 AJAX技术&#xff08;XHR对象&#xff09;发起获取省份列表数据的请求&#xff0c;服务器代码响应准备好的省份列表数据给前端&#xff0c;前端拿到数据数组以后&#xf…

手把手教学,一站式教你实现服务器(Ubuntu)Anaconda多用户共享

背景&#xff1a;书接上回&#xff0c;一站式安装Ubuntu及配置服务器手把手教学&#xff0c;一站式安装ubuntu及配置服务器-CSDN博客 在安装及配置好服务器后&#xff0c;因为课题组可能涉及多个用户共用一台服务器&#xff0c;为了防止服务器上代码误删和Anaconda环境管理混乱…

js之图表使用

今天为了给大家演示图表的使用,今天展示下切换图形的修改属性快速修改 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><script src"./js/jquery-3.7.1.js"></script><script src…

Android 使用 adb 列出设备上所有危险权限

步骤1&#xff1a;确定 Android SDK 位置 打开 Android Studio 的设置&#xff0c;并来到 Languages & Frameworks › Android SDK 处&#xff1a; 这里可以看到 Android SDK 目录的位置&#xff1a; 例如&#xff1a;/Users/admin/Library/Android/sdk。 复制这个路径&am…

RAG概述(一):RAG架构的演进

目录 概述 RAG核心步骤 Indexing索引 Retrieval检索 Generation生成​​​​​​​ Native RAG Advanced RAG Modular RAG 参考 概述 RAG&#xff1a;Retrieval-Augmented Generation 检索增强生成。 RAG通过结合LLMs的内在知识和外部数据库的非参数化数据&#xff…

区间合并-leetcode合并石头的最低成本-XMUOJ元素共鸣:深层次的唤醒

题目 思路 话不多说&#xff0c;直接上代码 附上INT_MAX和INT_MIN 【C】详解 INT_MAX 和 INT_MIN&#xff08;INT_MAX 和 INT_MIN是什么&#xff1f;它们的用途是什么&#xff1f;如何防止溢出&#xff1f;&#xff09;_c int max-CSDN博客 代码 /* leetcode合并石头的最低…

未授权访问:Hadoop 未授权访问漏洞

目录 1、漏洞原理 2、环境搭建 3、未授权访问 4、通过REST API命令执行 防御手段 今天继续学习各种未授权访问的知识和相关的实操实验&#xff0c;一共有好多篇&#xff0c;内容主要是参考先知社区的一位大佬的关于未授权访问的好文章&#xff0c;还有其他大佬总结好的文章…

【机器学习数据可视化-07】波士顿房价预测数据分析

波士顿房价预测&#xff1a;基于数据可视化的深入探索 一、引言   在当今社会&#xff0c;房地产市场作为经济的重要支柱之一&#xff0c;其走势与波动直接影响着国家经济的稳定和人民生活的品质。波士顿&#xff0c;这座历史悠久且充满活力的城市&#xff0c;其房地产市场一…

ElasticSearch学习篇12_《检索技术核心20讲》基础篇

背景 学习极客实践课程《检索技术核心20讲》https://time.geekbang.org/column/article/215243 课程分为基础篇、进阶篇、系统案例篇 主要记录企业课程学习过程课程大纲关键点&#xff0c;以文档形式记录笔记。 内容 检索技术&#xff1a;它是更底层的通用技术&#xff0c…

如何用bet快速创建文件夹多个同级文件夹,多层子文件夹

第一种用txt编辑&#xff0c;保存格式改为bat 运行即可 md用来创建文件夹 md空格文件夹名字 或者 md空格文件夹名字\子文件夹名字 第一个创建一个文件夹&#xff0c;或者多个同级文件夹用空格隔开或者用,英文逗号隔开 md 00 md 00 md 11 md 22 md 33 或者 md 00 1…

Python 中别再用 ‘+‘ 拼接字符串了!

当我开始学习 Python 时&#xff0c;使用加号来连接字符串非常直观和容易&#xff0c;就像许多其他编程语言&#xff08;比如Java&#xff09;一样。 然而&#xff0c;很快我意识到许多开发者似乎更喜欢使用.join()方法而不是。 在本文中&#xff0c;我将介绍这两种方法之间的…

Charles抓包App_https_夜神模拟器

Openssl安装 下载安装 下载地址&#xff1a; http://slproweb.com/products/Win32OpenSSL.html 我已经下载好了64位的&#xff0c;也放出来&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Nkur475YK48_Ayq_vEm99w?pwdf4d7 提取码&#xff1a;f4d7 --来自百度网…

Golang实现文件复制

方法&#xff1a;三种 package zdpgo_fileimport ("errors""io""os" )// CopyFile 使用io.Copy进行文件的复制&#xff0c;同时也会复制文件的所有权限 // param src 复制文件 // param des 目标文件 // return error 错误信息 func CopyFile(s…

MacOS安装Docker-Compose

方法一 按照百度的方法进行安装&#xff0c;我大致复制一下百度的方法 1.确保您已经安装了Docker Desktop。 2.下载Docker Compose二进制文件。 3.将二进制文件移动到/usr/local/bin目录。 4.更改二进制文件的权限&#xff0c;使其可执行。 以下是具体的命令&#xff1a;…

LiveGBS流媒体平台GB/T28181用户手册-用户管理:添加用户、编辑、关联通道、搜索、重置密码

LiveGBS流媒体平台GB/T28181用户手册-用户管理:添加用户、编辑、关联通道、搜索、重置密码 1、用户管理1.1、添加用户1.2、编辑用户1.3、关联通道1.4、重置密码1.5、搜索1.6、删除 2、搭建GB28181视频直播平台 1、用户管理 1.1、添加用户 添加用户&#xff0c;可以配置登陆用户…

git 无法下载UE5源码问题

最近做镜像&#xff0c;突然遇到这个问题。 无法下载&#xff0c;应该如何解决呢&#xff1f; 1.首先 跳过htts ssl验证 2&#xff0c;设置更大的缓冲区 结果还是这个问题&#xff1a;

鹏特资本进入中国市场具有以下一些优势

1. 带来资金&#xff1a;补充国内资金缺口&#xff0c;为企业发展和项目建设提供重要的资金支持。 2. 先进技术和管理经验&#xff1a;有助于推动技术创新和管理水平提升&#xff0c;促进产业升级和优化。 3. 促进竞争&#xff1a;激发国内市场活力&#xff0c;促使本土企业不…

【调和级数】100321. 优质数对的总数 II

本文涉及知识点 调和级数 质数、最大公约数、菲蜀定理 LeetCode100321. 优质数对的总数 II 给你两个整数数组 nums1 和 nums2&#xff0c;长度分别为 n 和 m。同时给你一个正整数 k。 如果 nums1[i] 可以被 nums2[j] * k 整除&#xff0c;则称数对 (i, j) 为 优质数对&#…

网络模型-路由策略

一、路由策略 路由策略(Routing Policy)作用于路由&#xff0c;主要实现了路由过滤和路由属性设置等功能&#xff0c;它通过改变路由属性(包括可达性)来改变网络流量所经过的路径。目的:设备在发布、接收和引入路由信息时&#xff0c;根据实际组网需要实施一些策略&#xff0c…

什么是聚簇索引和非聚簇索引,如何理解回表、索引下推

聚簇索引&#xff08;Clustered Index&#xff09;和非聚簇索引&#xff08;Non-clustered Index&#xff09;是数据库中的两种索引类型&#xff0c;它们在组织和存储数据时有不同的方式。 聚簇索引 聚簇索引简单理解就是将数据与索引放在一起&#xff0c;找到索引即找到了数…