/*
堆:一维数组
堆:一完全二叉树(就是除了最后一节点之外,其他的都是满的)去分析,从第一个结点开始编序号:**从 1 开始**
大顶堆:根结点的数比孩子节点的数要大,上一层的数比下一层的要大
数组下标:孩子节点的编号等于父结点的两倍
堆的插入:向上渗透
永远从堆的最后面插入
如果插入的结点比上一层的数要大,我们要调整堆
所以无论插入那个节点,首先都把它插到根部,然后再进行调整堆
堆的删除:向下渗透--对应出堆
*/
#include<stdio.h>
#include<stdlib.h>
#define MAX 11
//因为由数组实现,所以我们给他定义一个最大容量为11
typedef struct Heap
{
int sizeHeap; //堆的当前元素个数
int *heapData; //数据的存储
}HEAP,*LPHEAP;
//创建堆,堆就是一个结构体变量
LPHEAP createHeap()
{
LPHEAP heap = (LPHEAP) malloc (sizeof(HEAP));
heap->sizeHeap = 0;
heap->heapData = (int*)malloc(sizeof(int)*MAX);
return heap;
}
//万金油参数
int size(LPHEAP heap)
{
return heap->sizeHeap;
}
int empty(LPHEAP heap)
{
//如果返回1,表示为NULL,如果返回0,表示不为空
return heap->sizeHeap == 0;
}
//大顶堆,调整当前元素的位置,与除二的下标对比
void moveTocrrectPos(LPHEAP heap,int cusPos)
{
//向上渗透
while(cusPos > 1) //渗透到下标是 1 的位置,代表结束,当下标不为一的时候,要一直比较
{
int MAX = heap->heapData[curPos]; //假设插入的元素正好等于最后一个元素,然后再往上进行比较
int paretIndex = curPos / 2; //父结点下标等于孩子结点下标除以二
if(Max > heap->heapData[parentIndex])
{
//交换孩子节点和父结点的值
heap->heapData[curPos] = heap->heapData[parentIndex];
heap->heapData[parentIndex] = MAX;
curPos = parentIndex;
}
else
{
break; //不需要调整
}
}
}
//入堆
void insertHeap(LPHEAP heap,int data)
{
//放到堆的最后面
//从下标 1 开始
++heap->sizeHeap; //下标不从0开始
heap->heapData[heap->sizeHeap] = data;
moveTocrrectPos(heap,heap->sizeHeap); //sizeHeap传上去就是cusPos
//下标1 对应数据1,下标二对应数据2.。。。。。。。。
}
int popHeap(LPHEAP heap)
{
int Max = heap->heapData[1];
//调整堆,往下渗透,找最后一个元素合适的位置下标
//孩子节点等于父结点的两倍
int cusPos = 1;
int childIndex = cusPos * 2;
//然后小标从一开始1,2,,4,8....
while(childIndex <= heap->sizeHeap) //当孩子节点没有渗透到最后一层,就让它一直往下去
{
int temp = heap->heapData[childIndex];
//防止交换后位的数不是同层最大的,在这里进行左边和右边比较
if(childIndex+1 <= heap->sizeHeap && temp < geap->heapData[childIndex+1])
{
temp = heap->heapData[++childIndex]; //利用if循环判断获得最大值
}
heap->heapData[curPos] = temp;
curPos = childIndex; //这里的childIndex下标所指向的数是这一层最大的
childIndex*=2; //让childIndex往下一层去
}
heap->heapData[curPos] = heap->heapData[heap->sizeHeap];
//在这里最大的数已经到了最下方,然后让最小的数等于最大的数的下标,在这里,因为有MAX储存了最大数,正如下面return MAX,所以就是为了让最小的下标改到最大数最后走到的下标,相当于数组的伪删除,就是为了按大小顺序排列出来
--heap->sizeHeap;
return MAX;
}
int main()
{
LPHEAP heap = createHeap();
//堆里面,下标 0 是不会使用的,且这段内存不会使用
for(int i = 1;i < 11;i++)
{
inserHeap(heap.i);
//打印的结果是:10 9 6 7 8 2 5 1 4 3
}
printf("\n");
while(!empty(heap))
{
printf("%d\t",heap->heapData);
}
printf("\n");
system("pause");
return 0;
}
大顶堆
最新推荐文章于 2025-03-22 21:15:53 发布