【数据结构】堆的基本操作and堆排序

概念

堆是什么?

堆是一种特殊的完全二叉树,所以堆的底层通过数组实现
小堆:所有父节点的值小于其子节点的值。
大堆:所有父节点的值大于其子节点的值。![在这里插入图片描述](https://img-

在这里插入图片描述
**

堆的基本操作解析

**
建堆
1.先申请一块空间,然后对其赋值,逻辑上看为完全二叉树,然后对二叉树结构进行调整。(从对的倒数第一个非叶子节点向下调整,一直调整到堆的根节点,就可以调整成堆了)

在这里插入图片描述
向下调整算法(小堆)

1.设该节点下标为parent,
2.找到左孩子child = parent*2+1,如果右孩子存在比较左右孩子找出最小的孩子(大堆反之)
3.比较parent与最小孩子child的大小,如果parent<child,swap(parent,child)直到调整结束。
在这里插入图片描述
堆的插入
1.先检查是否需要扩容,
2.将数据插入到数组的结尾,
3.向上调整堆(通过child计算他的parent ,再比较child与parent,与向下调整类似)

在这里插入图片描述堆的删除
删除堆是删除堆顶的数据,将堆顶的数据跟最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。
**在这里插入图片描述
代码实现:

typedef int HPDataType;
typedef struct Heap
{
HPDataType * array;
int capacity;
int size;
}Heap;
void Swap(HPDataType* left, HPDataType * right)
{
 int temp = *left;
 *left = *right;
 *right = temp;
 }
 void Checkcapacity(Heap *hp)
{
 assert(hp);
 if (hp->size >= hp->capacity)
 {
  int newcapacity = 2 * hp->capacity;
  HPDataType* temp = (HPDataType *)malloc(sizeof(HPDataType)*newcapacity);
  if (temp == NULL)
  {
   assert(0);
   return;
  }
  memcpy(temp, hp->array, hp->size*sizeof(HPDataType));
  free(hp->array);
  hp->array = temp;
  hp->capacity = newcapacity;
 }
}
void AdjistDown(Heap *hp,int parent)
{
 int child = parent * 2 + 1;
 while (child<hp->size)
 {
  if (child +1 <hp->size && hp->array[child] > hp->array[child + 1])
  {
   child++;
  }
  if (hp->array[child] < hp->array[parent])
  {
   Swap(&hp->array[child], &hp->array[parent]);
   parent = child;
   child = parent * 2+1;
  }
  else
  {
   return;
  }
 }
}
void CreatHeap(Heap* hp, HPDataType arr[], int size)
{
 assert(hp);
 hp->array = (HPDataType *)malloc(sizeof(HPDataType)*size);
 if (hp->array == NULL)
 {
  assert(0);
  return;
 }
 hp->capacity = size;
 memcpy(hp->array, arr, sizeof(HPDataType)*size);
 hp->size = size;
 for (int root = (size - 2) / 2; root >= 0; root--)
 {
  AdjistDown(hp, root);
 }
}
void Heappush(Heap* hp, HPDataType data)
{
 assert(hp);
 Checkcapacity(hp);
 hp->array[hp->size++] = data;
 Adjistup(hp, hp->size - 1);
}
void Heappop(Heap* hp)
{
 assert(hp);
 if (Heapempty(hp))
 {
  return;
 }
 Swap(&hp->array[0], &hp->array[hp->size-1]);
 hp->size--;
 AdjistDown(hp, 0);
}
void Heapdestroy(Heap * hp)
{
 assert(hp);
 if (hp->array)
 {
  free(hp->array);
  hp->array = NULL;
  hp->size = 0;
  hp->capacity = 0;
 }
}

堆排序

升序建大堆,降序建小堆
堆排序就是利用堆删除元素的特性进行排序
先建堆 在循环进行heappop();
时间复杂度为O(nlogn);
空间复杂度O(1);
但是堆排序不稳定

在这里插入图片描述
代码实现:

void Adjistdown(int array[],int size,int parent)
{
 int child = parent * 2 + 1;
 while (child < size)
 {
  if (child + 1 < size&&array[child] > array[child + 1])
  {
   child += 1;
  }
  if (array[child] < array[parent])
  {
   int temp = array[parent];
   array[parent] = array[child];
   array[child] = temp;
   parent = child;
   ;
   child = parent * 2 + 1;
  }
  else
  {
   return;
  }
 }
}
void heapsort(int array[],int size)
{
 for (int root = (size - 2) >> 1; root >= 0; root--)
 {
  Adjistdown(array, size, root);
 }
 int end = size - 1;
 while (end)
 {
 int temp = array[end];
  array[end] = array[0];
  array[0] = temp;  
  Adjistdown(array, end, 0);
  end--;
 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值