排序算法-堆排序

堆用在动态数据排序中非常合适

以1索引为开始节点,parent(i) = i /2,left_child (i) =2*i ; right_child(i) = 2*i +1; 最后一个非叶子节点的索引count/2 

以0索引为开始节点,parent(i) = (i-1)/2, left_child (i) =2*i +1; right_child(i) = 2*i +2; 最后一个非叶子节点的索引(count -1)/2 

实现一个最大堆

//最大堆
template<typename Item>
class MaxHeap{
private:
    Item* data;
    int count;
    int capacity;

    void shiftUp(int k){
        while(k>1 && data[k/2] < data[k]){
            swap(data[k/2],data[k]);
            k /= 2;
        }
    }
    void shiftDown(int k){
        while (2*k <= count){
            int j = 2*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 Item[capacity+1];
        count=0;
        this->capacity = capacity;
    }
    ~MaxHeap(){
        delete [] data;
    }
    int size(){
        return count;
    }
    bool isEmpty(){
        return count ==0;
    }
    void insert(Item item){
        assert(count+1 <= capacity);
        data[count +1] = item;
        count++;
        shiftUp(count);
    }
    Item extractMax(){
        assert(count >0);
        Item ret = data[1];
        swap(data[1],data[count]);
        count --;
        shiftDown(1);
        return ret;
    }
};

 数组变成堆heapify

#ifndef SELECTIONSORT_HEAP_H
#define SELECTIONSORT_HEAP_H
#include <iostream>
#include <ctime>
#include <cassert>
using namespace std;

//最大堆
template<typename Item>
class MaxHeap{
private:
    Item* data;
    int count;
    int capacity;

    void shiftUp(int k){
        while(k>1 && data[k/2] < data[k]){
            swap(data[k/2],data[k]);
            k /= 2;
        }
    }
    void shiftDown(int k){
        while (2*k <= count){
            int j = 2*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 Item[capacity+1];
        count=0;
        this->capacity = capacity;
    }
    //heapfiy
    MaxHeap(Item arr[],int n){
        data = new Item[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(Item item){
        assert(count+1 <= capacity);
        data[count +1] = item;
        count++;
        shiftUp(count);
    }
    Item extractMax(){
        assert(count >0);
        Item ret = data[1];
        swap(data[1],data[count]);
        count --;
        shiftDown(1);
        return ret;
    }
};

#endif

堆排序实现

template<typename T>
void heapSort1(T arr[],int n){
    MaxHeap<T> maxheap = MaxHeap<T>(n);
    for(int i=0;i<n;i++)
        maxheap.insert(arr[i])
    for(int i =n-1;i>=0;i--)
        arr[i] = maxheap.extractMax();
}

template<typename T>
void heapSort2(T arr[],int n){
    MaxHeap<T> maxheap = MaxHeap<T>(arr,n);
    for(int i =n-1;i>=0;i--)
        arr[i] = maxheap.extractMax();
}

 原地堆排序

template<typename T>
void __shiftDown(T arr[],int n,int k){
    while (2*k+1 <= n){
            int j = 2*k+1;
            if(j+1 < n && arr[j+1] >arr[j])
                j+=1
            if(arr[k] >= arr[j])
                break;
            swap(arr[k],arr[j]);
            k=j;
    }
}

template<typename T>
void heapSort(T arr[],int n){
    //heapify
    for(int i =(n-1)/2 ;i>=0;i--)
        __shiftDown(arr,n,i);
    for(int i = n-1;i>0 ;i--)
        swap(arr[0],arr[i]);
        __shiftDown(arr,i,0)
}

 索引最大堆

//索引最大堆
template<typename Item>
class IndexMaxHeap{
private:
    Item* data;
    int* indexes;
    int* reverse;
    int count;
    int capacity;

    void shiftUp(int k){
        while(k>1 && data[indexes[k/2]] < data[indexes[k]]){
            swap(indexes[k/2],indexes[k]);
            reverse[indexes[k/2]] = k/2;
            reverse[indexes[k]]=k;
            k /= 2;
        }
    }
    void shiftDown(int k){
        while (2*k <= count){
            int j = 2*k;
            if(j+1 <= count && data[indexes[j+1]] >data[indexes[j]])
                j+=1
            if(data[indexes[k]] >= data[indexes[j]])
                break;
            swap(indexes[k],indexes[j]);
            reverse[indexes[k]] = k;
            reverse[indexes[j]] = j;
            k=j;
        }
        
    }
public:
    IndexMaxHeap(int capacity){
        data = new Item[capacity+1];
        indexes = new int[capacity+1];
        reverse = new int[capacity+1];
        for(int i=0;i<=capacity;i++)
            reverse[i]=0;
        count=0;
        this->capacity = capacity;
    }
    ~MaxHeap(){
        delete [] data;
        delete [] indexes;
        delete [] reverse;
    }
    int size(){
        return count;
    }
    bool isEmpty(){
        return count ==0;
    }
    //传入的i对于用户而言,是从0开始索引的
    void insert(int i,Item item){
        assert(count+1 <= capacity);
        assert(i+1 >=1 && i+1 <=capacity);
        i+=1;
        data[1] = item;
        indexes[count+1] = i;
        reverse[i] = count+1;
        count++;
        shiftUp(count);
    }
    Item extractMax(){
        assert(count >0);
        Item ret = data[indexes[1]];
        swap(indexes[1],indexes[count]);
        reverse[indexes[1]] = 1;
        reverse[indexes[count]] = 0;
        count --;
        shiftDown(1);
        return ret;
    }
    int extractMaxIndex(){
        assert(count >0);
        int ret = indexes[1] -1;
        swap(indexes[1],indexes[count]);
        reverse[indexes[1]] = 1;
        reverse[indexes[count]] = 0;
        count --;
        shiftDown(1);
        return ret;
    }
    bool contain(int i){
        assert(i+1 >= 1 && i+1 <= capacity)
        return reverse[i+1] != 0;
    }
    Item getItem(int i){
        assert(contain(i))
        return data[i+1];
    }

    void change(int i,Item newItem){
        assert(contain(i))
        i+=1;
        data[i] = newItem;
        //找到indexes[j] = i,j表示data[i]在堆中的位置
        // 之后shiftUp,再shiftDown
        // for(int j =1;j<=count;j++)
        //     if(indexes[j] ==i){
        //         shiftUp(j);
        //         shiftDown(j);
        //         return;
        //     }
        int j  = reverse[i];
        shiftUp(j);
        shiftDown(j);
    }
};
原文地址:https://www.cnblogs.com/Erick-L/p/12595129.html