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

实现堆的插入,删除,取堆首元素,堆整理
1.堆的基本概念:

    最大(最小)堆是一棵每一个节点的键值都不小于(大于)其孩子
    (如果存在)的键值的树。大顶堆是一棵完全二叉树,
    同时也是一棵最大树。小顶堆是一棵完全完全二叉树,同时也是一棵最小树。

2.堆的一些基本性质:

  堆的插入和删除操作,运行时间为 O(logn),n 为树上结点的个数。
  堆可以看成是一棵完全二叉树,除最后一层其余每层结点都是满的。

3.堆的插入和删除操作实现:

插入: 一开始的时候,我们将待插入的数据元素接至堆的末尾,
    然后再不断向上提升直至没有大小颠倒为止。

删除: 将堆顶元素和堆的最后一个元素进行交换,
    然后对堆顶元素做一个自上而下的堆调整,也就是下滤操作。

下滤操作和上溢操作类似,也是不断交换父亲节点以及其孩子节点,然后更新当前遍历到的节点的编号以及其孩子节点的编号,直到堆中没有大小颠倒为止。

代码实现如下:以大堆为例

头文件heap.h

#pragma once
#include<stdio.h>
#include<string.h>

#define MAX_SIZE  1024 
typedef char Heaptype;

//比较函数
typedef int(*Compare)(Heaptype a, Heaptype b);
//堆的结构体
typedef struct Heap
{
    Heaptype data[MAX_SIZE];
    size_t size;
    Compare cmp;
}Heap;

int Greater(Heaptype a, Heaptype b);

void HeapInit(Heap* heap, Compare cmp);


void HeapRemove(Heap* heap, Compare);

void HeapInsert(Heap* heap, Heaptype value);

void HeapPrintf(Heap* heap, const char* msg);

int Heaproot(Heap* heap, Heaptype* value);

void HeapErase(Heap* heap);

void HeapCreate(Heap* heap, Heaptype arr[], size_t size);

void HeapSort(Heaptype arr[], size_t size);

函数实现heap.c

#include"heap.h"

//小堆  任意节点的值小于它的左右孩子的值,堆顶元素值最小,
//根节点到每个节点的路径上组数元素组成的序列是递增的

int Greater(Heaptype a, Heaptype b)
{
    return a > b ? 1 : 0;
}
int Less(Heaptype a, Heaptype b)
{
    return a < b ? 1 : 0;
}


//初始化
void HeapInit(Heap* heap, Compare cmp)
{
    if (heap == NULL)
    {
        //非法
        return;
    }
    heap->size = 0;
    heap->cmp = cmp;
    return;
}

//删除堆
void HeapRemove(Heap* heap, Compare cmp)
{
    if (heap == NULL)
    {
        return;
    }
    heap->size = 0;
    heap->cmp = NULL;
    return;
}
void Swap(Heaptype* a, Heaptype* b)
{
    Heaptype tmp = *a;
    *a = *b;
    *b = tmp;
    return;
}
//上浮函数   (大堆)    
void AdjustUp(Heap* heap, size_t index)
{
    //定义当前值为孩子节点
    size_t child = index;

    size_t parent = (child - 1) / 2;

    while (child > 0 && heap->data[parent]<heap->data[child])
    {
        //父亲节点的值小于孩子节点的值,交换父子节点的值
        //if (!heap->cmp(heap->data[parent], heap->data[child]))  
        {
            Swap(&heap->data[parent], &heap->data[child]);
        }
        child = parent;   //继续向上遍历
        parent = (child - 1) / 2;   
    }
}
//下沉函数    -暂定为大堆
void AdjustDown(Heap*heap, size_t index)
{                                         
    size_t parent = index;   //当前遍历到的节点下标0
    size_t child = parent * 2 + 1; //左孩子

    while (parent > 0)
    {
        //右孩子小于堆中元素数目 下               左孩子节点值大于右孩子节点值
        if (child + 1 < heap->size && heap->cmp(heap->data[child + 1], heap->data[child]))
        {
            child = child + 1;  //右孩子
        }
        if (heap->cmp(heap->data[child], heap->data[parent]))   //如果孩子节点值大于父亲节点值,交换父亲和孩子节点的值
        {
            Swap(&heap->data[child], &heap->data[parent]);   
        }
        else
        {
            break;
        }
        //继续向下遍历
        parent = child;  
        child = parent * 2 + 1;
    }
}
//插入(尾插)    -上浮函数
void HeapInsert(Heap* heap, Heaptype value)
{   
    if (heap == NULL)
    {
        //非法
        return;
    }
    if (heap->size >= MAX_SIZE)
    {
        //堆满
        return;
    }
    heap->data[heap->size++] = value;
    AdjustUp(heap, heap->size - 1);
}

//创建堆
void HeapCreate(Heap* heap, Heaptype arr[], size_t size)
{
    if (heap == NULL)
    {
        return;
    }
    size_t i = 0;
    for (; i < size; ++i)
    {
        HeapInsert(heap, arr[i]);
    }
    return;
}
//取堆首元素
int  Heaproot(Heap* heap, Heaptype* value)
{
    if (heap == NULL)
    {
        return NULL;
    }
    if (heap->size == 0)
    {
        return NULL ;
    }
     *value = heap->data[0];
    return 1;
}

//删除堆首元素  (首尾交换,自上而下调整)
void HeapErase(Heap* heap)
{
    if (heap == NULL)
    {
        return;
    }
    if (heap->size == 0)
    {
        return;
    }

    Swap(&heap->data[0], &heap->data[heap->size - 1]);
    //删除最后一个元素
    --heap->size;
    AdjustDown(heap, 0);//调整0号下标的元素
    return;
}

void HeapSort(Heaptype arr[], size_t size)
{   
    Heap heap;
    HeapInit(&heap, Greater);
    HeapCreate(&heap, arr, size);
    while (heap.size > 0)
    {
        HeapErase(&heap);
    }
    memcpy(arr, heap.data, sizeof(Heaptype)*size);
    return;
}

猜你喜欢

转载自blog.csdn.net/yu876876/article/details/80402702