大顶堆基本操作(插入,出堆),堆排序(普通,Heapify方式,数组原地堆排序)

#include<iostream>
#include<algorithm>
#include<cassert>
using namespace std;

//大顶堆  根节点为1,左孩子为2i 右孩子为2i+1
//对于每一个孩子的父亲为i/2
class MaxHeap
{

private:
    int* data;
    int count;
    int capacity;

    void shiftUp(int k)
    {

        while( k>1 && data[k/2]<data[k])//控制边界,当k=1时就不需要再比了
        {
            swap( data[k/2], data[k]);
            k/=2;
        }
    }

    void shiftDown(int k)
    {

        while(2*k <=count)
        {
            int j=2*k;//此轮循环中,data[j]和data[k]交换
            if(j+1<=count &&data[j+1]>data[j])//如果有右孩子且比左孩子大
            {
                j+=1;
            }
            if(data[k]>=data[j])
                break;

            swap(data[k],data[j]);
            k=j;
        }
    }
public:
    MaxHeap(int capacity)
    {
        data=new int[capacity+1];
        count=0;
        this->capacity= capacity;
    }

    MaxHeap(int arr[],int n)//heapify  将一个数组中的元素构造成堆
    //不需要再一个一个的插入操作
    {
        data=new int[n+1];
        capacity=n;
        for(int i=0;i<n;i++)
        {
            data[i+1]=arr[i];
        }
        count=n;
        for(int i=count/2;i>=1;i--)//从第一个不是叶子结点开始
        {
            shiftDown(i);
        }
    }

    ~MaxHeap()
    {
        delete []data;
    }
    int size()
    {
        return count;
    }
    bool isEmpty()
    {
        return count==0;
    }
    void insert(int item)
    {
        assert(count+1 <= capacity);
        data[count+1]=item;
        count++;
        shiftUp( count );
    }
    int  extractMax()
    {

        assert(count>0);
        int ret=data[1];
        swap(data[1],data[count]);
        count--;
        shiftDown(1);
        return ret;
    }
};

void  heapSort1(int arr[],int n)
{

    MaxHeap maxheap=MaxHeap(n);
    for(int i=0;i<n;i++)//逐个插入的算法复杂度是nlogn
    {
        maxheap.insert(arr[i]);
    }
    for(int i=n-1;i>=0;i--)
    {
        arr[i]=maxheap.extractMax();
    }
}
void heapSort2(int arr[],int n)
{
    MaxHeap maxheap=MaxHeap(arr,n);//heapify的算法复杂度是n
    for(int i=n-1;i>=0;i--)
    {
        arr[i]=maxheap.extractMax();
    }
}
//heapify 最后一个除以2得到的序号就是第一个不是叶子结点的序号
void __shiftDown(int arr[],int n,int k)
{
  //现在是从0开始了, 左孩子为2*k+1
     while(2*k+1 < n)
        {
            int j=2*k+1;//此轮循环中,data[j]和data[k]交换
            if(j+1<n && arr[j+1]>arr[j])//如果有右孩子且比左孩子大
            {
                j+=1;
            }
            if(arr[k]>=arr[j])
                break;

            swap(arr[k],arr[j]);
            k=j;
        }
}
//原地堆排序
void heapSort(int arr[],int n)//在原数组上进行排序 不需要另外再开一个空间
{
    for(int i=(n-1)/2;i>=0;i--)//heapify    先进行一次heapify  当然现在数组是以0为下标开始的
    {
        __shiftDown(arr,n,i);
    }
    for(int i=n-1;i>0;i--) //然后将最大的换到后面  然后此时前n-1个又不满足大顶堆,再从开始处shiftdown
    {
        swap(arr[0],arr[i]);
        __shiftDown(arr,i,0);
    }

}





int  main()
{
    MaxHeap  maxheap=MaxHeap(100);
    int arr[100];
    for(int i=0;i<100;i++)
    {
       arr[i]=100-i;
    }
     for(int i=0;i<100;i++)
    {
        cout<<arr[i]<<" ";
    }
    cout<<endl;
    cout<<"-----------"<<endl;
   /* while(!maxheap.isEmpty())
    {
        cout<<maxheap.extractMax()<<" ";
    }*/
    heapSort1(arr,100);
    for(int i=0;i<100;i++)
    {
        cout<<arr[i]<<" ";
    }
    cout<<endl;
    cout<<"-----------"<<endl;

    heapSort2(arr,100);//效率还是快的
    for(int i=0;i<100;i++)
    {
        cout<<arr[i]<<" ";
    }
        cout<<endl;
    cout<<"-----------"<<endl;
    heapSort(arr,100);//效率还是快的
    for(int i=0;i<100;i++)
    {
        cout<<arr[i]<<" ";
    }
    return 0;
}
原文地址:https://www.cnblogs.com/libin123/p/11448428.html