目录
1.二叉树顺序结构及实现
1.1二叉树的顺序结构
普通二叉树是不是适合用数组来存储的,因为可能存在大量的空间浪费。而完全二叉树更适合使用顺序存储结构。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结,一个是操作系统管理内存的一块区域分段。
1.2堆的概念及结构
如果有一个关键码的集合K = {k0, k1, k2, …, kn - 1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:K(i) <= K(2i+1) 且 K(i) <= K(2i+2) (K(i) >= K(2i+1) 且 K(i) >= K(2i+2)) i = 0, 1, 2…,则称为小堆或大堆。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质:
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一颗完全二叉树。
1.3 堆的实现
1.3.1堆的插入
先插入x到数组的尾上,再进行向上调整算法,直到满足堆 。
1.将元素插入到堆的末尾,即最后一个孩子之后
2.插入之后如果堆的性质遭到破坏,将新插入节点顺着其双亲往上调整到合适位置即可
//交换函数
void Swap(HPDataType* pa, HPDataType* pb)
{
HPDataType tmp = *pa;
*pa = *pb;
*pb = tmp;
}
//向上调整
void AdjustUp(HPDataType* a, size_t child)
{
size_t 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 HeapPush(HP* php, HPDataType x)
{
assert(php);
if (php->size == php->capacity)
{
size_t newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;
HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newCapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
php->a = tmp;
php->capacity = newCapacity;
}
php->a[php->size] = x;
php->size++;
//向上调整,保持是小堆
AdjustUp(php->a, php->size - 1);
}
1.3.2堆的删除
删除堆是删除堆顶的数据,将堆顶的数据跟最后一个数据进行对换,然后删除最后一个数据,再进行向下调整算法。
1.根位置的元素跟最后一个元素进行交换
2.删除最后一个数据
3.进行向下调整
(找出左右孩子中较小的一个,跟父亲比较,如果比父亲小则交换,再从交换的孩子继续往下调整)
//向下调整
void AdjustDown(HPDataType* a, size_t size)
{
size_t parent = 0;
size_t child = parent * 2 + 1;
while (child < size)
{
//选出孩子中较小的一个
if (child + 1 < size && 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 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);
}
Heap.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int HPDataType;
typedef struct Heap
{
HPDataType* a;
size_t size;
size_t capacity;
}HP;
void Swap(HPDataType* pa, HPDataType* pb);
void HeapInit(HP* php);
void HeapPrint(HP* php);
void HeapDestory(HP* php);
void HeapPush(HP* php, HPDataType x);
void HeapPop(HP* php);
bool HeapEmpty(HP* php);
size_t HeapSize(HP* php);
size_t HeapTop(HP* php);
Heap.c
#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 HeapPrint(HP* php)
{
assert(php);
for (size_t i = 0; i < php->size; i++)
{
printf("%d ", php->a[i]);
}
printf("\n");
}