c++小根堆数组实现

来源:互联网 发布:在线财神网淘宝店 编辑:程序博客网 时间:2024/06/06 11:02

主要功能

最小堆排序(大到小):
void order();
删除首元素:
Type fetch_root();
插入元素:
void insert_item(const Type & item);
void insert_item_faster(const Type & item);//快速版本

关键

  • 向下调整比较关键,即从start结点到end结点逐个调整最小堆:
    void shiftdown(Type* array, int start, int end);
    另外是实现了迭代版本,效果都是一样的;
    void shiftdown_regression(Type* array, int start, int end);
  • 最小堆调整函数:
    int mini_operation(Type* array, int father, int lchild , int rchild);
    保证父结点比左右子都小;

source code

/** * @file mini-complete-binary-heap.cpp * @brief  * @author anribras@gmail.com * @version  * @date 2017-07-04 */#include <string.h>#include <stdio.h>#include <iostream>#include <math.h>#include <stdlib.h>using namespace std;#define min_2(a,b) ((a<b)?(a):(b))#define min_3(a,b,c) min_2(min_2(a,b),min_2(a,c))#define Null (0)/** @brief min_array_heap  * * 最小根堆 最大的作用是从huge数据中找到最小的元素 *           也可以排序 * * * */template<typename Type>class min_array_heap {    private:        int m_size;        Type* m_array;        void swap(Type & a, Type & b) {            Type tmp;            tmp = a;            a = b;            b = tmp;        };        //从i节点开始往下调整,调整到第end个节点,序号从0开始        void shiftdown(Type* array, int start, int end) {            int lchild = 2* start + 1;            int rchild = 2* start + 2;            int min;            while (lchild <= end) {                //cout << "father[" << start << "] = " << array[start] << endl;                //cout << "left child[" << lchild << "] = " << array[lchild] << endl;                //cout << "right child[" << rchild << "] = " << array[rchild] << endl;#if 0                // 左子 < 父亲                if( array[lchild] < array[start]) {                    // 如果 右子存在 且 右子 < 左子                    if (  (rchild < end)  && (array[rchild] < array[lchild]) ) {                        swap(array[rchild],array[start]);                        start ++;                    } else                         swap(array[lchild],array[start]);                } else {                    // 左子 > 父亲 但是右子 < 父亲                    if( (rchild < end) && (array[rchild] < array[start])) {                        swap(array[rchild],array[start]);                        start ++;                    }                }#else                //如果右子超范围了,只比较左子和父亲                 if(rchild >= end) {                    min = min_2(array[start],array[lchild]);                    if (min == array[lchild]) {                        swap(array[lchild],array[start]);                    }                }                 //否则都要比较                else {                    min = min_3(array[start],array[lchild],array[rchild]);                     if( min == array[lchild]) {                        swap(array[lchild],array[start]);                    }                    if (min == array[rchild]) {                        swap(array[rchild],array[start]);                        start++;                    }                }#endif                start = lchild;                lchild = 2* start + 1;                rchild = 2* start + 2;            }        };        //递归版本        void shiftdown_regression(Type* array, int start, int end) {            int lchild = 2* start + 1;            int rchild = 2* start + 2;            if(lchild >  end) return;            if(rchild == end) {                mini_operation(array, start,lchild,rchild);                return;            }            //最后一个无右子,交换左子与父亲即可            if(lchild == end) {                mini_operation(array, start,lchild,lchild);                return ;            }            int offset = mini_operation(array,start,lchild, rchild);            //offset = 0,从左子开始调整            if (offset == 0) {                shiftdown_regression(array,lchild, end);            } else  {                //否则从右子开始调整                shiftdown_regression(array,rchild, end);            }        }        //最小堆操作,将父亲,左子,右子调整好,        //返回偏移是该往左(0),还是往右(1)        int mini_operation(Type* array, int father, int lchild , int rchild) {            int min = min_3(array[father],array[lchild],array[rchild]);            if( min == array[lchild]) {                swap(array[lchild],array[father]);                return 0;            }            if (min == array[rchild]) {                swap(array[rchild],array[father]);                return 1;            }        };    public:        min_array_heap(): m_array(0),m_size(0){};        min_array_heap(const Type array[], int size): m_size(size) {            //因为要动态扩展数组,用realloc更好            //m_array =  new Type[m_size];            m_array =  (Type*)malloc(m_size * sizeof(Type));            memcpy(m_array,array,m_size* sizeof(Type));            update();            //update_reg();        };        ~min_array_heap(){            if(m_array) free(m_array);            m_size = 0;        };        min_array_heap(const min_array_heap & array) {            m_size = array.m_size;            m_array =  new Type[m_size];            memcpy(m_array,array.m_array,m_size* sizeof(Type));        };        min_array_heap & operator=(const min_array_heap & array) {            if(this == &array)                 return *this;            delete [] m_array;            m_size = array.m_size;            m_array =  new Type[m_size];            memcpy(m_array,array,m_size* sizeof(Type));        };        const Type & operator[](int pos) {            return m_array[pos];        };        int  get_size() {return m_size;}        Type get_min_node() {            return m_array[0];        }        //堆初始化        void update() {            int n =  (m_size - 1);            //从最后一个node的父亲往根结点逐个调整            for(int i = (n -1)/2; i >=0; i-- )                shiftdown(m_array,i,n);        }        void update_reg() {            int n =  (m_size - 1);            //从最后一个node的父亲往根结点逐个调整            for(int i = (n -1)/2; i >=0; i-- )                shiftdown_regression(m_array,i,n);        }        //从pos往根结点逐个调整        void update(int pos) {            int n =  pos;            for(int i = (n -1)/2; i >=0; i-- )                shiftdown(m_array,i,n);        }        void insert_item(const Type & item ) {            m_size ++;            m_array=  (Type*)realloc(m_array,m_size*sizeof(Type));            m_array[m_size - 1]  = item;            update();        };        void insert_item_faster(const Type & item ) {            m_size ++;            m_array=  (Type*)realloc(m_array,m_size*sizeof(Type));            m_array[m_size - 1]  = item;            //新插入结点到根结点的序列是已排序的,            //将新结点重新排序, 其他结点不用动,非常快            int start =  m_size - 1;            int father = (start -1) /2 ;            while(father >= 0) {                if(m_array[father] > m_array[start])                    swap(m_array[father],m_array[start]);                else                     break;                start = father;                 father =  (start -1) /2 ;            }        };        int fetch_root(Type* item) {            if(m_size > 0) {                *item =  m_array[0];                m_array[0] = m_array[m_size -1];                m_size --;                update();                //update_reg();                return 0;            } else {                return -1;            }        };        void order() {            int start;            //小根堆排序 是按从大到小的排序。            //每次将root node和最后一个node交换,最小的node放在最后,            //然后重新update从root node到交换node的堆结构            for (start = m_size -1 ;  start > 0 ; start --) {                swap(m_array[0],m_array[start]);                update(start -1);            }        };        void print_array() {            for(int i = 0; i < m_size ; i ++) {                cout << m_array[i] << " ";            }            cout << "\n";        };};/** * @brief main  * @param argc * @param argv[] * @return  */int main (int argc , char* argv[]){    int size = 10;    //int * a  = new int[size];    int a[10] = {61, 33, 33, 70, 13, 22, 18, 68, 5, 10 };    srand((int)time(0));    cout << "original:\n";    for(int i =0;i < size; i ++) {        //a[i] = rand() % 100;        cout << a[i] << " ";     }    cout << "\n";    cout << "in mini_heap:\n";    min_array_heap<int>  mheap(a,size);    mheap.print_array();    int tmp;    mheap.fetch_root(&tmp);    cout << "fetch_root: " << tmp << "\t" << endl;    mheap.print_array();    //cout << "normal insert:\n";    //mheap.insert_item(30);    //mheap.print_array();    //mheap.fetch_root();    tmp  = 10;    cout << "faster insert:\n";    mheap.insert_item_faster(tmp);    mheap.print_array();    cout << "mini_heap order:\n";    mheap.order();    mheap.print_array();    min_array_heap<int>  mheap_t = mheap;    //while(mheap_t.get_size()) {        //mheap_t.fetch_root(&tmp);        //cout << "fetch_root: " << tmp << "\t" << endl;        //mheap_t.print_array();    //}    //cout << "normal insert:\n";    //mheap.insert_item(30);    //mheap.print_array();    //mheap.fetch_root();    //cout << "faster insert:\n";    //mheap.insert_item_faster(10);    //mheap.print_array();    cin.get();    //delete [] a;    return 0;}
原创粉丝点击