堆的增删改查和堆排序(堆是特殊的完全二叉树,堆按顺序表存储)
1.堆是特殊的完全二叉树,堆按顺序表存储
2.按下标:叶子结点个数 (n+1)/2 非叶子节点 n/2
按元素:叶子结点个数 (n-1)/2 非叶子节点 n/2-1 父情节点
代码实现
Heap.h
#ifndef _HEAP_H_
#define _HEAP_H_
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef int HPDataType;
typedef struct Heap
{
HPDataType* data;
int size;
int capacity;
}Heap;
void adjustDown(Heap* hp, int n);
void HeapInit(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);//判空
void HeapPrint(Heap* hp);
void HeapPrintS(Heap* hp);
void HeapSort(Heap* hp);// 堆排序
#endif // !_HEAP_H_
Heap.c
#include "Heap.h"
//向下调整算法复杂度O(logn);
void adjustDown(Heap* hp, int cur) {
assert(hp);
int n;
while (cur * 2 + 1 < hp->size) {
if (cur * 2 + 2 >= hp->size) {
n = cur * 2 + 1;
}
else {
if (hp->data[cur * 2 + 1] > hp->data[cur * 2 + 2]) {
n = cur * 2 + 1;
}
else {
n = cur * 2 + 2;
}
}
if (hp->data[cur] < hp->data[n]) {
int tmp = hp->data[cur];
hp->data[cur] = hp->data[n];
hp->data[n] = tmp;
cur = n;
}
else {
break;
}
}
}
//初始堆时间复杂度O(nlogn);
void HeapInit(Heap* hp, HPDataType* a, int n) {
assert(hp && a);
hp->capacity = n * 2;
hp->size = n;
hp->data = (HPDataType*)calloc(hp->capacity, sizeof(HPDataType));
for (int i = 0; i < n; i++) {
hp->data[i] = a[i];
}
for (int i = n / 2 - 1; i >= 0; i--) {
adjustDown(hp, i);
}
}
void HeapDestory(Heap* hp) {
assert(hp);
if (hp->data) {
}
free(hp->data);
hp->data = NULL;
hp->capacity = 0;
hp->size = 0;
}
//插入用向上调整算法
void HeapPush(Heap* hp, HPDataType x) {
assert(hp);
if (hp->size == hp->capacity) {
hp->capacity *= 2;
hp->data = (HPDataType*)realloc(hp->data, hp->capacity*sizeof(HPDataType));
}
int cur = hp->size;
hp->data[hp->size] = x;
hp->size++;
while (cur>0) {
if (hp->data[(cur - 1) / 2] < hp->data[cur]) {
int tmp = hp->data[(cur - 1) / 2];
hp->data[(cur - 1) / 2] = hp->data[cur];
hp->data[cur] = tmp;
cur = (cur - 1) / 2;
}
else {
break;
}
}
}
//删堆顶元素时间复杂度O(longn);
void HeapPop(Heap* hp) {
assert(hp);
if (hp->size == 0) {
return;
}
hp->size--;
int tmp = hp->data[0];
hp->data[0] = hp->data[hp->size];
hp->data[hp->size] = tmp;
adjustDown(hp, 0);
}
HPDataType HeapTop(Heap* hp) {
assert(hp);
if (hp->size == 0) {
return (HPDataType)0;
}
return hp->data[0];
}
int HeapSize(Heap* hp) {
assert(hp);
return hp->size;
}
//判空
int HeapEmpty(Heap* hp) {
assert(hp);
return hp->size == 0;
}
void HeapPrint(Heap* hp) {
putchar('\n');
assert(hp);
int rn = 0;
for (int i = 0; i < hp->size; i++) {
printf("%d ", hp->data[i]);
if (i == rn) {
putchar('\n');
rn = 2 * i + 2;
}
}
putchar('\n');
}
void HeapPrintS(Heap* hp) {
assert(hp);
for (int i = hp->size - 1; i >=0 ; i--) {
printf("%d ", hp->data[i]);
}
}
// 堆排序时间复杂度O(logn);
void HeapSort(Heap* hp) {
assert(hp);
int tmp = hp->size;
while (hp->size > 1) {
HeapPop(hp);
}
hp->size = tmp;
}
main.c
#include "Heap.h"
int main() {
int data[10] = { 29, 72, 48, 53, 45, 30, 18, 36, 13, 35 };
Heap hp;
HeapInit(&hp, data, 10);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
HeapPrint(&hp);
adjustDown(&hp, 0);
HeapPrint(&hp);
HeapPush(&hp, 13);
HeapPush(&hp, 11);
HeapPrint(&hp);
HeapPop(&hp, 13);
HeapPrint(&hp);
HeapInit(&hp, data, 10);
HeapPrint(&hp);
HeapSort(&hp);
HeapPrintS(&hp);
system("pause");
return 0;
}