zoukankan      html  css  js  c++  java
  • 大顶堆基本操作(插入,出堆),堆排序(普通,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;
    }
  • 相关阅读:
    LVS基于DR模式负载均衡的配置
    Linux源码安装mysql 5.6.12 (cmake编译)
    HOSt ip is not allowed to connect to this MySql server
    zoj 3229 Shoot the Bullet(无源汇上下界最大流)
    hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割
    poj 2391 Ombrophobic Bovines(最大流+floyd+二分)
    URAL 1430 Crime and Punishment
    hdu 2048 神、上帝以及老天爷(错排)
    hdu 3367 Pseudoforest(最大生成树)
    FOJ 1683 纪念SlingShot(矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/libin123/p/11448428.html
Copyright © 2011-2022 走看看