十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
//////
成都创新互联是一家集网站建设,景德镇企业网站建设,景德镇品牌网站建设,网站定制,景德镇网站建设报价,网络营销,网络优化,景德镇网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。1.堆是什么?含义:堆实质上是用一维数组(比链表实现更优)存贮一种特殊的二叉树(完全二叉树)的一种顺序存贮方式;所以,堆总是一颗完全二叉树,而且堆还有大小堆之分;
大堆:根节点是堆中大的数,且每一个父节点总是大于等于自己的子节点;
小堆:根节点是堆中最小的数,且每一个父节点总是小于自己的子节点
如下图所示:(不一定是有序的数组,这只是方便举例)
/////
2.堆的简单接口实现
2.1 初始化堆:既然是用一维数组实现,根据之前对栈等线性表用数组实现的学习,我们应该知道此时需要用结构体来构建其结构,结构体中包含 存贮完全二叉树中的节点信息的数组array,记录多少个节点的size, 以及用来判断是否需要扩容的capacity;,具体代码如下所示:
//定义结构体,表示堆的信息:
typedef int typedata;
typedef struct HeapNode
{
typedata* arr;
int size;
int capacity;
}HP;
//初始化堆
void HeapInit(HP* ps)//这里我没有先malloc空间,到后面插入的时候直接realloc就可以了;
{
assert(ps);
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
//
2.2 向堆中依次插入元素(向上调整法):
//向堆中插入:
void swap(typedata* p1, typedata* p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void AdjustUP(typedata* ps, int child)
{
int parent = (child - 1) / 2;//找到此时子节点的父节点,比较看是否需要向上调整;
while (child >0)
{
if (ps[child] >ps[parent])//如果子节点的值大于父节点的值
{
swap(&ps[child], &ps[parent]);//交换函数:交换子节点与父节点的值;
child = parent;//将父节点的数组下标给子节点,
parent = (child - 1) / 2;//让子节点找到新的父节点,继续比较;
}
else
{
break;
}
}
}
void HeapPush(HP* ps, typedata x)
{
assert(ps);
//扩容:
if (ps->size == ps->capacity)
{
ps->capacity = 0 ? 4 : ps->capacity * 2;
typedata* ptr = realloc(ps->arr,sizeof(typedata) *(ps->capacity));
if (ptr == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->arr = ptr;
}
ps->arr[ps->size] = x;
ps->size++;
//向上调整建堆:
AdjustUP(ps->arr, ps->size - 1);
}
//定义数组,调用插入接口依次插入:
int arr[10] = { 17,11,12,25,36,46,71,42,29,100 };
for (int i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
{
//向堆中依次插入元素:
HeapPush(&ps, arr[i]);
}
//
2.3 删除堆顶元素(向下调整法):
void AdjustDown(typedata* ps, int n, int parent)
{
assert(ps);
int child = parent * 2 + 1;
while (childps[parent])
{
swap(&ps[parent], &ps[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
//删除堆顶元素接口:
void HeapPop(HP* ps)
{
assert(!HeapEmpty(ps));
swap(&ps->arr[0], &ps->arr[ps->size - 1]);//先将堆顶与堆底交换;
ps->size--;//利用数组下标删除掉交换过来的堆顶;
//向下调整建堆:
AdjustDown(ps->arr, ps->size - 1, 0);
}
//
2.4 Topk问题(取堆中k个大或最小的元素):
//Top(选取大或最小的元素)接口:
typedata HeapTop(HP* ps)//有返回值;
{
assert(!HeapEmpty(ps));//调用判空接口对结构体判空
return ps->arr[0];//返回堆顶元素;
}
//Topk问题:取堆中大或最小的前K个元素:
int k = 5;
while(k--)
{
printf("%d ", HeapTop(&ps));//调用Top接口,获取堆顶元素,并打印出来;
HeapPop(&ps);//调用删除堆顶元素接口,删除掉打印过的堆顶,找堆中新的堆顶,实现多次寻找;
}
//
2.4 堆中元素个数,判空,打印以及销毁:
这几个接口比较简单,直接给出代码:
//判空:
bool HeapEmpty(HP* ps)
{
assert(ps);
return ps->size == 0;
}
//堆中元素个数:
size_t Heapsize(HP* ps)
{
assert(!HeapEmpty(ps));
return ps->size;
}
//打印堆:
void HeapPrint(HP* ps)
{
assert(!HeapEmpty(ps));
int i = 0;
for (i = 0; i< ps->size; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
//销毁堆:
void HeapDestroty(HP* ps)
{
assert(ps);
free(ps->arr);
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
/////
3,堆的意义?
意义:堆的意义在于存贮完全二叉树时同时可以通过堆排序(时间复杂度为O(n*log N)),快速的进行排序,此意义我将会在后面与其他几种排序中尽我大的能力去说明与理解;
/////
至此,这是我对堆的创建,堆的一些简单接口的实现的全部理解,如有不足之处,请各位大佬不吝赐教,谢谢!你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧