首页 > 其他分享 >数据结构:二叉树的顺序结构及代码实现

数据结构:二叉树的顺序结构及代码实现

时间:2024-07-07 19:28:32浏览次数:14  
标签:php int HpDatatype 顺序 二叉树 child 数据结构 size

一:二叉树的顺序结构

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

1.1堆的结构及概念 

1、堆在逻辑上是一颗完全二叉树(类似于一颗满二叉树只缺了右下角)。

2、堆的实现利用的是数组,我们通常会利用动态数组来存放元素,这样可以快速扩容也不会很浪费空间,我们是将这颗完全二叉树用层序遍历的方式储存在数组里的。

3、堆有两种分别是大根堆小根堆 。

二.堆的代码实现 

1.1 堆的实现


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

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

1.2堆的创建

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

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

1.3建堆的时间复杂度

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

所以建堆的时间复杂度为O(N) 

1.4堆的插入

先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆。

1.5堆的删除

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法.

1.6堆的代码实现 

typedef int HpDatatype;
typedef struct Heap
{
	HpDatatype* a;
	int size;
	int capacity;
}HP;

void HpInit(HP* php);//堆的初始化
void Adjustup(HpDatatype* a, int child);//堆的向上调整
void Adjustdown(HpDatatype* a, int n, int parent);//堆的向下调整
void HpDestroy(HP* php);//堆的销毁
void HpPush(HP* php, HpDatatype x);//堆的插入
void HpPop(HP* php);//堆的删除
HpDatatype HPtop(HP* php);//取堆顶的数据
bool HPempty(HP* php);//堆的判空
void HpInit(HP* php)
{
	php->a = NULL;
	php->capacity = php->size = 0;
}
void HpDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->capacity = php->size = 0;
}
void swap(HpDatatype* p1, HpDatatype* p2)
{
	HpDatatype temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}
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;
		}
	}
}
void HpPush(HP* php, HpDatatype x)
{
	assert(php);
	if (php->size == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HpDatatype* temp = (HpDatatype*)realloc(php->a, newcapacity * sizeof(HpDatatype));
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}
		php->a = temp;
		php->capacity = newcapacity;
	}
	php->a[php->size] = x;
	php->size++;
	Adjustup(php->a,php->size-1);
}
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);

}
HpDatatype HPtop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	return php->a[0];
}
bool HPempty(HP* php) 
{
	assert(php);
	return php->size == 0;
}

三.用堆解决Top-k问题


TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:
1. 用数据集合中前K个元素来建堆
前k个最大的元素,则建小堆
前k个最小的元素,则建大堆
2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

void text1()
{
	int a[] = { 1,9,6,4,8,2,7,65,43,78,99,3,5,63 };
	int size = sizeof(a) / sizeof(int);
	HP hp;
	HpInit(&hp);
	for (int i = 0; i < size; i++)
	{
		HpPush(&hp, a[i]);
	}

	int i = 0;
	scanf("%d", &i);
	while (i--)
	{
		printf("%d ", HPtop(&hp));
		HpPop(&hp);
	}
}

此代码中的函数在上面的代码中有体现。

标签:php,int,HpDatatype,顺序,二叉树,child,数据结构,size
From: https://blog.csdn.net/cbwjty/article/details/140216745

相关文章

  • 数据结构:二叉树的链式结构及代码实现
    一.二叉树的链式结构1.1前置说明在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树结构掌握还不够深入,为了降低大家学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头......
  • mybatis-plus中last和orderBy的连用的使用顺序
    1. mybatis-plus中last和orderBy的连用的使用顺序在MyBatis-Plus中,last方法用于在构建查询时添加自定义的SQL片段,而orderBy方法用于指定排序规则。当你想要结合使用这两个方法时,可以先调用orderBy指定排序规则,然后调用last添加自定义的SQL片段。@Autowired......
  • 数据结构小学期第七天
    今天继续学习Springboot的项目实战今天了解了一下,如何在自己登陆后,还能让界面知道是谁在进行操作,这个功能的实现需要JWT令牌的作用我们需要先引入一个JWT依赖1<!--java-JWT坐标-->2<dependency>3<groupId>com.auth0</groupId>4<artifa......
  • [数据结构]堆
    建堆的两种方式自上而下这种方式的思路是,每插入一个节点,就向上比较,判断是否需要与其父节点进行交换,分析这种方式的时间复杂度,假设树的高度为h,以下均考虑最坏情况,也就是每一个节点都调整到根第一层的1个节点不需要调整第二层的2个节点,每个节点向上调整1次,2*1,第三层的4个节点......
  • 【手写数据库内核组件】01 解析树的结构,不同类型的数据结构组多层的链表树,抽象类型统
    不同类型的链表​专栏内容:postgresql使用入门基础手写数据库toadb并发编程个人主页:我的主页管理社区:开源数据库座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.文章目录不同类型的链表概述1.数据类型识别1.1TLV格式介绍1.2结构体分层定义1.3定义......
  • 数据结构——RMQ(ST表)问题
    数据结构——RMQ(ST表)问题问题描述对于序列\(A[1\dotsn]\),有\(m\)组询问\(\langlel,r\rangle\),求\(\max_{i=l}^rA_i\)。我们下面使用\(\mathcalO(A)\sim\mathcalO(B)\)表示预处理\(\mathcalO(A)\),单次询问\(\mathcalO(B)\)的时间复杂度。线段树解法时间复杂度......
  • 数据结构初阶 遍历二叉树问题(一)
    一.链式二叉树的实现1.结构体代码typedefintBTDateType;typedefstructBinaryTreeNode{ BTDateTypedata; structBinaryTreeNode*left; structBinaryTreeNode*right;}BTNode;大概的图形是这样子2.增删查改我们这里要明确的一点的二叉树的增删查改是没有......
  • 二叉树的链式结构
    前言Hello,友友们,小编将继续重新开始数据结构的学习,前面讲解了堆的部分知识,今天将讲解二叉树的链式结构的部分内容。1.概念回顾与新增二叉树是一种数据结构,其中每个节点最多有两个子节点,分别是左子节点和右子节点。二叉树的链式结构表示是使用指针(或引用)来连接节点,形成......
  • LCR 156. 序列化与反序列化二叉树
    序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列/反序列化算法执行......
  • DAY 1 数据结构与算法 (选择排序,冒泡排序,插入排序)
    1.选择排序        选择排序(SelectionSort)是一种简单直观的排序算法。其基本思想是每一次从待排序的数据元素中选择最小(或最大)的一个元素,放在已排好序的元素序列的末尾,直到全部待排序的数据元素排好序为止。即每一次设定一个数为最大或者最小值,然后与其他的数进行交......