爱上数据结构:二叉树


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

🔥个人主页guoguoqiang. 🔥专栏数据结构

Alt

一、二叉树的顺序结构及实现

1.二叉树的顺序结构

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。
在这里插入图片描述

2.堆的概念及结构

如果有一个关键码的集合K = { , , ,…, },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: <= 且 <= ( >= 且 >= ) i = 0,1,2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

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

在这里插入图片描述
1.下列关键字序列为堆的是:(A)
A 100,60,70,50,32,65
B 60,70,65,50,32,100
C 65,100,70,32,50,60
D 70,65,100,32,50,60
E 32,50,100,70,65,60
F 50,100,70,65,60,32

2.已知小根堆为8,15,10,21,34,16,12,删除关键字 8 之后需重建堆,在此过程中,关键字之间的比较次
数是(C)。
A 1
B 2
C 3
D 4
3.一组记录排序码为(5 11 7 2 3 17),则利用堆排序方法建立的初始堆为©
A(11 5 7 2 3 17)
B(11 5 7 2 17 3)
C(17 11 7 2 3 5)
D(17 11 7 5 3 2)
E(17 7 11 3 5 2)
F(17 7 11 3 2 5)
4.最小堆[0,3,2,5,7,4,6,8],在删除堆顶元素0之后,其结果是(C)
A[3,2,5,7,4,6,8]
B[2,3,5,7,4,6,8]
C[2,3,4,5,7,8,6]
D[2,3,4,5,6,7,8]

3.堆的实现

1.堆向上调整算法

parent=(child-1)/2;
leftchild=(parent2)+1;
rightchild=(parent
2)+2;
向上调整建堆是O(N*logN)

void Swap(HPDataType *px, HPDataType *py) {
 	HPDataType tmp = *px;
	*px = *py;
	*py = tmp;
}
void AdjustUp(HPDataType *a, int child) {
	int parent = (child - 1) / 2;
	while (child > 0) {
		if (a[child] < a[parent]) {
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else {
			break;
		}
	}
}
//建堆时间复杂度O(N*logN)
for(int i=1;i<php->size;i++){
	AdjustUp(php->a,i);
}

2.向下调整算法

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整
成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。
parent=(child-1)/2;
leftchild=(parent2)+1;
rightchild=(parent
2)+2;

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

在这里插入图片描述

void AdjustDown(HPDataType* a,int n, int parent){
	int child=parent*2+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=parent*2+1;
		}
		else{
			break;
		}
	}
}
//建堆时间复杂度O(N)
for(int i=1;i<php->size;i++){
	AdjustDown(php->a,i);
}

通过时间复杂度来看,向下调整算法要优于向上调整。所以我们正常在建堆时一般使用向下调整。

3.堆的建立

下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根节点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆。

int a[] = {1,5,3,8,7,6};

在这里插入图片描述

4.建堆的时间复杂度

因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明(时间复杂度本来看的
就是近似值,多几个节点不影响最终结果):

向上调整建堆
在这里插入图片描述

在这里插入图片描述
向下调整算法建堆的时间复杂度为O(N)。

5. 堆的插入

先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆。
在这里插入图片描述

void HPPush(HP* php, HPDataType x) {
	assert(php);
	if (php->size == php->capacity) {
		size_t newcapcity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = realloc(php->a, sizeof(HPDataType)* newcapcity);
		if (tmp == NULL) {
			perror("realloc fail");
			return;
		}
		php->a = tmp;
		php->capacity = newcapcity;
	}
	php->a[php->size] = x;
	php->size++;

	AdjustUp(php->a, php->size - 1);
}

6.堆的删除

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。
在这里插入图片描述

void HPPop(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);
}

7.堆的实现

//Heap.h
#pragma once
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <time.h>
typedef int HPDataType;
typedef struct Heap {
	HPDataType* a;
	int size;
	int capacity;
}HP;
void HPInit(HP* php);
void HPDestroy(HP* php);
void HPPush(HP* php, HPDataType x);
HPDataType HPTop(HP* php);
void HPPop(HP* php);
bool HPEmpty(HP* php);
void AdjustDown(HPDataType* a, int n, int parent);
void Swap(HPDataType* px, HPDataType* py);
//Heap.c
#include "Heap.h"
void HPInit(HP* php) {
	assert(php);
	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}
void HPDestroy(HP* php) {
	assert(php);
	free(php->a);
	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}
void Swap(HPDataType *px, HPDataType *py) {
 	HPDataType tmp = *px;
	*px = *py;
	*py = tmp;
}
void AdjustUp(HPDataType *a, int child) {//O(N*log N)
	int parent = (child - 1) / 2;
	while (child > 0) {
		if (a[child] < a[parent]) {
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else {
			break;
		}
	}
}
void HPPush(HP* php, HPDataType x) {
	assert(php);
	if (php->size == php->capacity) {
		size_t newcapcity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = realloc(php->a, sizeof(HPDataType)* newcapcity);
		if (tmp == NULL) {
			perror("realloc fail");
			return;
		}
		php->a = tmp;
		php->capacity = newcapcity;
	}
	php->a[php->size] = x;
	php->size++;

	AdjustUp(php->a, php->size - 1);
}
HPDataType HPTop(HP* php) {
	assert(php);
	return php->a[0];
}
void AdjustDown(HPDataType* a,int n, int parent) {
	int child = parent * 2 + 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 = parent * 2 + 1;
		}
		else {
			break;
		}
	}
}
void HPPop(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);
}
bool HPEmpty(HP* php) {
	assert(php);
	return php->size == 0;
}

8.堆的应用

1.堆排序

堆排序即利用堆的思想来进行排序

1.建堆 升序建大堆,降序建小堆
2.利用向下排序建堆
在这里插入图片描述

2.top-k问题

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大

  1. 用数据集合中前K个元素来建堆 前k个最大的元素,则建小堆 前k个最小的元素,则建大堆
  2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素,将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。
void TopK() {
	printf("请输入k:>");
	int k = 0;
	scanf("%d", &k);
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (fout == NULL) {
		perror("fopen error");
		return;
	}
	int val = 0;
	int* minheap = (int*)malloc(sizeof(int) * k);
	if (minheap == NULL) {
		perror("malloc fail");
		return;
	}
	for (int i = 0; i < k; i++) {
		fscanf(fout, "%d", &minheap[i]);
	}
	for (int i = (k - 1 - 1) / 2; i >= 0; i--) {
		AdjustDown(minheap, k, i);
	}
	int x = 0;
	while (fscanf(fout, "%d", &x) != EOF) {
		if (x > minheap[0]) {
			minheap[0] = x;
			AdjustDown(minheap, k, 0);
		}
	}
	for (int i = 0; i < k; i++) {
		printf("%d ", minheap[i]);
	}
	fclose(fout);
}

感谢观看!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

String工具类 StringBuilder、StringBuffer、StringJoiner

StringBuilder StringBuilder是可变字符串对象&#xff0c;是一个字符串容器&#xff0c;里面的字符串是可以改变的&#xff0c;就是用来操作字符串的。相比较于String&#xff1a; 更适合于做修改操作使代码看上去更加简洁效率更高 常見的api 代码 StringBuilder sb new Str…

【随笔】Git 高级篇 -- 整理提交记录(上)cherry-pick(十五)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

【无标题】【Android】Android中Intent的用法总结

2.显示地图: Java代码 Uri uri Uri.parse(“geo:38.899533,-77.036476”); Intent it new Intent(Intent.Action_VIEW,uri); startActivity(it); 3.从google搜索内容 Java代码 Intent intent new Intent(); intent.setAction(Intent.ACTION_WEB_SEARCH); intent.pu…

狗都能看懂的DDPM的论文详解

DDPM/扩散模型是什么 DDPM&#xff08;Denoising Diffusion Probabilistic Models&#xff09;是扩散模型的一种&#xff0c;在视觉领域是属于生成式的模型。 扩散模型&#xff08;Diffusion Model&#xff09;的概念最早可以追溯到统计物理学中的玻尔兹曼机&#xff08;Bolt…

WPS解决插入公式在正文带来行间距变大问题

问题描述 写论文解释公式时&#xff0c;插入对应的变量&#xff0c;导致行间距变大&#xff0c;如图 显然上文与下文行间距不等。但无法通过修改数值修改下文行间距。 解决办法

给毕业生推荐的三款二手车

我是一名纯正的90后&#xff0c;2011年毕业&#xff0c;汽车维修专业毕业&#xff0c;从小对汽车非常感兴趣&#xff0c;由于某些不可抗拒的原因&#xff0c;我在当年义无反顾的选择了去学习汽车维修&#xff0c;想着自己能做一名牛B 的汽车修理工&#xff0c;不为别的&#xf…

wordpress全站开发指南-面向开发者及深度用户(全中文实操)--php数组与基本循环

php数组与基本循环 <?php$myName"xixi";$namesarray(xixi1,xixi2,xixi3); ?> <p> Hi ,my name is <?php echo $myName; ?> </p> <p> Hi,my name is <?php echo $names[0] ?> </p> <p> Hi,my name is <?…

SMW200A罗德与施瓦茨SMW200A信号发生器

181/2461/8938产品概述&#xff1a; SMW200A是开发新型宽带通信系统&#xff0c;验证3G和4G基站&#xff0c;以及需数字调制信号的理想信号发生器。 SMW200A 矢量信号发生器 具有内部基带、高达2 GHz的I/Q调制带宽可以满足第4代和第5代标准(例如&#xff0c;5G、LTE-Advanced…

小程序商城免费搭建之java商城 电子商务Spring Cloud+Spring Boot+二次开发+mybatis+MQ+VR全

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

最短路计数

题目描述 给出一个 N 个顶点 M 条边的无向无权图&#xff0c;顶点编号为 1∼N。问从顶点 1 开始&#xff0c;到其他每个点的最短路有几条。 输入描述 第一行包含 2 个正整数 N,M&#xff0c;为图的顶点数与边数。 接下来 M 行&#xff0c;每行两个正整数 x,y&#xff0c;表示…

机器学习周记(第三十三周:文献阅读[GWO-GART])2024.4.1~2024.4.7

目录 摘要 ABSTRACT 1 论文信息 1.1 论文标题 1.2 论文摘要 1.3 论文数据集 1.4 论文模型 2 相关知识 摘要 本周阅读了一篇使用GAT结合GRU预测PM2.5浓度的文章。论文模型为图注意力循环网络&#xff08;GART&#xff09;&#xff0c;首次提出了一种新型的多层GAT架构&…

2024-简单点-python中的多重继承mro和super的联系

在Python的多重继承中&#xff0c;super()函数的作用主要是确保父类的方法被正确地调用&#xff0c;同时避免了直接调用父类可能带来的问题&#xff0c;如方法覆盖或名称冲突。super()的使用是Python实现合作式多重继承的关键。 具体来说&#xff0c;当一个类从多个父类继承时…

HTTP 摘要认证

文章目录 一、什么是摘要认证二、工作流程三、实例演示 一、什么是摘要认证 摘要认证&#xff0c;即 Digest Access Authentication&#xff0c;是一种HTTP身份验证机制&#xff0c;用于验证用户的身份。相较于基本认证&#xff08;Basic Authentication&#xff09;使用用户名…

Qt快速入门到熟练(3.程序运行发布与设置图标)

程序运行发布 当我们执行过qt过后&#xff0c;将会在项目目录里面生成出一个debug构建目录&#xff0c;点击进去选择debug文件夹&#xff0c;就可以看到我们生成出来的可执行文件。 很显然我们的项目就叫做MyFirstWidget&#xff0c;所以生成的可执行文件在没有人为设置的情…

CLR学习

视频链接&#xff1a;《CLR十分钟》系列之CLR运行模型_哔哩哔哩_bilibili 什么是 CLR 公共语言运行时&#xff08;Common Language Runtime CLR&#xff09; 是一个可有多种编程语言使用的 运行时&#xff0c;CLR 的核心功能&#xff08;比如 内存管理&#xff0c;程序集加载…

notion的使用心得

从老石的视频知道了notion是一个很强大的管理工具&#xff1a;这就是最棒的效率软件&#xff01;如果不是&#xff0c;我倒想试试你的 | Notion使用技巧分享_哔哩哔哩_bilibili 我一时半会不能全部学会&#xff0c;但是借用大家的好模板&#xff1a;如何用5分钟搭建简洁高效的…

html5分步问卷调查表模板源码

文章目录 1.设计来源1.1 问卷调查11.2 问卷调查21.3 问卷调查31.4 问卷调查41.5 问卷调查51.6 问卷调查6 2.效果和源码2.1 完整效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/137454703 html5分…

React 项目配置代码提交规范 ESLint、Pretttier、Husky、CommitLint

React 项目配置代码提交规范 ESLint、Pretttier、Husky、CommitLint 前言 团队开发的成员越来越多&#xff0c;项目都是由多个人进行开发和维护&#xff0c;每个人的代码书写习惯和风格又不尽相同&#xff0c;commit 的提交log 也是乱七八糟&#xff0c;为以后的开发和维护增…

PPT在线压缩工具推荐

有时候使用邮箱发送邮件时&#xff0c;添加的PPT、Word、PDF文档总会因为过大而转为其他类型的附件发送&#xff0c;不仅上传缓慢&#xff0c;对方查收下载时还有有效期限制&#xff0c;7天或15天后就过期再也无法下载了&#xff0c;有没有什么办法可以压缩PPT等文档&#xff0…

python3内置持久化模块shelve心得

python3内置持久化模块shelve心得 来自python官方网站的解释&#xff1a; https://docs.python.org/zh-cn/3.10/library/shelve.html 本文环境&#xff1a; Windows 10 专业版 64 位 Thonny 3.2.6 概述 内置模块 shelve 可以将任意 Python 对象&#xff08;即 https://docs…