二叉树顺序存储之堆(上)

堆的概念特性及接口实现
博客介绍了堆的概念,关键码集合按完全二叉树顺序存储在一维数组,满足特定条件可分为小堆和大堆。还阐述了堆的性质,如顺序存储的特殊形式、节点值与父节点关系、是完全二叉树,最后给出实现堆接口的代码。

1. 熟悉堆的概念以及特性

2. 实现堆的以下接口:

typedef int HPDataType; 
typedef struct Heap 
{ 
HPDataType* _array; 
int _capacity; 
int _size; 
}Heap; 

// 用数组初始化堆 
void InitHeap(Heap* hp, HPDataType* array, int size); 

// 初始化一个空堆 
void InitEmptyHeap(Heap* hp, int capacity); 

// 在堆中插入值为data的元素 
void InsertHeap(Heap* hp, HPDataType data); 

// 删除堆顶元素 
void EraseHeap(Heap* hp); 

// 获取堆中有效元素个数 
int HeapSize(Heap* hp); 

// 检测堆是否为空堆 
int HeapEmpty(Heap* hp); 

// 获取堆顶元素 
HPDataType HeapTop(Heap* hp); 

// 销毁堆 
void DestroyHeap(Heap* hp); 
  1. 熟悉堆的概念以及特性

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

  • 堆是顺序存储的一种特殊形式
  • 堆中某个节点的值总是不大于或者不小于其父节点的值;
  • 堆总是一颗完全二叉树
  1. 实现堆的以下接口:

直接上代码
注释即解释总结

Heap.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>

typedef int HPDataType;

typedef struct Heap
{
	HPDataType* _array;
	int _size;
	int _capacity;
}Heap, *pHeap;

// 用数组初始化堆 
void InitHeap(Heap* hp, HPDataType* array, int size);

// 初始化一个空堆 
void InitEmptyHeap(Heap* hp, int capacity);

// 在堆中插入值为data的元素 
void InsertHeap(Heap* hp, HPDataType data);

// 删除堆顶元素 
void EraseHeap(Heap* hp);

// 获取堆中有效元素个数 
int HeapSize(Heap* hp);

// 检测堆是否为空堆 
int HeapEmpty(Heap* hp);

// 获取堆顶元素 
HPDataType HeapTop(Heap* hp);

// 销毁堆 
void DestroyHeap(Heap* hp);

Heap.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
//建大堆
void Swap(HPDataType* pleft, HPDataType* pright)
{
	HPDataType tmp = *pleft;
	*pleft = *pright;
	*pright = tmp;
}

void adjustDown(HPDataType* array, int size, int parent)//向下调整将所传节点(这次传的是根节点)排到相应位置
{
	// 默认让child标记parent的左孩子,因为:完全二叉树某个节点如果只有一个孩子,该孩子一定是其双亲的左孩子
	int child = 2 * parent + 1;
	while (child < size)
	{
		//if (child + 1 < size && array[child + 1] < array[child])
		if (child + 1 < size && array[child + 1] > array[child])//建大堆向下调整时找两个孩子中较大的,小堆找较小的(牢记呀兄dei)
		{
			child += 1;
		}
		if (array[child] > array[parent])
		{
			Swap(&array[child], &array[parent]);
			parent = child;//parent 这一次是要调整根节点,根节点从上往下依次走,再去和下一个子节点进行比较进而判断是否调整
			child = parent * 2 + 1;
		}
		else
			return;
	}
}

void adjustUp(HPDataType* array, int size, int child)
{
	int parent = (child - 1) / 2;
	//对比向下调整,不需要判断寻找较小的节点,因为根节点唯一
	while (child)
	{
		if (child < size && array[child] > array[parent])//注意:向上调整时child不需要和他的兄弟节点来比较
					//重要:向上调整时,建大堆,child比parent根节点大的的话,向上调整交换,
					//反之,建小堆的话,child比parent根节点小的的话,向上调整交换
		{
			Swap(&array[child], &array[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			return;
	}
}

void checkCapacity(pHeap hp)
{
	assert(hp);
	if (hp->_size == hp->_capacity)
	{
		int newcapacity = hp->_capacity * 2;
		// 申请新空间
		HPDataType* ptmp = (HPDataType*)malloc(sizeof(HPDataType)* newcapacity);
		if (NULL == ptmp)
		{
			assert(0);
			return;
		}
		// 拷贝元素
		for (int i = 0; i < hp->_size; ++i)
			ptmp[i] = hp->_array[i];
		// 释放旧空间
		free(hp->_array);
		hp->_array = ptmp;
		hp->_capacity = newcapacity;
	}
}

// 用数组初始化堆 
void InitHeap(Heap* hp, HPDataType* array, int size)//是要把array数组(大小是size)放进堆hp中使其初始化
													//用数组初始化堆,传的是数组的大小size
{
	assert(hp);
	hp->_array = (HPDataType*)malloc(sizeof(HPDataType)* size);//牢记,初始化需要给堆里面的数组malloc
	if (NULL == hp->_array)
	{
		assert(0);
		return;
	}
	hp->_capacity = size;//数组直接就放满了
	//需不需要循环?需要的
	for (int i = 0; i < size; ++i)
	{
		hp->_array[i] = array[i];
	}
	hp->_size = size;//数组直接就放满了

	//调整为堆
	int root = (size - 2) >> 1;// 找完全二叉数中倒数第一个非叶子节点
	for (; root >= 0; --root)
	{
		adjustDown(hp->_array, hp->_size, root);//这里是向下调整
	}
}
// 初始化一个空堆 
void InitEmptyHeap(Heap* hp, int capacity)//初始化空堆,传的是capacity,并不是size
{
	assert(hp);
	hp->_array = (HPDataType*)malloc(sizeof(HPDataType)* capacity);//只要初始化就需要开辟空间malloc
	if (NULL == hp->_array)
	{
		assert(0);
		return;
	}
	hp->_capacity = capacity;
	hp->_size = 0;
}

// 在堆中插入值为data的元素 
void InsertHeap(Heap* hp, HPDataType data)
{
	assert(hp);
	checkCapacity(hp);
	hp->_array[hp->_size] = data;
	hp->_size++;
	adjustUp(hp->_array, hp->_size, hp->_size - 1);//什么时候向上调整,什么时候向下,向上向下的区别
	//size是堆的大小,size-1是要调整的元素下标(这里是最后一个)
}

// 删除堆顶元素 
void EraseHeap(Heap* hp)//为什么不直接删除最后一个元素?只能删除堆顶元素
{
	assert(hp);
	if (NULL == hp->_array)
		return;
	Swap(&hp->_array[0], &hp->_array[hp->_size - 1]);//交换堆顶元素和堆末尾元素
	hp->_size--;//size往前走一个
	adjustDown(hp->_array, hp->_size, 0);//再将堆顶放的交换过去的堆末尾元素向下调整到对应位置
}

// 获取堆中有效元素个数 
int HeapSize(Heap* hp)
{
	assert(hp);
	return hp->_size;
}

// 检测堆是否为空堆 
int HeapEmpty(Heap* hp)
{
	assert(hp);
	//return NULL == hp->_array;
	return 0 == hp->_size;//牢记:注意这两个的区别
						  //这里判空用size
}

// 获取堆顶元素 
HPDataType HeapTop(Heap* hp)
{
	assert(hp);
	return hp->_array[0];
}

// 销毁堆 
void DestroyHeap(Heap* hp)
{
	assert(hp);
	if (hp->_array)
	{
		free(hp ->_array);
		hp->_capacity = 0;
		hp->_size = 0; //是需要的,不能忘
	}
}

void TestHeap1()
{
	Heap hp;
	int array[] = { 2, 3, 8, 0, 9, 1, 7, 4, 6, 5 };
	InitHeap(&hp, array, sizeof(array) / sizeof(array[0]));
	printf("%d\n", HeapSize(&hp));
	printf("%d\n", HeapTop(&hp));

	EraseHeap(&hp);
	printf("%d\n", HeapTop(&hp));

	InsertHeap(&hp, 0);
	printf("%d\n", HeapTop(&hp));
	DestroyHeap(&hp);
}

int main()
{
	TestHeap1();
	system("pause");
	return 0;
}
标题SpringBoot智能在线预约挂号系统研究AI更换标题第1章引言介绍智能在线预约挂号系统的研究背景、意义、国内外研究现状及论文创新点。1.1研究背景与意义阐述智能在线预约挂号系统对提升医疗服务效率的重要性。1.2国内外研究现状分析国内外智能在线预约挂号系统的研究与应用情况。1.3研究方法及创新点概述本文采用的技术路线、研究方法及主要创新点。第2章相关理论总结智能在线预约挂号系统相关理论,包括系统架构、开发技术等。2.1系统架构设计理论介绍系统架构设计的基本原则和常用方法。2.2SpringBoot开发框架理论阐述SpringBoot框架的特点、优势及其在系统开发中的应用。2.3数据库设计与管理理论介绍数据库设计原则、数据模型及数据库管理系统。2.4网络安全与数据保护理论讨论网络安全威胁、数据保护技术及其在系统中的应用。第3章SpringBoot智能在线预约挂号系统设计详细介绍系统的设计方案,包括功能模块划分、数据库设计等。3.1系统功能模块设计划分系统功能模块,如用户管理、挂号管理、医生排班等。3.2数据库设计与实现设计数据库表结构,确定字段类型、主键及外键关系。3.3用户界面设计设计用户友好的界面,提升用户体验。3.4系统安全设计阐述系统安全策略,包括用户认证、数据加密等。第4章系统实现与测试介绍系统的实现过程,包括编码、测试及优化等。4.1系统编码实现采用SpringBoot框架进行系统编码实现。4.2系统测试方法介绍系统测试的方法、步骤及测试用例设计。4.3系统性能测试与分析对系统进行性能测试,分析测试结果并提出优化建议。4.4系统优化与改进根据测试结果对系统进行优化和改进,提升系统性能。第5章研究结果呈现系统实现后的效果,包括功能实现、性能提升等。5.1系统功能实现效果展示系统各功能模块的实现效果,如挂号成功界面等。5.2系统性能提升效果对比优化前后的系统性能
在金融行业中,对信用风险的判断是核心环节之一,其结果对机构的信贷政策和风险控制策略有直接影响。本文将围绕如何借助机器学习方法,尤其是Sklearn工具包,建立用于判断信用状况的预测系统。文中将涵盖逻辑回归、支持向量机等常见方法,并通过实际操作流程进行说明。 一、机器学习基本概念 机器学习属于人工智能的子领域,其基本理念是通过数据自动学习规律,而非依赖人工设定规则。在信贷分析中,该技术可用于挖掘历史数据中的潜在规律,进而对未来的信用表现进行预测。 二、Sklearn工具包概述 Sklearn(Scikit-learn)是Python语言中广泛使用的机器学习模块,提供多种数据处理和建模功能。它简化了数据清洗、特征提取、模型构建、验证与优化等流程,是数据科学项目中的常用工具。 三、逻辑回归模型 逻辑回归是一种常用于分类任务的线性模型,特别适用于二类问题。在信用评估中,该模型可用于判断借款人是否可能违约。其通过逻辑函数将输出映射为0到1之间的概率值,从而表示违约的可能性。 四、支持向量机模型 支持向量机是一种用于监督学习的算法,适用于数据维度高、样本量小的情况。在信用分析中,该方法能够通过寻找最佳分割面,区分违约与非违约客户。通过选用不同核函数,可应对复杂的非线性关系,提升预测精度。 五、数据预处理步骤 在建模前,需对原始数据进行清理与转换,包括处理缺失值、识别异常点、标准化数值、筛选有效特征等。对于信用评分,常见的输入变量包括收入水平、负债比例、信用历史记录、职业稳定性等。预处理有助于减少噪声干扰,增强模型的适应性。 六、模型构建与验证 借助Sklearn,可以将数据集划分为训练集和测试集,并通过交叉验证调整参数以提升模型性能。常用评估指标包括准确率、召回率、F1值以及AUC-ROC曲线。在处理不平衡数据时,更应关注模型的召回率与特异性。 七、集成学习方法 为提升模型预测能力,可采用集成策略,如结合多个模型的预测结果。这有助于降低单一模型的偏差与方差,增强整体预测的稳定性与准确性。 综上,基于机器学习的信用评估系统可通过Sklearn中的多种算法,结合合理的数据处理与模型优化,实现对借款人信用状况的精准判断。在实际应用中,需持续调整模型以适应市场变化,保障预测结果的长期有效性。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值