二叉树的顺序存储

目录

顺序存储:

简介:

节点的位置关系:

优缺点:

优点:

缺点:

二叉树顺序存储的模拟实现:

向上调整算法:

向下调整算法:

二叉树的初始化:

直接初始化:

建堆初始化:

二叉树的头删:

二叉树的尾插:

二叉树的取顶端元素:

二叉树的判空:

二叉树的销毁:

完整代码:


顺序存储:

简介:

顺序结构存储就是使用数组来存储 ,一般使用数组只适合表示完全二叉树 ,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

节点的位置关系:

对于任意节点,设其在数组中的索引为 i(索引从0开始),则:

  • 父节点的索引为 (i-1)/2(向下取整)
  • 左子节点的索引为 2*i + 1
  • 右子节点的索引为 2*i + 2

优缺点:

优点

  • 访问任意节点的时间复杂度为O(1),因为可以直接通过索引访问。
  • 对于完全二叉树和满二叉树,空间利用率高。

缺点

  • 适用于完全二叉树或满二叉树,对于一般的二叉树,存在大量的空间浪费。
  • 插入和删除操作复杂,需要移动大量节点以保持树的顺序存储结构。

二叉树顺序存储的模拟实现:

向上调整算法:

cpp 复制代码
void AdjustUp(HeapDataType* 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;
		}
	}
}

向下调整算法:

cpp 复制代码
void Adjustdown(HeapDataType* a, int n, int parent)
{
	size_t 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;
		}
	}
}

二叉树的初始化:

直接初始化:

cpp 复制代码
void HeapInit(HP* php)
{
	php->a = NULL;
	php->capacity = 0;
	php->size = 0;
}

建堆初始化:

cpp 复制代码
void HeapInitArrey(HP* php, HeapDataType* a, int n)
{
	assert(php);
	php->a = (HeapDataType*)malloc(sizeof(HeapDataType) * n);
	if (php->a == NULL)
	{
		perror("malloc fail:");
		return;
	}
	memcpy(php->a, a, sizeof(HeapDataType) * n);
}

二叉树的头删:

cpp 复制代码
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);
}

二叉树的尾插:

cpp 复制代码
void HeapPush(HP* php, HeapDataType x)
{
	if (php->size == php->capacity)
	{
		size_t newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
		HeapDataType* tmp = realloc(php->a, sizeof(HeapDataType) * newcapacity);
		php->a = tmp;
		php->capacity = newcapacity;
	}
	php->a[php->size] = x;
	php->size++;

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

二叉树的取顶端元素:

cpp 复制代码
HeapDataType HeapTop(HP* php)
{
	assert(php);
	return php->a[0];
}

二叉树的判空:

cpp 复制代码
bool Empty(HP* php)
{
	assert(php);
	return php->size == 0;
}

二叉树的销毁:

cpp 复制代码
void HeapDestory(HP* php)
{
	free(php);
	php->a = NULL;
	php->capacity = 0; 
	php->size = 0;
}

完整代码:

cpp 复制代码
#include "heap.h"
void HeapInit(HP* php)
{
	php->a = NULL;
	php->capacity = 0;
	php->size = 0;
}

void HeapInitArrey(HP* php, HeapDataType* a, int n)
{
	assert(php);
	php->a = (HeapDataType*)malloc(sizeof(HeapDataType) * n);
	if (php->a == NULL)
	{
		perror("malloc fail:");
		return;
	}
	memcpy(php->a, a, sizeof(HeapDataType) * n);
}

void HeapPush(HP* php, HeapDataType x)
{
	if (php->size == php->capacity)
	{
		size_t newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
		HeapDataType* tmp = realloc(php->a,sizeof(HeapDataType) * newcapacity);
		php->a = tmp;
		php->capacity = newcapacity;
	}
	php->a[php->size] = x;
	php->size++;

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

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);
}

void Swap(HeapDataType* x, HeapDataType* y)
{
	HeapDataType* tmp = *x;
	*x = *y;
	*y = tmp;
}

void AdjustUp(HeapDataType* 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 Adjustdown(HeapDataType* a, int n, int parent)
{
	size_t 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;
		}
	}
}

HeapDataType HeapTop(HP* php)
{
	assert(php);
	return php->a[0];
}

bool Empty(HP* php)
{
	assert(php);
	return php->size == 0;
}

void HeapDestory(HP* php)
{
	free(php);
	php->a = NULL;
	php->capacity = 0; 
	php->size = 0;
}
相关推荐
挺菜的3 分钟前
【算法刷题记录(简单题)003】统计大写字母个数(java代码实现)
java·数据结构·算法
mit6.8243 分钟前
7.6 优先队列| dijkstra | hash | rust
算法
蜗牛沐雨4 分钟前
警惕 Rust 字符串的性能陷阱:`chars().nth()` 的深坑与高效之道
开发语言·后端·rust
2401_8582861137 分钟前
125.【C语言】数据结构之归并排序递归解法
c语言·开发语言·数据结构·算法·排序算法·归并排序
钱彬 (Qian Bin)1 小时前
一文掌握Qt Quick数字图像处理项目开发(基于Qt 6.9 C++和QML,代码开源)
c++·开源·qml·qt quick·qt6.9·数字图像处理项目·美观界面
guygg881 小时前
基于matlab的FIR滤波器
开发语言·算法·matlab
双叶8361 小时前
(C++)学生管理系统(正式版)(map数组的应用)(string应用)(引用)(文件储存的应用)(C++教学)(C++项目)
c语言·开发语言·数据结构·c++
源代码•宸2 小时前
C++高频知识点(二)
开发语言·c++·经验分享
ysh98882 小时前
PP-OCR:一款实用的超轻量级OCR系统
算法
遇雪长安2 小时前
差分定位技术:原理、分类与应用场景
算法·分类·数据挖掘·rtk·差分定位