最大堆及堆排序的实现

来源:互联网 发布:淘宝电商夜鹰好吗 编辑:程序博客网 时间:2024/04/30 02:36

堆数据结构用于排序算法中,空间复杂度O(1),时间复杂度O(NlogN),但是在实践中还是不如快速排序(好像快速排序可以更好的利用硬件特性)。堆的意义就在于:最快的找到最大/最小值,在堆结构中插入一个值重新构造堆结构,取走最大/最下值后重新构造堆结构 其时间复杂度为O(logN),而其他方法最少为O(N).堆实践中用途不在于排序,其主要用在调度算法中,比如优先级调度,每次取优先级最高的,时间驱动,取时间最小/等待最长的 等等 ,分为最大堆/最小堆。

这里讨论最大堆,最小堆与最大堆类似。

void MaxHeapify(int i):移动一个指定的元素使其符合最大堆。

void BuildMaxHeap():对已知的数组元素构造最大堆。通过调用MaxHeapify来实现。

T Maximum():返回最大值。

T ExtractMaximum():提取最大值,堆中元素少一,提取后还是一个最大堆。

void IncreaseKey(int i, T key):对指定位置的元素进行增大操作,操作后仍为最大堆。

void HeapInsert(T key):在最大堆中执行插入操作,先在数组最后边添加一个无穷小元素,然后调用IncreaseKey来实现。

void HeapSort():对最大堆进行排序,注意,排序后的数组不再是最大堆。

下面是具体的实现:

template <typename T>
class MaxHeap
{
public:
    MaxHeap(
int max_size, int cur_size, T data[]) : cur_size_(cur_size), max_size_(max_size)
    
{
        
if (max_size_ < cur_size_)
            
throw logic_error("Maximum size must no more less then the current size!");

        heap_ 
= new T[max_size_ + 1];
        copy(data, data 
+ cur_size_, heap_ + 1);
    }

    
~MaxHeap() 
    
{
        delete []heap_;
    }

    
void MaxHeapify(int i)
    
{
        
int l = left(i);
        
int r = right(i);
        
int largest = i;

        
if (l <= cur_size_ && heap_[l] > heap_[largest])
            largest 
= l;

        
if (r <= cur_size_ && heap_[r] > heap_[largest])
            largest 
= r;

        
if (largest != i)
        
{
            swap(heap_[largest], heap_[i]);
            MaxHeapify(largest);
        }

    }

    
void BuildMaxHeap()
    
{
        
for (int i = cur_size_ / 2; i >= 1; i--)
        
{
            MaxHeapify(i);
        }

    }

    T Maximum()
    
{
        
return heap_[1];
    }

    T ExtractMaximum()
    
{
        
if (cur_size_ <= 1)
            
throw logic_error("No element in max heap!");

        T max 
= heap_[1];
        heap_[
1= heap_[cur_size_];
        cur_size_
--;
        MaxHeapify(
1);

        
return max;
    }

    
void IncreaseKey(int i, T key)
    
{
        
if (key < heap_[i])
            
throw logic_error("the new key is smaller than current key!");

        heap_[i] 
= key;
        
while (i > 1 && heap_[parent(i)] < heap_[i])
        
{
            swap(heap_[parent(i)], heap_[i]);
            i 
= parent(i);
        }

    }

    
void HeapInsert(T key)
    
{
        
if (max_size_ <= cur_size_)
            
throw logic_error("The heap is out of size, can't insert!");

        cur_size_
++;
        heap_[cur_size_] 
= T(-0xFFFF);
        IncreaseKey(cur_size_, key);
    }
    
    
void HeapSort()
    
{
        
int tmp_size = cur_size_;
        
for (int i = tmp_size; i > 1; i--)
        
{
            swap(heap_[
1], heap_[i]); 
            cur_size_
--;
            MaxHeapify(
1);
        }

        
// restore the size
        cur_size_ = tmp_size;
    }

    ostream
& print(ostream& out
    
{
        copy(heap_ 
+ 1, heap_ + cur_size_ + 1, ostream_iterator<T>(out" ")); 
        
return out
    }
    

private:
    
int parent(int i) return i / 2; }
    
int left(int i)   return i * 2; }
    
int right(int i)  return i * 2 + 1; }

private:
    
int cur_size_;
    
int max_size_;
    T
* heap_;
}
;

template 
<typename T>
ostream
& operator <<(ostream& out, MaxHeap<T>& mh)
{
    
return mh.print(out);
}

下面是测试代码:

int main()
{
    
int data[10= {4132169101487};
    
int count = sizeof(data) / sizeof(int);

    MaxHeap
<int> mh(2 * count, count, data);
    cout 
<< "Before build: " << mh << endl;

    mh.BuildMaxHeap();
    cout 
<< "After build: " << mh << endl;

    mh.HeapSort();
    cout 
<< "After sort: " << mh << endl;

    
return getchar();
}