二叉树的性质
- 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对
于序号为i的结点有:
1. 若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点 编号,无双亲节点
2. 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
3 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子
堆的概念及结构
1如果有一个关键码的集合K = { , , ,…, },把它的所有元素按完全二叉树的顺序存储方式存储
在一个一维数组中,并满足: <= 且 <= ( >= 且 >= ) i = 0,1,
2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质:
1)堆中某个节点的值总是不大于或不小于其父节点的值;
2)堆总是一棵完全二叉树。
注意:它们不一定是有序的,例如:大根堆的56与30交换也是可以的。
大概反向:
typedef int HPDataType;
typedef struct Heap
{
HPDataType* _a;
int _size;
int _capacity;
}Heap;
// 堆的构建
void HeapCreate(Heap* hp, HPDataType* a, int n);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
int HeapEmpty(Heap* hp);
提示:
堆的插入后可能不符合堆的性质(堆中某个节点的值总是不大于或不小于其父节点的值)。我们可以向上调整。
当然删除的时候,先第一个和最后一个交换后删除,在向下调整
代码:
.h文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h >
#include<assert.h>
typedef int HPDataType;
typedef struct Heap
{
HPDataType* data;
int size;
int capacity;
}HP;
void Swap(HPDataType* p1, HPDataType* p2);
void AdjustUp(HPDataType* data, int child);
void AdjustDown(HPDataType* data, int size, int parent);
//初始化
void HPInit(HP* php);
//销毁
void HPDestory(HP* php);
//插入
void HPPush(HP* php, HPDataType x);
//删除
void HPPop(HP* php);
//取头
HPDataType HPTop(HP* php);
//个数
int HPSize(HP* php);
//判断
bool HPEmpy(HP* php);
//打印
void HPPrint(HP* php);
两个.c文件
#include"heap.h"
void Swap(HPDataType* p1, HPDataType* p2)
{
HPDataType tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void HPInit(HP* php)
{
assert(php);
php->data = NULL;
php->size = 0;
php->capacity = 0;
}
void HPDestory(HP* php)
{
assert(php);
free(php->data);
php->data = NULL;
php->size = php->capacity = 0;
}
//向上调整
void AdjustUp(HPDataType* data, int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (data[child] > data[parent])
{
Swap(&data[child], &data[parent]);
child = parent;
parent = (child - 1) / 2;;
}
else
{
break;
}
}
}
void HPPush(HP* php, HPDataType x)
{
assert(php);
//扩容
if (php->capacity == php->size)
{
int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
HPDataType* tmp = (HPDataType*)realloc(php->data, newcapacity * sizeof(HPDataType));
if (tmp == NULL)
{
printf("realloc fail");
exit(-1);
}
php->data = tmp;
php->capacity = newcapacity;
}
php->data[php->size] = x;
php->size++;
AdjustUp(php->data, php->size - 1);
}
//向下调整
void AdjustDown(HPDataType* data, int size, int parent)
{
int child = parent * 2 + 1;
while (child < size)
{
if ((child + 1 < size) && (data[child + 1] > data[child]))
{
++child;
}
if (data[child] > data[parent])
{
Swap(&data[child], &data[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HPPop(HP* php)
{
assert(php);
assert(php->size > 0);
Swap(&(php->data[0]), &(php->data[php->size - 1]));
php->size--;
AdjustDown(php->data, php->size, 0);
}
HPDataType HPTop(HP* php)
{
assert(php);
return php->data[0];
}
int HPSize(HP* php)
{
assert(php);
return php->size;
}
bool HPEmpy(HP* php)
{
assert(php);
return php->size == 0;
}
void HPPrint(HP* php)
{
assert(php);
int i = 0;
for (i = 0; i < php->size; ++i)
{
printf("%d ", php->data[i]);
}
printf("\n");
}
void TestHeap()
{
HP hp;
HPInit(&hp);
int a[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };
for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
{
HPPush(&hp, a[i]);
}
HPPrint(&hp);
HPPush(&hp, 10);
HPPrint(&hp);
HPPop(&hp);
HPPrint(&hp);
HPPop(&hp);
HPPrint(&hp);
}
int main()
{
TestHeap();
return 0;
}
堆排序实现
// 对数组进行堆排序
void HeapSort(int* a, int n);
#include"heap.h"
void HeapSort(int* a, int n)
{
//向下调整时间复杂度为o(n),而向上调整时间复杂度为o(nlogn)
int i = 0;
for (i = (n - 1 - 1) / 2; i >= 0; --i)
{
AdjustDown(a, n, i);
}
//大堆排序,可以让数组变为升序 o(nlogn)
//我们可以依次把最大到最小值放到最后
int end = n - 1;
while (end > 0)
{
Swap(&a[0], &a[end]);
AdjustDown(a, end, 0);
--end;
}
for (i = 0; i < n; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
}
void TestHeapSort()
{
int a[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };
HeapSort(a, sizeof(a) / sizeof(int));
}
void TestHeap()
{
HP hp;
HPInit(&hp);
int a[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };
for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
{
HPPush(&hp, a[i]);
}
HPPrint(&hp);
HPPush(&hp, 10);
HPPrint(&hp);
HPPop(&hp);
HPPrint(&hp);
HPPop(&hp);
HPPrint(&hp);
}
int main()
{
//TestHeap();
TestHeapSort();
return 0;
}