【数据结构】堆(一)——堆的实现(二)

简介: 【数据结构】堆(一)——堆的实现(二)

Ajustup函数:

二叉树的性质:child=2*parent+1

(可参考我的另外一篇博客:http://t.csdn.cn/GLlHN)


如果child<parent时,child和parent交换,交换后child=parent。否则break跳出循环。以此循环,当child来到根节点时结束,即:下标为0。

void Ajustup(HPDataType*a, int child)
{//N*logN
  assert(a);
  //int child = n - 1;
  while (child > 0)
  {
    int parent = (child - 1) / 2;
    if (a[child] > a[parent])
    {
      Swap(&a[child], &a[parent]);
      child = parent;
    }
    else
    {
      break;
    }
  }
}

交换可以写一个函数Swap来复用,会用到很多次。

void Swap(HPDataType* p1, HPDataType* p2)
{
  assert(p1);
  assert(p2);
  HPDataType tmp = 0;
    tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}


HeapPop函数

出数据只能是出堆顶的元素(根节点),否则没有什么意义。

当我们将根节点删除后,它的左子节点leftchild和右子节点rightchild谁来当根节点呢? 并且我们还得维持它是一个堆,也就是维持它是一个完全二叉树

假设左子节点大于右子节点时,让左子节点当根节点会出现什么情况呢?

显然这种方法是不可行的!!!

换一种思路:

让第一个位置的值和最后一个位置的值,再size--不就相当于删除了嘛,但交换上去的值在根节点的位置上,我们无法维持是大堆的情况,因此还需要向下调整Ajustdown。

void HeapPop(HP* php)
{
  assert(php);
  assert(php->size > 0);
  Swap(&php->a[0], &php->a[php->size-1]);
  php->size--;
  Ajustdown(php->a, php->size-1 , 0);
}


Ajustdown函数:

  • 由性质child=2*parent+1,反推:parent=(child-1)/2。

假设左子节点大,左子节点leftchild大于右子节点rightchild ,当左子节点小于右子节点,child++找到子节点大的那一个。

parent>child时交换,parent=child、child=2*child+1。

void Ajustdown(HPDataType* a, int n,int parent)
{//O(N)
  assert(a);
  int child = 2 * parent+1;
  while (child<n)
  {
    if (child + 1 < n && a[child] < a[child + 1])//  <假设左子树大
    {
      child++;
    }
    if (a[child] > a[parent])//>大堆,<为小堆
    {
      Swap(&a[child], &a[parent]);
      parent = child;
      child = child * 2 + 1;
    }
    else
    {
      break;
    }
  }
}

HeapTop、HeapSize、HeapEmpty函数较为直接,就不做解释了。

HPDataType HeapTop(HP* php)
{
  assert(php);
  assert(php->size > 0);
  return php->a[0];
}
int HeapSize(HP* php)
{
  assert(php);
  return php->size;
}
bool HeapEmpty(HP* php)
{
  assert(php);
  if (php->size == 0)
    return true;
  else
    return false;
}


代码实现:


Heap.h文件:

#define  _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<time.h>
typedef int HPDataType;
typedef struct Heap
{
  HPDataType* a;
  int size;
  int capacity;
}HP;
void Swap(HPDataType* p1, HPDataType* p2);
void HeapCreate(HP* php, HPDataType* a, int n);
void HeapPrintf(HP* php);
void HeapInit(HP* php);
void HeapDestroy(HP* php);
void HeapPush(HP* php, HPDataType x);
void HeapPop(HP* php);
HPDataType HeapTop(HP* php);
int HeapSize(HP* hp);
bool HeapEmpty(HP* hp);
void Ajustdown(HPDataType* a, int n, int parent); 
void Ajustup(HPDataType* a, int n);

Heap.c文件:

#include"Heap.h"
void HeapInit(HP* php)
{
  assert(php);
  php->capacity = 0;
  php->size = 0;
  php->a = NULL;
}
void HeapDestroy(HP* php)
{
  assert(php);
  assert(php->a);
  free(php->a);
  free(php);
}
void HeapPrintf(HP* php)
{
  assert(php);
  for (int i = 0; i < php->size; i++)
  {
    printf("%d ", php->a[i]);
  }
  printf("\n");
}
void Swap(HPDataType* p1, HPDataType* p2)
{
  assert(p1);
  assert(p2);
  HPDataType tmp = 0;
    tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}
void Ajustup(HPDataType*a, int child)
{//N*logN
  assert(a);
  //int child = n - 1;
  while (child > 0)
  {
    int parent = (child - 1) / 2;
    if (a[child] > a[parent])
    {
      Swap(&a[child], &a[parent]);
      child = parent;
    }
    else
    {
      break;
    }
  }
}
void Ajustdown(HPDataType* a, int n,int parent)
{//O(N)
  assert(a);
  int child = 2 * parent+1;
  while (child<n)
  {
    if (child + 1 < n && a[child] < a[child + 1])//  <假设左子树大
    {
      child++;
    }
    if (a[child] > a[parent])//>大堆,<为小堆
    {
      Swap(&a[child], &a[parent]);
      parent = child;
      child = child * 2 + 1;
    }
    else
    {
      break;
    }
  }
}
void HeapCreate(HP* php, HPDataType* a, int n)
{
  assert(php);
  HPDataType*tmp=(HPDataType*)malloc(sizeof(HPDataType) * n);
  if (tmp == NULL)
  {
    perror("malloc fail");
    exit(-1);
  }
  memcpy(php->a, tmp, sizeof(HPDataType)*n);
  php->size = php->capacity = n;
  for (int i = (n - 1 - 1) / 2; i >= 0; i--)
  {
    Ajustdown(php->a, n, i);
  }
}
void HeapPush(HP* php, HPDataType x)
{
  assert(php);
  if (php->size == php->capacity)
  {
    int newcapacity=php->capacity == 0 ? 4 : 2 * php->capacity;
    HPDataType* tmp=(HPDataType*)realloc(php->a, sizeof(HPDataType) * newcapacity);
    if (tmp == NULL)
    {
      perror("realloc fail");
      exit(-1);
    }
    php->a = tmp;
    php->capacity = newcapacity;
  }
  php->a[php->size++] = x;
  Ajustup(php->a, php->size-1);
}
void HeapPop(HP* php)
{
  assert(php);
  assert(php->size > 0);
  Swap(&php->a[0], &php->a[php->size-1]);
  php->size--;
  Ajustdown(php->a, php->size-1 , 0);
}
HPDataType HeapTop(HP* php)
{
  assert(php);
  assert(php->size > 0);
  return php->a[0];
}
int HeapSize(HP* php)
{
  assert(php);
  return php->size;
}
bool HeapEmpty(HP* php)
{
  assert(php);
  if (php->size == 0)
    return true;
  else
    return false;
}

Test.c文件:

#include"Heap.h"
void test1()
{
  HP php;
  HeapInit(&php);
  HeapPush(&php, 75);
  HeapPush(&php, 56);
  HeapPush(&php, 30);
  HeapPush(&php, 25);
  //HeapPop(&php);
  int a=HeapSize(&php);
  printf("%d\n", a);
  HeapPrintf(&php);
  HeapPush(&php, 100);
  HeapPrintf(&php);
  HeapPop(&php);
  HeapPrintf(&php);
  HeapDestroy(&php);
}
int main()
{
  test1();
  //test2();
  //test3();
  //test4();
  return 0;
}
相关文章
|
1月前
|
存储 算法 Java
散列表的数据结构以及对象在JVM堆中的存储过程
本文介绍了散列表的基本概念及其在JVM中的应用,详细讲解了散列表的结构、对象存储过程、Hashtable的扩容机制及与HashMap的区别。通过实例和图解,帮助读者理解散列表的工作原理和优化策略。
39 1
散列表的数据结构以及对象在JVM堆中的存储过程
|
1月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
71 16
|
2月前
|
存储 JavaScript 前端开发
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
92 1
|
3月前
|
存储 Java
【数据结构】优先级队列(堆)从实现到应用详解
本文介绍了优先级队列的概念及其底层数据结构——堆。优先级队列根据元素的优先级而非插入顺序进行出队操作。JDK1.8中的`PriorityQueue`使用堆实现,堆分为大根堆和小根堆。大根堆中每个节点的值都不小于其子节点的值,小根堆则相反。文章详细讲解了如何通过数组模拟实现堆,并提供了创建、插入、删除以及获取堆顶元素的具体步骤。此外,还介绍了堆排序及解决Top K问题的应用,并展示了Java中`PriorityQueue`的基本用法和注意事项。
67 5
【数据结构】优先级队列(堆)从实现到应用详解
|
2月前
|
存储 算法 调度
数据结构--二叉树的顺序实现(堆实现)
数据结构--二叉树的顺序实现(堆实现)
|
2月前
|
存储 算法 分布式数据库
【初阶数据结构】理解堆的特性与应用:深入探索完全二叉树的独特魅力
【初阶数据结构】理解堆的特性与应用:深入探索完全二叉树的独特魅力
|
2月前
|
存储 算法
探索数据结构:分支的世界之二叉树与堆
探索数据结构:分支的世界之二叉树与堆
|
2月前
|
存储 算法 Java
【用Java学习数据结构系列】用堆实现优先级队列
【用Java学习数据结构系列】用堆实现优先级队列
36 0
|
2月前
|
存储 算法
【数据结构】二叉树——顺序结构——堆及其实现
【数据结构】二叉树——顺序结构——堆及其实现
|
2月前
【数据结构】大根堆和小根堆
【数据结构】大根堆和小根堆
43 0