zoukankan      html  css  js  c++  java
  • 堆与堆排序

    实现一个堆

    实现堆并从堆顶依次取出元素的过程实现了一个简单的排序

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <ctime>
    #include <cmath>
    #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; // 在此轮循环中,data[k]和data[j]交换位置
                if( j+1 <= count && data[j+1] > data[j] )
                    j ++;
                // data[j] 是 data[2*k]和data[2*k+1]中的最大值
    
                if( data[k] >= data[j] ) break;
                swap( data[k] , data[j] );
                k = j;
            }
        }
    
    public:
        // 构造函数, 构造一个空堆, 可容纳capacity个元素
        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;
        }
    
        // 像最大堆中插入一个新的元素 item
        void insert(Item item){
            assert( count + 1 <= capacity );
            data[count+1] = item;
            shiftUp(count+1);
            count ++;
        }
    
        // 从最大堆中取出堆顶元素, 即堆中所存储的最大数据
        Item extractMax(){
            assert( count > 0 );
            Item ret = data[1];
    
            swap( data[1] , data[count] );
            count --;
            shiftDown(1);
    
            return ret;
        }
    
        // 获取最大堆中的堆顶元素
        Item getMax(){
            assert( count > 0 );
            return data[1];
        }
    
    };
    
    
    // 测试最大堆
    int main() {
    
        MaxHeap<int> maxheap = MaxHeap<int>(100);
    
        srand(time(NULL));
        int n = 100;    // 随机生成n个元素放入最大堆中
        for( int i = 0 ; i < n ; i ++ ){
            maxheap.insert( rand()%100 );
        }
    
        int* arr = new int[n];
        // 将maxheap中的数据逐渐使用extractMax取出来
        // 取出来的顺序应该是按照从大到小的顺序取出来的
        for( int i = 0 ; i < n ; i ++ ){
            arr[i] = maxheap.extractMax();
            cout<<arr[i]<<" ";
        }
        cout<<endl;
    
        // 确保arr数组是从大到小排列的
        for( int i = 1 ; i < n ; i ++ )
            assert( arr[i-1] >= arr[i] );
    
        delete[] arr;
    
    
        return 0;
    }
    

    一段在控制台打印树的代码

      // 以树状打印整个堆结构
        void testPrint(){
    
            // 我们的testPrint只能打印100个元素以内的堆的树状信息
            if( size() >= 100 ){
                cout<<"This print function can only work for less than 100 int";
                return;
            }
    
            // 我们的testPrint只能处理整数信息
            if( typeid(Item) != typeid(int) ){
                cout <<"This print function can only work for int item";
                return;
            }
    
            cout<<"The max heap size is: "<<size()<<endl;
            cout<<"Data in the max heap: ";
            for( int i = 1 ; i <= size() ; i ++ ){
                // 我们的testPrint要求堆中的所有整数在[0, 100)的范围内
                assert( data[i] >= 0 && data[i] < 100 );
                cout<<data[i]<<" ";
            }
            cout<<endl;
            cout<<endl;
    
            int n = size();
            int max_level = 0;
            int number_per_level = 1;
            while( n > 0 ) {
                max_level += 1;
                n -= number_per_level;
                number_per_level *= 2;
            }
    
            int max_level_number = int(pow(2, max_level-1));
            int cur_tree_max_level_number = max_level_number;
            int index = 1;
            for( int level = 0 ; level < max_level ; level ++ ){
                string line1 = string(max_level_number*3-1, ' ');
    
                int cur_level_number = min(count-int(pow(2,level))+1,int(pow(2,level)));
                bool isLeft = true;
                for( int index_cur_level = 0 ; index_cur_level < cur_level_number ; index ++ , index_cur_level ++ ){
                    putNumberInLine( data[index] , line1 , index_cur_level , cur_tree_max_level_number*3-1 , isLeft );
                    isLeft = !isLeft;
                }
                cout<<line1<<endl;
    
                if( level == max_level - 1 )
                    break;
    
                string line2 = string(max_level_number*3-1, ' ');
                for( int index_cur_level = 0 ; index_cur_level < cur_level_number ; index_cur_level ++ )
                    putBranchInLine( line2 , index_cur_level , cur_tree_max_level_number*3-1 );
                cout<<line2<<endl;
    
                cur_tree_max_level_number /= 2;
            }
        }
    
    private:
        void putNumberInLine( int num, string &line, int index_cur_level, int cur_tree_width, bool isLeft){
    
            int sub_tree_width = (cur_tree_width - 1) / 2;
            int offset = index_cur_level * (cur_tree_width+1) + sub_tree_width;
            assert(offset + 1 < line.size());
            if( num >= 10 ) {
                line[offset + 0] = '0' + num / 10;
                line[offset + 1] = '0' + num % 10;
            }
            else{
                if( isLeft)
                    line[offset + 0] = '0' + num;
                else
                    line[offset + 1] = '0' + num;
            }
        }
    
        void putBranchInLine( string &line, int index_cur_level, int cur_tree_width){
    
            int sub_tree_width = (cur_tree_width - 1) / 2;
            int sub_sub_tree_width = (sub_tree_width - 1) / 2;
            int offset_left = index_cur_level * (cur_tree_width+1) + sub_sub_tree_width;
            assert( offset_left + 1 < line.size() );
            int offset_right = index_cur_level * (cur_tree_width+1) + sub_tree_width + 1 + sub_sub_tree_width;
            assert( offset_right < line.size() );
    
            line[offset_left + 1] = '/';
            line[offset_right + 0] = '\';
        }
    

    堆排序

    一种是上面已经实现的排序

    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();
    
    }
    

    heapSort1, 将所有的元素依次添加到堆中, 在将所有元素从堆中依次取出来, 即完成了排序,无论是创建堆的过程, 还是从堆中依次取出元素的过程, 时间复杂度均为O(nlogn),整个堆排序的整体时间复杂度为O(nlogn)

    对其进行优化

    // 构造函数, 通过一个给定数组创建一个最大堆
        // 该构造堆的过程, 时间复杂度为O(n)
        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);
        }
    
    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();
    
    }
    

    heapSort2, 借助我们的heapify过程创建堆,此时, 创建堆的过程时间复杂度为O(n), 将所有元素依次从堆中取出来, 实践复杂度为O(nlogn),堆排序的总体时间复杂度依然是O(nlogn), 但是比上述heapSort1性能更优, 因为创建堆的性能更优

    原地堆排序

    // 不使用一个额外的最大堆, 直接在原数组上进行原地的堆排序
    template<typename T>
    void heapSort(T arr[], int n){
    
        // 注意,此时的堆是从0开始索引的
        // 从(最后一个元素的索引-1)/2开始
        // 最后一个元素的索引 = n-1
        for( int i = (n-1-1)/2 ; i >= 0 ; i -- )
            __shiftDown2(arr, n, i);
    
        for( int i = n-1; i > 0 ; i-- ){
            swap( arr[0] , arr[i] );
            __shiftDown2(arr, i, 0);
        }
    }
    
    // 优化的shiftDown过程, 使用赋值的方式取代不断的swap,
    // 该优化思想和我们之前对插入排序进行优化的思路是一致的
    template<typename T>
    void __shiftDown2(T arr[], int n, int k){
    
        T e = arr[k];
        while( 2*k+1 < n ){
            int j = 2*k+1;
            if( j+1 < n && arr[j+1] > arr[j] )
                j += 1;
    
            if( e >= arr[j] ) break;
    
            arr[k] = arr[j];
            k = j;
        }
    
        arr[k] = e;
    }
    

    索引堆

    #include <iostream>
    #include <cassert>
    #include "SortTestHelper.h"
    
    using namespace std;
    
    // 最大索引堆
    template<typename Item>
    class IndexMaxHeap{
    
    private:
        Item *data;     // 最大索引堆中的数据
        int *indexes;   // 最大索引堆中的索引
    
        int count;
        int capacity;
    
        // 索引堆中, 数据之间的比较根据data的大小进行比较, 但实际操作的是索引
        void shiftUp( int k ){
    
            while( k > 1 && data[indexes[k/2]] < data[indexes[k]] ){
                swap( indexes[k/2] , indexes[k] );
                k /= 2;
            }
        }
    
        // 索引堆中, 数据之间的比较根据data的大小进行比较, 但实际操作的是索引
        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] );
                k = j;
            }
        }
    
    public:
        // 构造函数, 构造一个空的索引堆, 可容纳capacity个元素
        IndexMaxHeap(int capacity){
    
            data = new Item[capacity+1];
            indexes = new int[capacity+1];
    
            count = 0;
            this->capacity = capacity;
        }
    
        ~IndexMaxHeap(){
            delete[] data;
            delete[] indexes;
        }
    
        // 返回索引堆中的元素个数
        int size(){
            return count;
        }
    
        // 返回一个布尔值, 表示索引堆中是否为空
        bool isEmpty(){
            return count == 0;
        }
    
        // 向最大索引堆中插入一个新的元素, 新元素的索引为i, 元素为item
        // 传入的i对用户而言,是从0索引的
        void insert(int i, Item item){
            assert( count + 1 <= capacity );
            assert( i + 1 >= 1 && i + 1 <= capacity );
    
            i += 1;
            data[i] = item;
            indexes[count+1] = i;
            count++;
    
            shiftUp(count);
        }
    
        // 从最大索引堆中取出堆顶元素, 即索引堆中所存储的最大数据
        Item extractMax(){
            assert( count > 0 );
    
            Item ret = data[indexes[1]];
            swap( indexes[1] , indexes[count] );
            count--;
            shiftDown(1);
            return ret;
        }
    
        // 从最大索引堆中取出堆顶元素的索引
        int extractMaxIndex(){
            assert( count > 0 );
    
            int ret = indexes[1] - 1;
            swap( indexes[1] , indexes[count] );
            count--;
            shiftDown(1);
            return ret;
        }
    
        // 获取最大索引堆中的堆顶元素
        Item getMax(){
            assert( count > 0 );
            return data[indexes[1]];
        }
    
        // 获取最大索引堆中的堆顶元素的索引
        int getMaxIndex(){
            assert( count > 0 );
            return indexes[1]-1;
        }
    
        // 获取最大索引堆中索引为i的元素
        Item getItem( int i ){
            assert( i + 1 >= 1 && i + 1 <= capacity );
            return data[i+1];
        }
    
        // 将最大索引堆中索引为i的元素修改为newItem
        void change( int i , Item newItem ){
    
            i += 1;
            data[i] = newItem;
    
            // 找到indexes[j] = i, j表示data[i]在堆中的位置
            // 之后shiftUp(j), 再shiftDown(j)
            for( int j = 1 ; j <= count ; j ++ )
                if( indexes[j] == i ){
                    shiftUp(j);
                    shiftDown(j);
                    return;
                }
        }
    
        // 测试索引堆中的索引数组index
        // 注意:这个测试在向堆中插入元素以后, 不进行extract操作有效
        bool testIndexes(){
    
            int *copyIndexes = new int[count+1];
    
            for( int i = 0 ; i <= count ; i ++ )
                copyIndexes[i] = indexes[i];
    
            copyIndexes[0] = 0;
            std::sort(copyIndexes, copyIndexes + count + 1);
    
            // 在对索引堆中的索引进行排序后, 应该正好是1...count这count个索引
            bool res = true;
            for( int i = 1 ; i <= count ; i ++ )
                if( copyIndexes[i-1] + 1 != copyIndexes[i] ){
                    res = false;
                    break;
                }
    
            delete[] copyIndexes;
    
            if( !res ){
                cout<<"Error!"<<endl;
                return false;
            }
    
            return true;
        }
    };
    

    反向查找表

    #include <iostream>
    #include <cassert>
    #include "SortTestHelper.h"
    
    using namespace std;
    
    // 最大索引堆
    template<typename Item>
    class IndexMaxHeap{
    
    private:
        Item *data;     // 最大索引堆中的数据
        int *indexes;   // 最大索引堆中的索引, indexes[x] = i 表示索引i在x的位置
        int *reverse;   // 最大索引堆中的反向索引, reverse[i] = x 表示索引i在x的位置
    
        int count;
        int capacity;
    
        // 索引堆中, 数据之间的比较根据data的大小进行比较, 但实际操作的是索引
        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;
            }
        }
    
        // 索引堆中, 数据之间的比较根据data的大小进行比较, 但实际操作的是索引
        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:
        // 构造函数, 构造一个空的索引堆, 可容纳capacity个元素
        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;
        }
    
        ~IndexMaxHeap(){
            delete[] data;
            delete[] indexes;
            delete[] reverse;
        }
    
        // 返回索引堆中的元素个数
        int size(){
            return count;
        }
    
        // 返回一个布尔值, 表示索引堆中是否为空
        bool isEmpty(){
            return count == 0;
        }
    
        // 向最大索引堆中插入一个新的元素, 新元素的索引为i, 元素为item
        // 传入的i对用户而言,是从0索引的
        void insert(int i, Item item){
            assert( count + 1 <= capacity );
            assert( i + 1 >= 1 && i + 1 <= capacity );
    
            // 再插入一个新元素前,还需要保证索引i所在的位置是没有元素的。
            assert( !contain(i) );
    
            i += 1;
            data[i] = 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[count]] = 0;
            count--;
    
            if(count){
                reverse[indexes[1]] = 1;
                shiftDown(1);
            }
    
            return ret;
        }
    
        // 从最大索引堆中取出堆顶元素的索引
        int extractMaxIndex(){
            assert( count > 0 );
    
            int ret = indexes[1] - 1;
            swap( indexes[1] , indexes[count] );
            reverse[indexes[count]] = 0;
            count--;
    
            if(count) {
                reverse[indexes[1]] = 1;
                shiftDown(1);
            }
    
            return ret;
        }
    
        // 获取最大索引堆中的堆顶元素
        Item getMax(){
            assert( count > 0 );
            return data[indexes[1]];
        }
    
        // 获取最大索引堆中的堆顶元素的索引
        int getMaxIndex(){
            assert( count > 0 );
            return indexes[1]-1;
        }
    
        // 看索引i所在的位置是否存在元素
        bool contain( int i ){
            assert( i + 1 >= 1 && i + 1 <= capacity );
            return reverse[i+1] != 0;
        }
    
        // 获取最大索引堆中索引为i的元素
        Item getItem( int i ){
            assert( contain(i) );
            return data[i+1];
        }
    
        // 将最大索引堆中索引为i的元素修改为newItem
        void change( int i , Item newItem ){
    
            assert( contain(i) );
            i += 1;
            data[i] = newItem;
    
            // 有了 reverse 之后,
            // 我们可以非常简单的通过reverse直接定位索引i在indexes中的位置
            shiftUp( reverse[i] );
            shiftDown( reverse[i] );
        }
    
        // 测试索引堆中的索引数组index和反向数组reverse
        // 注意:这个测试在向堆中插入元素以后, 不进行extract操作有效
        bool testIndexesAndReverseIndexes(){
    
            int *copyIndexes = new int[count+1];
            int *copyReverseIndexes = new int[count+1];
    
            for( int i = 0 ; i <= count ; i ++ ){
                copyIndexes[i] = indexes[i];
                copyReverseIndexes[i] = reverse[i];
            }
    
            copyIndexes[0] = copyReverseIndexes[0] = 0;
            std::sort(copyIndexes, copyIndexes + count + 1);
            std::sort(copyReverseIndexes, copyReverseIndexes + count + 1);
    
            // 在对索引堆中的索引和反向索引进行排序后,
            // 两个数组都应该正好是1...count这count个索引
            bool res = true;
            for( int i = 1 ; i <= count ; i ++ )
                if( copyIndexes[i-1] + 1 != copyIndexes[i] ||
                        copyReverseIndexes[i-1] + 1 != copyReverseIndexes[i] ){
                    res = false;
                    break;
                }
    
            delete[] copyIndexes;
            delete[] copyReverseIndexes;
    
            if( !res ){
                cout<<"Error!"<<endl;
                return false;
            }
    
            for( int i = 1 ; i <= count ; i ++ )
                if( reverse[ indexes[i] ] != i ){
                    cout<<"Error 2"<<endl;
                    return false;
                }
    
            return true;
        }
    };
    

    最小堆

    #include <algorithm>
    #include <cassert>
    
    using namespace std;
    
    // 最小堆
    template<typename Item>
    class MinHeap{
    
    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 ++;
                if( data[k] <= data[j] ) break;
                swap( data[k] , data[j] );
                k = j;
            }
        }
    
    public:
    
        // 构造函数, 构造一个空堆, 可容纳capacity个元素
        MinHeap(int capacity){
            data = new Item[capacity+1];
            count = 0;
            this->capacity = capacity;
        }
    
        // 构造函数, 通过一个给定数组创建一个最小堆
        // 该构造堆的过程, 时间复杂度为O(n)
        MinHeap(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);
        }
    
        ~MinHeap(){
            delete[] data;
        }
    
        // 返回堆中的元素个数
        int size(){
            return count;
        }
    
        // 返回一个布尔值, 表示堆中是否为空
        bool isEmpty(){
            return count == 0;
        }
    
        // 向最小堆中插入一个新的元素 item
        void insert(Item item){
            assert( count + 1 <= capacity );
            data[count+1] = item;
            shiftUp(count+1);
            count ++;
        }
    
        // 从最小堆中取出堆顶元素, 即堆中所存储的最小数据
        Item extractMin(){
            assert( count > 0 );
            Item ret = data[1];
            swap( data[1] , data[count] );
            count --;
            shiftDown(1);
            return ret;
        }
    
        // 获取最小堆中的堆顶元素
        Item getMin(){
            assert( count > 0 );
            return data[1];
        }
    };
    

    索引最小堆

    #include <iostream>
    #include <algorithm>
    #include <cassert>
    
    using namespace std;
    
    // 最小索引堆
    template<typename Item>
    class IndexMinHeap{
    
    private:
        Item *data;     // 最小索引堆中的数据
        int *indexes;   // 最小索引堆中的索引, indexes[x] = i 表示索引i在x的位置
        int *reverse;   // 最小索引堆中的反向索引, reverse[i] = x 表示索引i在x的位置
    
        int count;
        int capacity;
    
        // 索引堆中, 数据之间的比较根据data的大小进行比较, 但实际操作的是索引
        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;
            }
        }
    
        // 索引堆中, 数据之间的比较根据data的大小进行比较, 但实际操作的是索引
        void shiftDown( int k ){
    
            while( 2*k <= count ){
                int j = 2*k;
                if( j + 1 <= count && data[indexes[j]] > data[indexes[j+1]] )
                    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:
        // 构造函数, 构造一个空的索引堆, 可容纳capacity个元素
        IndexMinHeap(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;
        }
    
        ~IndexMinHeap(){
            delete[] data;
            delete[] indexes;
            delete[] reverse;
        }
    
        // 返回索引堆中的元素个数
        int size(){
            return count;
        }
    
        // 返回一个布尔值, 表示索引堆中是否为空
        bool isEmpty(){
            return count == 0;
        }
    
        // 向最小索引堆中插入一个新的元素, 新元素的索引为i, 元素为item
        // 传入的i对用户而言,是从0索引的
        void insert(int index, Item item){
            assert( count + 1 <= capacity );
            assert( index + 1 >= 1 && index + 1 <= capacity );
    
            index += 1;
            data[index] = item;
            indexes[count+1] = index;
            reverse[index] = count+1;
            count++;
            shiftUp(count);
        }
    
        // 从最小索引堆中取出堆顶元素, 即索引堆中所存储的最小数据
        Item extractMin(){
            assert( count > 0 );
    
            Item ret = data[indexes[1]];
            swap( indexes[1] , indexes[count] );
            reverse[indexes[count]] = 0;
            count--;
    
            if(count){
                reverse[indexes[1]] = 1;
                shiftDown(1);
            }
    
            return ret;
        }
    
        // 从最小索引堆中取出堆顶元素的索引
        int extractMinIndex(){
            assert( count > 0 );
    
            int ret = indexes[1] - 1;
            swap( indexes[1] , indexes[count] );
            reverse[indexes[count]] = 0;
            count--;
    
            if(count){
                reverse[indexes[1]] = 1;
                shiftDown(1);
            }
    
            return ret;
        }
    
        // 获取最小索引堆中的堆顶元素
        Item getMin(){
            assert( count > 0 );
            return data[indexes[1]];
        }
    
        // 获取最小索引堆中的堆顶元素的索引
        int getMinIndex(){
            assert( count > 0 );
            return indexes[1]-1;
        }
    
        // 看索引i所在的位置是否存在元素
        bool contain( int index ){
    
            return reverse[index+1] != 0;
        }
    
        // 获取最小索引堆中索引为i的元素
        Item getItem( int index ){
            assert( contain(index) );
            return data[index+1];
        }
    
        // 将最小索引堆中索引为i的元素修改为newItem
        void change( int index , Item newItem ){
    
            assert( contain(index) );
            index += 1;
            data[index] = newItem;
    
            shiftUp( reverse[index] );
            shiftDown( reverse[index] );
        }
    
    };
    
  • 相关阅读:
    Anaconda安装(python2和python3版本)
    windows系统同时安装python2和python3的详细步骤
    Java 重写和重载的区别
    Windows Internals 笔记——用内核对象进行线程同步
    公考之行测笔记3
    公考之行测笔记2
    公考之行测笔记
    Docker: 简要分析内核问题
    Docker: 仓库管理
    Docker: 认识与使用
  • 原文地址:https://www.cnblogs.com/ygjzs/p/12727498.html
Copyright © 2011-2022 走看看