堆的基本操作(创建,排序,插入,删除...)

堆的概念:如果有一个关键码的集合k = {k0 , k1 , k2 , … , kn-1},把他的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:ki <= k2*i + 1 且 ki <= k2*i + 2(ki >= k2*i + 1且 ki >= k2*i + 2) i = 0 , 1, 2, 3, 4…,则称为小堆(或大堆).
例如下图:
这里写图片描述

下面用到了函数指针,在这里对函数指针进行粗略的描述

void Init(int a); //这个为一个函数. Init 为函数名
void ( * )(int a); // 这个是一种函数指针类型 就和 int * , char * 一样
void (* Init)(int a); // Init为函数指针
typedef void (* Init) (int a);// Init为一种类型(函数指针类型) 就像是 typedef int* p ; 这里的 Init 与 p 的意思是一样的

将二叉树调整为最小堆的原理:

  • 假设该结点的下标为parent
  • 找到该结点的左孩子left = parent*2 +1
  • 如果右孩子right = parent*2 + 1存在,找到left和right中最小的孩子
  • 比较parent是否小于其左右孩子中较小者,如果parent小于等于较小者,调整结束
  • 否则将parent中元素与较小的孩子交换,此时有可能导致其子树不满足堆的性质,继续其子树直到满足堆的性质
void AdjustDown(Heap* hp, int Parent)//调整顺序
{
    int childe = (Parent << 1) + 1;
    while (childe < hp->_size)
    {
        if (childe + 1 < hp->_size&& hp->_compare(hp->_hp[childe+1] , hp->_hp[childe]))
        {
            childe += 1;
        }

        if (hp->_compare(hp->_hp[childe] , hp->_hp[Parent]))
        {
            Swap(&hp->_hp[childe], &hp->_hp[Parent]);
            Parent = childe;
            childe = (Parent << 1) + 1;
        }
        else
            return;
    }
}

下面是关于堆的基本操作:

//Heap.h
#pragma once
#include<assert.h>
#include<malloc.h>
#include<stdlib.h>


typedef int HPDataType;
typedef int (*PCompare)(HPDataType left, HPDataType right);//函数指针
typedef struct Heap
{
    HPDataType* _hp;
    int _capacity;
    int _size;
    PCompare _compare;
}Heap;


int Less(HPDataType left, HPDataType right);
int Greater(HPDataType left, HPDataType right);
void InitHeap(Heap* hp);//初始化
void CreatHeap(Heap* hp, int* array, int size,PCompare compare);//创建堆
void AdjustDown(Heap* hp, int Parent);//调整顺序
void InsertHeap(Heap* hp,HPDataType data);//插入
void RemoveHeap(Heap* hp);//删除
int  SizeHeap(Heap* hp);//求大小
int EmptyHeap(Heap* hp);//判空
void DestroyHeap(Heap* hp);//销毁
HPDataType TopHeap(Heap* hp);//求堆顶元素

void Adjustup(Heap* hp, int child);
void CheckCapacity(Heap* hp);//扩容
//Heap.c
#include"Heap.h"

void InitHeap(Heap* hp)//初始化
{
    hp->_hp = (HPDataType*)malloc(3 * sizeof(HPDataType));
    hp->_size = 0;
    hp->_capacity = 3;
    hp->_compare = NULL;
}

int Less(HPDataType left, HPDataType right)
{
    return left < right;
}

int Greater(HPDataType left, HPDataType right)
{
    return left > right;
}

void Swap(HPDataType** childe,HPDataType** parent)
{
    HPDataType* tmp = *childe;
    *childe = *parent;
    *parent = tmp;
}


void AdjustDown(Heap* hp, int Parent)//调整顺序
{
    int childe = (Parent << 1) + 1;
    while (childe < hp->_size)
    {
        if (childe + 1 < hp->_size&& hp->_compare(hp->_hp[childe+1] , hp->_hp[childe]))
        {
            childe += 1;
        }

        if (hp->_compare(hp->_hp[childe] , hp->_hp[Parent]))
        {
            Swap(&hp->_hp[childe], &hp->_hp[Parent]);
            Parent = childe;
            childe = (Parent << 1) + 1;
        }
        else
            return;
    }
}


void CreatHeap(Heap* hp, int* array, int size, PCompare compare)//创建堆
{
    int root;
    assert(hp);
    root = (size - 2) / 2;
    hp->_hp = (HPDataType*)malloc(size * sizeof(HPDataType));
    if (0 == hp->_hp)
    {
        perror("malloc::hp");
        return;
    }
    hp->_capacity = size;
    memcpy(hp->_hp, array, size * sizeof(HPDataType));
    hp->_size = size;
    hp->_compare = compare;
    for (; root >= 0; root--)
    {
        AdjustDown(hp, root);
    }
}

void CheckCapacity(Heap* hp)//扩充容量
{
    assert(hp);
    if (hp->_size == hp->_capacity)
    {
        int i = 0;
        HPDataType* pTem = (HPDataType*)malloc((hp->_size * 2) * sizeof(HPDataType));
        if (pTem == NULL)
        {
            perror("malloc::CheakCapacity");
            return;
        }
        /*for (i = 0; i < hp->_size; i++)
        {
            pTem[i] = hp->_hp[i];
        }*/
        memcpy(pTem, hp->_hp, hp->_size * sizeof(HPDataType));
        free(hp->_hp);
        hp->_hp = pTem;
        hp->_capacity = hp->_size * 2;
    }
}

void Adjustup(Heap* hp, int child)//向上调整

{
    int parent = ((child - 1) >> 1);
    while (child)
    {
        if (hp->_compare(hp->_hp[child] , hp->_hp[parent]))
        {
            Swap(&hp->_hp[parent], &hp->_hp[child]);
            child = parent;
            parent = ((child - 1) >> 1);
        }
        else
            return;
    }
}

void InsertHeap(Heap* hp, HPDataType data)//插入
{
    assert(hp);
    //将元素先放到堆中
    CheckCapacity(hp);
    hp->_hp[hp->_size++] = data;
    //对堆中元素进行调整(向上调整)

    Adjustup(hp, hp->_size - 1);//向上调整
}

int  SizeHeap(Heap* hp)//求大小
{
    assert(hp);
    return hp->_size;
}

int EmptyHeap(Heap* hp)//判空
{
    assert(hp);
    return !(hp->_size);
}

HPDataType TopHeap(Heap* hp)//求堆顶元素
{
    assert(hp);
    return hp->_hp[0];
}

void RemoveHeap(Heap* hp)//删除
{
    assert(hp);
    if (EmptyHeap(hp))
        return;
    Swap(&hp->_hp[0], &hp->_hp[hp->_size - 1]);
    hp->_size--;
    AdjustDown(hp, 0);
}

void DestroyHeap(Heap* hp)//销毁
{
    assert(hp);
    free(hp->_hp);
    hp->_size = 0;
    hp->_capacity = 0;
    hp->_compare = NULL;
}


//test.c
#include"Heap.h"


void test1()
{
    Heap hp;
    int array[] = { 1,2,3,4,5,6,7,8,9 };
    int size = sizeof(array) / sizeof(array[0]);
    InitHeap(&hp);//初始化

    CreatHeap(&hp, array,size,Greater);//创建堆
    InsertHeap(&hp,0);//插入
    RemoveHeap(&hp);//删除
}

int main()
{

    test1();
    system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39032310/article/details/82190328