堆
一、最大堆的特点
1、每个节点最多可以有两个节点
2、根节点的键值是所有堆节点键值的最大值,并所有节点的值都比子节点大
3、处跟节点和最后一个左子节点外,其它节点必须有兄弟节点
二、怎么找子节点或父节点
堆是用数组表示的树
三、代码
#include<iostream>
#define MAX_CAPCITY 128
typedef struct _Heap {
int* arr;//存堆元素的数组
int size;//当前元素个数
int capacity;//当前存储容量
}Heap;
bool PopHeap(Heap& heap, int& value);//最大元素依次出列
bool insert(Heap& heap, int value);//插入元素
bool initHeap(Heap& heap, int* orginal, int size);//初始化
static void buildHeap(Heap& heap);//循环找节点
static void adjustDown(Heap& heap, int index);//向下排序
static void adjustUp(Heap& heap, int value);//向上排序
//初始化堆
bool initHeap(Heap& heap, int* orginal, int size) {
int capacity = MAX_CAPCITY > size ? MAX_CAPCITY : size;//看哪个大使用最大容量
heap.arr = new int[capacity];
if (!heap.arr)return false;
heap.capacity = capacity;
heap.size = 0;
if (size > 0) {
//方式一、一起拷贝
memcpy(heap.arr, orginal, size * sizeof(int));
heap.size = size;
//方式二: 一次插入一个
//for(int i=0; i<size; i++){
//insert(heap, orginal[i]);
//}
buildHeap(heap);
}
else {
heap.size = 0;
}
return true;
}
//按照当前的节点和子节点调整成最大堆
void adjustDown(Heap& heap, int index) {
int cur = heap.arr[index];
int parend, child;
//根据节点大小判断是否要进行调整
for (parend = index; (parend * 2 + 1) < heap.size; parend = child) {
child = parend * 2 + 1;
//取两个子节点中的最大节点
if (((child + 1) < heap.size) && (heap.arr[child] < heap.arr[child + 1])) {
child++;
}
//判断当前节点是否大于父节点
if (cur >= heap.arr[child]) {
break;
}
else {//大于当前父节点,进行交换,子节点位置继续往下调
heap.arr[parend] = heap.arr[child];
heap.arr[child] = cur;
}
}
}
void buildHeap(Heap& heap) {
int i;
for (i = heap.size/2 - 1; i >= 0; i--) {
adjustDown(heap, i);
}
}
//最大元素依次出列
bool PopHeap(Heap& heap, int& value) {
if (heap.size < 1)return false;
value = heap.arr[0];//对顶最大值给value
heap.arr[0] = heap.arr[--heap.size];//将最后一个元素给堆顶,并数组减1
adjustDown(heap, 0);//重新排序
return true;
}
bool insert(Heap& heap, int value) {
if (heap.size == heap.capacity) {//判断是否可以继续插入值
std::cout << "资源耗尽" << std::endl;
return false;
}
int index = heap.size;//获取到最后一个元素
heap.arr[heap.size++] = value;//在最后一个元素后加
adjustUp(heap, index);//重新排序,向上排序
return true;
}
//向上排序
void adjustUp(Heap& heap, int index) {
if (index < 0 || index >= heap.size) {
return;
}
while (index > 0) {
int temp = heap.arr[index];//获取到元素位置
int parent = (index - 1) / 2;//找到父节点
if (parent >= 0) {//判断是否有父节点
if (temp > heap.arr[parent]) {//进行比较
heap.arr[index] = heap.arr[parent];//重新排序
heap.arr[parent] = temp;
index = parent;
}
else {//不需要换位置时结束循环
break;
}
}
else {//没有父节点停止循环
break;
}
}
}
int main() {
int su[] = { 11,66,55,33,77,88,22,90,44,12 };
Heap heap;
if (!initHeap(heap, su, sizeof(su) / sizeof(su[0]))) {
std::cout << "初始化失败" << std::endl;
exit(-1);
}
for (int i = 0; i < heap.size; i++) {
std::cout << i<<"\t" << heap.arr[i] << std::endl;
}
std::cout << "-----------------------" << std::endl;
insert(heap, 99);
for (int i = 0; i < heap.size; i++) {
std::cout << i << "\t" << heap.arr[i] << std::endl;
}
std::cout << "元素从大到小依次出列" << std::endl;
int value;
while (PopHeap(heap, value)) {
std::cout << "出列元素为:" << value << std::endl;
}
}