欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++实现堆、最大堆、最小堆 -- 堆排序插入删除操作

程序员文章站 2024-02-13 16:13:22
...
堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。
最大堆和最小堆是二叉堆的两种形式。
最大堆:根结点的键值是所有堆结点键值中最大者。
最小堆:根结点的键值是所有堆结点键值中最小者。
而最大-最小堆集结了最大堆和最小堆的优点,这也是其名字的由来。
最大-最小堆是最大层和最小层交替出现的二叉树,即最大层结点的儿子属于最小层,最小层结点的儿子属于最大层。
以最大(小)层结点为根结点的子树保有最大(小)堆性质:根结点的键值为该子树结点键值中最大(小)项。 
                                                                                                                                                                                              
一:堆
  我们构建一个堆类,用最大堆和最小堆来继承他。

#ifndef _HEAP_H  
#define _HEAP_H  
  
#include <iostream>  
using namespace std;  
  
enum{DEFAULT_SIZE = 10};  
  
template <typename T>  
class Heap{  
public:  
    Heap() = default;  
    virtual ~Heap() = default;  
public:   
    virtual void show_heap()const = 0;  
    virtual bool insert_heap(const T&) = 0;  
    virtual bool remove_heap(T &) = 0;  
};  
  
//public interface  
  
#endif   /*Heap.h*/  

二:最大堆

  下面是最大堆的实现:

#ifndef _MAXHEAP_H  
#define _MAXHEAP_H  
  
#include <iostream>  
  
#include "Heap.h"  
  
template <typename T>  
class MaxHeap : public Heap<T>{  
public:  
    MaxHeap(int);  
    MaxHeap(const T [], const int);  
    ~MaxHeap();  
public:  
    bool insert_heap(const T&);  
    bool remove_heap(T &);  
  
    void show_heap()const;  
protected:  
    void sift_down(int, int);  
    void sift_up(int);  
private:  
    T *heap;  
    int size;  
    int capacity;  
};  
  
//public interface  
  
template <typename T>  
MaxHeap<T>::MaxHeap(int sz = DEFAULT_SIZE)  
{  
    capacity = sz > DEFAULT_SIZE ? sz : DEFAULT_SIZE;  
    heap = new T[capacity];  
    assert(heap != NULL);  
    size = 0;  
}  
  
template <typename T>  
MaxHeap<T>::MaxHeap(const T arr[], const int arrSize)  
{  
    capacity = arrSize > DEFAULT_SIZE ? arrSize : DEFAULT_SIZE;  
    heap = new T[capacity];  
    assert(heap != NULL);  
    size = arrSize;  
  
    for(int i=0; i<size; ++i)  
        heap[i] = arr[i];  
      
    int curPos = size/2 - 1;  
    while(curPos >= 0){  
        sift_down(curPos, size-1);  
        --curPos;  
    }  
      
}  
  
template <typename T>  
MaxHeap<T>::~MaxHeap()  
{  
    delete []heap;  
    heap = NULL;  
    capacity = size = 0;  
}  
  
template <typename T>  
bool MaxHeap<T>::insert_heap(const T& val)  
{  
    if(size >= capacity)  
        return false;  
      
    heap[size] = val;  
    sift_up(size);  
    ++size;  
    return true;  
}  
  
template <typename T>  
bool MaxHeap<T>::remove_heap(T &val)  
{  
    if(size <= 0)  
        return false;  
      
    val = heap[0];  
    heap[0] = heap[size-1];  
    --size;  
    sift_down(0, size-1);  
    return true;  
}  
  
template <typename T>  
void MaxHeap<T>::show_heap()const  
{  
    for(int i=0; i<size; ++i)  
        std::cout << heap[i] << " ";  
    std::cout << std::endl;  
}  
  
//protected interface  
  
template <typename T>  
void MaxHeap<T>::sift_down(int start, int end)  
{  
    int i = start;  
    int j = i*2 + 1;  
  
    T tmp = heap[i];  
    while(j <= end){  
        if(j+1 <= end && heap[j] < heap[j+1])  
            ++j;  
        if(tmp < heap[j])  
            heap[i] = heap[j];  
        else  
            break;  
  
        i = j;  
        j = j*2 + 1;  
    }  
    heap[i] = tmp;  
}  
  
template <typename T>  
void MaxHeap<T>::sift_up(int start)  
{  
    int j = start;  
    int i = (start-1) / 2;  
  
    T tmp = heap[j];  
    while(j > 0){  
        if(tmp < heap[i])  
            break;  
        else  
            heap[j] = heap[i];  
          
        j = i;  
        i = (i-1) / 2;  
    }  
    heap[j] = tmp;  
}  
  
#endif   /*MaxHeap.h*/  
三:最小堆
  下面是最小堆的实现:
#ifndef _MINHEAP_H  
#define _MINHEAP_H  
  
#include <assert.h>  
  
#include "Heap.h"  
  
template <typename T>  
class MinHeap : public Heap<T>{  
public:  
    MinHeap(int);  
    MinHeap(const T [], const int );  
    ~MinHeap();  
public:  
    bool insert_heap(const T&);  
    bool remove_heap(T &);  
      
    void show_heap()const;  
protected:  
    void sift_down(int, int);  
    void sift_up(int);  
private:  
    T* heap;  
    int size;  
    int capacity;  
};  
  
//interface  
  
template <typename T>  
MinHeap<T>::MinHeap(int sz = DEFAULT_SIZE)  
{  
    capacity = sz > DEFAULT_SIZE ? sz : DEFAULT_SIZE;  
    heap = new T[capacity];  
    assert(heap != NULL);  
    size = 0;  
}  
  
template <typename T>  
MinHeap<T>::MinHeap(const T arr[], const int arrSize)  
{  
    capacity = arrSize > DEFAULT_SIZE ? arrSize : DEFAULT_SIZE;  
    heap = new T[capacity];  
    assert(heap != NULL);  
    size = arrSize;  
  
    for(int i=0; i<arrSize; ++i)  
        heap[i] = arr[i];  
      
    int curPos = arrSize/2 - 1;  
    while(curPos >= 0){  
        sift_down(curPos, arrSize-1);  
        --curPos;  
    }  
}  
  
template <typename T>  
MinHeap<T>::~MinHeap()  
{  
    delete []heap;  
    heap = NULL;  
    capacity = size = 0;  
}  
  
template <typename T>  
bool MinHeap<T>::insert_heap(const T& val)  
{  
    if(size >= capacity)  
        return false;  
      
    heap[size] = val;  
    sift_up(size);  
    ++size;  
    return true;  
}  
  
template <typename T>  
bool MinHeap<T>::remove_heap(T& val)  
{  
    if(size <= 0)  
        return false;  
      
    val = heap[0];  
    heap[0] = heap[size-1];  
    --size;  
    sift_down(0, size-1);  
    return true;  
}  
  
template <typename T>  
void MinHeap<T>::show_heap()const  
{  
    for(int i=0; i<size; ++i)  
        std::cout << heap[i] << " ";  
    std::cout << std::endl;  
}  
  
//protected interface  
  
template <typename T>  
void MinHeap<T>::sift_down(int start, int end)  
{  
    int i = start;  
    int j = start*2 + 1;  
  
    T tmp = heap[i];  
    while(j <= end){  
        if(j+1 < end && heap[j] > heap[j+1])  
            ++j;  
        if(tmp < heap[j])  
            break;  
        else  
            heap[i] = heap[j];  
          
        i = j;  
        j = j*2 + 1;  
    }  
    heap[i] = tmp;  
}  
  
template <typename T>  
void MinHeap<T>::sift_up(int start)  
{  
    int j = start;  
    int i = (start-1) / 2;  
  
    T tmp = heap[j];  
    while(j > 0){  
        if(tmp > heap[i])  
            break;  
        else  
            heap[j] = heap[i];  
        j = i;  
        i = (i-1) / 2;  
    }  
    heap[j] = tmp;  
}  
  
#endif  

四:测试如下:

#include "MinHeap.h"  
#include "MaxHeap.h"  
#include <iostream>  
using namespace std;  
  
int main()  
{  
    int array[] = {23, 9, 34, 2, 56, 89, 35, 54};  
      
    cout << "***************************MinHeap***************************" << endl;  
    MinHeap<int> min_heap(array, sizeof(array)/sizeof(int));  
      
    min_heap.show_heap();  
    min_heap.insert_heap(1);  
    min_heap.show_heap();  
    for(int i=0; i<9; ++i){  
        int val;  
        min_heap.remove_heap(val);  
        cout << val << " ";  
    }  
    cout << endl;  
      
    MaxHeap<int> max_heap(array, sizeof(array)/sizeof(int));  
    cout << "***************************MaxHeap**************************" << endl;   
    max_heap.show_heap();  
    max_heap.insert_heap(99);  
    max_heap.show_heap();  
    for(int i=0; i<9; ++i){  
        int val;  
        max_heap.remove_heap(val);  
        cout << val << " ";  
    }  
    cout << endl;  
      
    return 0;  
}  
结果如下:
C++实现堆、最大堆、最小堆 -- 堆排序插入删除操作