七龙珠第23界武道大会前八强
武道大会这种打擂台的比赛就类似与堆的原理 最强的人称为冠军
优点:是可以找到最强的人!
缺点:第二强的人却不知道是不是名副其实。
可能此时天津饭也可以和比克一战!
最大堆的特点:
1.每个节点最多可以有两个接点
2. 根节点的键值是所有节点里面的最大值,且每个节点的值都比其孩子节点的大
3. 除了根节点没有兄弟节点 最后一个左子节点可以没有兄弟节点 其他节点必须有兄弟节点
看图识最大堆
ab不是最大堆 c是最大堆
堆其实是用数组表示的树!
i的左子节点:2i+1
i的右子节点:2i+2
i的父节点:(i-1)/2
在数组中快速创建堆
原:
目标:
1.首先找到一个节点的父节点
如图 我们找到的是87 与其子节点比较 比子节点小 所以要和子节点调整位置 若比子节点大则不需要调整
2。移动到前一个节点93 做与上一步相同的操作
结果无需变化
3. 继续移动到前一个父节点 82 与子节点的较大者进行比较 比95要小 所以要调整位置.
4. 交换后 82又比其子节点小 又需要调整位置
5.构建堆完成
#include<iostream>
using namespace std;
//堆 数据结构的定义
#define DEFAULT_CAPCITY 128
typedef struct _Heap {
int* arr; //当前堆元素的数组
int size; //当前已经存储的元素个数
int capacity; //当前存储的容量
}Heap;
//建最大堆
//堆的初始化
void buildHeap(Heap& heap);
bool initHeap(Heap& heap, int* orginal, int size) {
//若默认容量大于传入的容量 则把容量设置为默认 否则设置为传入的size
int capacity = DEFAULT_CAPCITY > size ? DEFAULT_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;
buildHeap(heap);
}
else {
heap.size = 0;
}
return true;
}
/**************
* 将当前节点和和其子节点调整为最大堆
**************/
void adjustDown(Heap& heap, int index) {
int cur = heap.arr[index]; //当前待调整的系欸但
int parent, child;
/*判断是否存在大于当前节点的子节点,如果不存在,则堆本身是平衡的
*如果存在 则将最大子系欸但与之交换 ,交换后 如果这个子节点还存在
* 子节点 则需要按照相同的步骤 对这个子节点 进行调整
*
*/
for (parent = index; (parent * 2 + 1) < heap.size; parent = child) {
child = parent * 2 + 1;
//去两个子节点中较大的节点
if ((child + 1) < heap.size && (heap.arr[child] < heap.arr[child + 1])) {
child++;
}
//判断最大的节点是否大于当前的父节点
if (cur >= heap.arr[child]) {//不大于 不需要调整
break;
}
else {//大于 需要进行交换位置 然后从子系欸但位置 继续向下调整
heap.arr[parent] = heap.arr[child];
heap.arr[child] = cur;
}
}
}
/*从最后一个父节点 (size/2的位置)组个往前调整所以父节点(直到根节点),
*确保每一个夫节点都是一个最大堆,最后整体上形成一个最大堆
*/
void buildHeap(Heap& heap) {
int i;
for (i = heap.size / 2 - 1; i >= 0; i--) {
adjustDown(heap, i);
}
}
/*
*将当前节点 和父节点调整为最大堆
*/
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;
}
}
}
/*最大堆尾部插入节点 同时保证最大堆的特征*/
bool insert(Heap& heap, int value) {
if (heap.size == heap.capacity)
{
fprintf(stderr, "栈空间耗尽!\n");
return false;
}
int index = heap.size;
heap.arr[heap.size++] = value;
adjustUp(heap, index);
return true;
}
//最大元素出堆 把最后一个元素赋值给第一个最大的 再重新进行排列 向下调整
int popHeap(Heap& heap) {
int index = heap.arr[0];
heap.arr[0] = heap.arr[--heap.size ];
adjustDown(heap, 0);
return index;
}
int main(void) {
Heap hp;
int origVals[] = { 1, 2, 3, 87, 93, 82, 92, 86, 95 };
int i = 0;
if (!initHeap(hp, origVals, sizeof(origVals) / sizeof(origVals[0]))) {
fprintf(stderr, "初始化堆失败!\n");
exit(-1);
}
for (i = 0; i < hp.size; i++) {
printf("the %dth element:%d\n", i, hp.arr[i]);
}
insert(hp, 99);
printf("在堆中插入新的元素 99,插入结果:\n");
for (i = 0; i < hp.size; i++) {
printf("the %dth element:%d\n", i, hp.arr[i]);
}
int a=popHeap(hp);
printf("堆中的最大元素%d\n", a);
for (i = 0; i < hp.size; i++) {
printf("the %dth element:%d\n", i, hp.arr[i]);
}
system("pause");
return 0;
}