堆(讲解+代码超详细哦)

首先要和大家说一说堆得基本概念,也就是堆是什么:如果有一个关键码的集合,把他的所有元素按完全二叉树的顺序存储方式存储在一个一维数组 ,并满足; Ki <= K2*i+1 且 Ki<= K2*i+2  (Ki >= K2*i+1 且 Ki >= K2*i+2) i =0,1,2...,则 称为小堆 (或大堆)。

小堆(大堆)中:任一结点的关键码均小于(大于)等于它的左右孩子的关键码,位于堆顶结点的关键码最小(最大),从根节点到每个结点的路径上数组元素组成的序列都是递增(递减)的

堆存储在下标为0开始的数组中,因此在堆中给定下标为i的结点时:

如果i=0,结点i是根节点,没有双亲节点;否则结点i的双亲结点为结点(i-1)/2
如果
2 * i + 1 <= n - 1,则结点i的左孩子为结点2 * i + 1,否则结点i无左孩子

如果2 * i + 2 <= n - 1,则结点i的右孩子为结点2 * i + 2,否则结点i无右孩子

如图

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

从最后一个非叶子结点开始调整,一直到根节点为止,将每个结点及其子
树调整到满足小堆的性质即可
具体方法如下

1假设该节点的下标为parent

2找到该节点的左孩子 right=parent*2+1;

3如果右孩子也在,比较找出左右孩子中最小的孩子

4比较parent与最小的孩子,如果比最小的孩子小,那么调整结束

否则将最小孩子与parent交换此时有可能导致其子树不满足堆的性质,继续其子树直到满足堆的性质



堆的插入和删除

插入;

堆的插入;在建成最小堆的后面插入新元素,插入之后,当树中结点不满足堆的性质时,就需要对堆进行重新调整

删除;

堆的删除时,每次删除堆顶元素

删除方法

1用堆中最后一个元素,代替堆顶元素

2将堆的元素个数减少一个,相当于删除了最后一个元素。

3此时堆结构可能被破坏,应堆顶向下调整使再次满足堆的性质。



以上是我对堆的一点理解,下面是我实现的代码

#include <malloc.h>
#include<assert.h>
typedef int DataType;
typedef struct Heap
{
        DataType* _array;//存放堆的数组
        int _capacity;//数组的容量
        int _size;//已存数组的大小
}Heap;
void Swap(DataType *pLeft,DataType*pRight)//交换数值
{        
        DataType  temp;
        assert(pLeft);
        assert(pRight);

             
        temp=*pLeft;
        *pLeft=*pRight;
        *pRight=*pLeft; 
    
}   
    

void _AdjustDown(Heap*hp,int parent)//向下调整
{   
        //标记左右孩子中最小孩子
        int child=parent<<1+1;
        int size=hp->_size;
        while(child<size)
        { 
                if (child+1<size&&hp->_array[child]>hp->_array[child+1])//有右子树时 ,找左右孩子中最小的孩子 
                        child=child+1;
                if(hp->_array[child]<hp->_array[parent])//最小孩子小于双亲时 ,孩子与双亲数值交换,否则说明已经调好,不用继续
                {
                        Swap(&hp->_array[child],&hp->_array[parent]);
                        parent=child;
                        child =parent<<1;
                }
                else
                        return ;
        }
}


void CreateHeap(Heap*hp,DataType*array,int size)//创建
{
        int i=0;
        int root=(size-2)>>1;
        if (hp==NULL)
                return;
        //给堆申请空间
        hp->_array=(DataType*)malloc(sizeof (DataType)*size);
        if (hp->_array==NULL)
        {
                assert(0);
                return ;
        }
        //数组中元素放到堆中
        for (;i<size;++i)
                hp->_array[i]=array[i];
        hp->_capacity=size;
        hp->_size=size;
        //堆调整

        for (;root>=0;root--)
        {
                _AdjustDown(hp,root);
        }
}


void _AdjustUp(Heap*hp,int child)//向上调整
{
        int parent=(child-1)>>1;
        while (child)
        {
                if(hp->_array[child]<hp->_array[parent])
                {       Swap(&hp->_array[child],&hp->_array[parent]);
                        child=parent;
                        parent =(child-1)>>1;
                }
                else
                        return;
        }

}

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



void  _CheckCapacity(Heap*hp)//扩容
{
        int i=0;
        int newcapacity=0;
        DataType* temp=NULL;
        assert (hp);
        if (hp->_size==hp->_capacity)
        {
                newcapacity=hp->_capacity*2;
                DataType* temp=(DataType*)malloc(sizeof(DataType)*newcapacity);
                if (NULL==temp)
                {
                        assert (temp);
                        return;
                }
                for (i=0;i<hp->_size;i++)//老数组元素插入新数组
                {
                        temp[i]=hp->_array[i];
                }
                free(hp->_array);
                hp->_array=temp;
                hp->_capacity=newcapacity;
        }
}

        void InsertHeap(Heap*hp,DataType  data)
        {
                int child=0;
                int parent=0;
                assert(hp);
                _CheckCapacity(hp);
                hp->_array[hp->_size++]=data;//插入到最后一个元素的下一个位置
                //调整刚插入元素,
                _AdjustUp(hp,hp->_size-1);




        }




        void DeleteHeap(Heap*hp)//删除堆顶
        {
                if (EmptyHeap(hp))
                        return ;

                hp->_array[0]=hp->_array[hp->_size-1];//用最后一个元素覆盖堆顶,相当于删除堆顶
                hp->_size—;//删除最后一个元素
                _AdjustDown(hp,0);//对第一个元素进行调整

        }

        void TestHeap()
        {
                int arr[]={53,17,78,9,45,65,87,23,31};
                Heap   hp;


                CreateHeap(&hp,arr,sizeof(arr)/sizeof(arr[0]));
                InsertHeap(&hp,5);
                DeleteHeap(&hp);
        }

        int SizeHeap(Heap*hp)
        {
                assert (hp);
                return hp->_size;
        }
        int   main ()
        {
                TestHeap();
                                                                                                                           168,1-8       98%

 
 
 
 
 
 



猜你喜欢

转载自blog.csdn.net/a15929748502/article/details/80391886