堆的实现

//头文件:景.h
#pragma once
#include<iostream>
#include<assert.h>
#include<vector>

        /*
        堆实际上是一棵完全二叉树
        对于数组来说它的数据存放位置是随意的,实现堆,实际上就是实现一个具有特殊结构的数组,
        目的就是将数组的数据变得有序或者有优先级,一个数组,既可以看作一行存放数据,也可以看做树结构存放数据,将后者适当的
        进行操作,就使其成为了一个有序的堆:堆,只不过是利用一些数据将一般的树组成一个有序的树,*/

using namespace std;

template<class T>
class _Heap
{
public:
    _Heap()
    {}
    _Heap(const T* a,int size)      
    {
        assert(a);

        /*每一个节点都可以用下标的方式访问*/
        for(int i = 0; i < size; i++)
        {
            _a.push_back (a[i]);
        }

        for(int i=(_a.size()-2)/2; i >= 0; i--)//建堆,并且找最后一个的非叶子节点,以向下调整的方式进行堆的建立
        {
            _AdjustDown(i);//向下调整:在于先得到最后一个非叶子节点,将其作为parent,然后与child进行比较,谁大parent就指向谁,调整完这次之后,将其
            //看作一个子问题,防止产生调整之前的child的child大于调整之后的child的问题,直到child的child为空的时候或者当child大于数组的个数时,比较完该子树,i进行--,再次重复以上步骤
            //也就是说,所谓的向下调整:将该节点及其下方的所有子节点进行有序排列
        }

    }


public:

        void _AdjustDown(int parent)//向下调整排序:一开始给的是parent,则向下调整
        {
            size_t child = parent*2+1;//左子节点
            while(child < _a.size ()) //保证子节点个数满足条件
            {
                if(child+1<_a.size()&&_a[child+1]>_a[child])
                    ++child;
                if(_a[child] > _a[parent])
                {
                    swap(_a[child],_a[parent]);//交换之后防止parent小于child,执行下面两句话
                    parent = child;
                    child = parent*2+1;
                }
                else break;

            }
        }

            void _AdjustUp(int child)//向上调整适合于在堆中进行插入操作
        {
             int parent = (child-1)/2;
             while(child > 0)
             {


                 if(_a[child] > _a[parent ])
                 {
                     swap(_a[child ],_a[parent ]);
                    child = parent ;
                    parent = (child-1)/2;
                 }
                 else
                     break;
             }

        }

                void Push(const T& x)  //O(lgN)  给堆尾插并且需要重新进行排序,
        {
            _a.push_back (x);   
            _AdjustUp(_a.size()-1);

        }

        //void Push(const T& x)   这种方式的时间复杂度;O(N*lgN)
        //{
        //  _a.push_back (x);               
        //  for(int i=(_a.size()-2)/2; i >= 0; i--)//建堆,并且找最后一个的非叶子节点
        //{
        //  _AdjustDown(i);
        //}
        //}

                void Pop()//将堆顶的元素进行弹出 。最好的方式就是:将堆顶的数据与堆尾的数据进行交换,删除队尾,堆顶一下的数据是有序的,那么只需要将堆顶的数据传参给向下调整函数。
                {
                    assert (!_a.empty());
                    swap(_a[0],_a[_a.size()-1]);
                    _a.pop_back ();
                    _AdjustDown(0);
                }



protected:
    vector<int> _a;
};


//主函数:

#include"景.h"
//实现大堆排序
//堆:一种数据结构(完全二叉树),将一种数组对象用堆的方式存储起来,
//:堆 分两种大堆小堆,堆排序,就是利用堆进行的排序


void text()
{
    int a[10]={10,16,18,12,11,13,15,17,14,19};
    _Heap<int> h(a,10);
    //h.Push (111);
    //h.Push (222);
    //h.Push (333);
    //h.Push (3);
    //h.Push (2);
    //h.Push (1);
    h.Pop ();


}
int main()
{
    text ();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值