算法导论第6章讲了堆排序和优先队列,包括最小、最大。堆排序主要由几个部分组成:
一个是维护堆的根结点最大的算法,该算法要求孩子结点已经是最大堆,否则不能调用。
第二个就是建堆算法,从不是叶子结点的第一个数开始(即n/2,假设n个数),递减到1,调用维护最大堆的算法,因为叶子结点已经是最大堆,从后调用已经满足最大堆的性质。
第三个算法就是堆排序的算法,该算法思想是用根结点与最后一个结点的元素互换,并调用维护堆的算法。然后将堆的大小减1,如此继续下去。便实现了堆排序。
接下来是优先队列,优先队列主要讲了几个操作:
1.返回队列中的最大值:运用最大堆实现的队列,直接返回堆顶元素即可。
2. 剔除最大值:基于最大堆,直接将堆顶元素与末元素替换,然后维护堆,并减size,该算法与heap-sort的操作类似。
3. 改变某个元素的大小:基于最大堆,先判断改变的是否大于原元素本身,如果是的话,直接将该元素替换,并且从新建立最大堆。
4.插入某个元素:将元素插入到末尾,然后调用3的算法,便直接可以完成。
所有的都是基于数组这个结构来实现最大堆的,假设数组的大小为m,堆的大小为size,则size<=m,即堆只是数组中的一部分。
有些实现细节的问题,暂时没有详细写出来,有问题可以留言探讨。
下面贴代码:关于由链表和栈的习题代码暂时没贴,等到栈的那章在补上!
// copyright
// author:huang xiaopeng
/*
* this is the answer of chapter 6,heap sort
* i write basically all the program that i can solve,
* and i think i write it all down ,
* this answer just in code,some problem whichs are need to be proved,
* i do not do it, beacuse i think those just math,you can do it in paper by yourself
* so the answers are as follows
*/
#include<iostream>
using namespace std;
int Parent(int& i)
{
return (i - 1) / 2;
}
int Left(int& i)
{
return 2 * i + 1;
}
int Right(int& i)
{
return 2 * i + 2;
}
// MAX-HEAPIFY
//in order to rebuild the maxheap
template<class T>
void exchange(T& a, T& b) //subprogram,just to exchange two elements
{
T c=a;
a = b;
b = c;
}
template<class T>
void MAX_HEAPIFY(T* A, int i, int size)
{
try {
if (i <= size) {
int largest;
int l = Left(i);
int r = Right(i);
if (l <= size&&A[l] > A[i])
largest = l;
else
largest = i;
if (r <= size&&A[r] > A[largest])
largest = r;
if (largest != i)
{
exchange(A[i], A[largest]);
MAX_HEAPIFY(A, largest, size);
}
}
else
{
throw("this is an error due to the element is beyond the arraysize");
}
}
catch (char* s) {
cout << "this is error";
}
}
//this is the meathod to build a maxheap
template<class T>
void BUILD_MAX_HEAP(T* A, int size)
{
int length = size / 2-1;
for (int i = length; i >= 0; i--)
MAX_HEAPIFY(A, i, size);
}
//the way to bulid heapsort
template<class T>
void HeapSort(T* A, int size)
{
BUILD_MAX_HEAP(A, size);
for (int i = size; i >= 1; i--)
{
exchange(A[i], A[0]);
size -= 1;
MAX_HEAPIFY(A, 0, size);
}
}
//and this is about priority queue
//HEAP-MAXIMUM(A)
template<class T>
T HEAP_MAXIMUM(T* A,int size)
{
if (size <= 0)
throw("this is no element in it,error!!");
return A[0];
}
//HEAP-EXTRACT-MAX(A)
template<class T>
T Heap_Extract_Max(T* A, int size)
{
if (size < 1)
throw("this is an error,heap underflow");
T max = A[0];
A[0] = A[size];
size--;
MAX_HEAPIFY(A, 0,size);
return max;
}
//HEAP-INCREASE-KEY(A,i,key)
template<class T >
void Heap_Increase_Key(T* A, int i, T key)
{
int p=Parent(i);
try {
if (key < A[i])
throw("error,can't add the number less than privious!");
}
catch (char* s)
{
cout <<"this is a big error " << endl;
}
A[i] = key;
while (i >0 && A[p] < A[i])
{
exchange(A[i], A[p]);
i = p;
p = Parent(i);
}
}
//MAX-HEAP-INSERT
template<class T>
void Max_Heap_Insert(T* A,T key,int size)
{
size++;
key--;
A[size] = key;
key++;
Heap_Increase_Key(A, size, key);
}
//solution to 6.2-2
template<class T>
void MIN_HEAPIFY(T *A, int i, int size)
{
if (i <= size)
{
int l = Left(i);
int R = Right(i);
int smallest;
if (l <= size&&A[l] < A[i])
smallest = l;
else
smallest = i;
if (R <= size&&A[R] < A[smallest])
smallest = R;
if (i != smallest)
{
exchange(A[i], A[smallest]);
MIN_HEAPIFY(A,smallest,size);
}
}
}
//solution to 6.2-5 ,recusive version of MAX-HEAPIFY
template<class T>
void MAX_HEAPIFY_recusive(T* a, int i,int size)
{
int l;
int r ;
int largest ;
do {
l = Left(i);
r = Right(i);
if (l <= size&&a[l] > a[i])
largest = l;
else
largest = i;
if (r <= size&&a[r] > a[largest])
largest = r;
exchange(a[i], a[largest]);
} while (i != largest);
}
//*************************************************************************
//solution to 6.5-3 to realize the smallest priority queue
template<class T>
void BUILD_Min_HEAP(T* A, int size)
{
int length = size / 2 - 1;
for (int i = length; i >= 0; i--)
MIN_HEAPIFY(A, i, size);
}
template<class T>
T Minimum(T* A,int size)
{
if (size <= 0)
throw("error!");
return A[0];
}
template<class T>
T Heap_Extract_Min(T* A, int size)
{
if (size < 1)
throw("error!");
T min = A[0];
A[0] = A[size];
size--;
MIN_HEAPIFY(A, 0, size);
return min;
}
template<class T>
void Heap_decrease_key(T* A, int i, T key)
{
int p = Parent(i);
if (key >A[i])
throw("error!!");
A[i] = key;
while (i > 0 && A[p] > A[i])
{
exchange(A[p], A[i]);
i = p;
p = Parent(i);
}
}
template<class T>
void MIN_heap_insert(T* A, int size, T key)
{
size++;
key++;
A[size] = key;
key--;
Heap_decrease_key(A, size, key);
}
//******************************************************************************************************
//solution to 6.5-6
template<class T >
void Heap_Increase_Key_onecopy(T* A, int i, T key)
{
int p = Parent(i);
try {
if (key < A[i])
throw("error,can't add the number less than privious!");
}
catch (char* s)
{
cout << "this is a big error " << endl;
}
A[i] = key;
while (i >0 && A[p] < A[i])
{
A[i] = A[p];
i = p;
p = Parent(i);
}
A[p] = key;
}
//***********************************************************************
//solution to 6.5-8
template<class T>
T Heap_delete(T* a, int i, int size)
{
T temp = a[i];
if (a[i] == a[size])
a[i] = a[size];
if (a[i] > a[size])
{
a[i] = a[size];
size--;
MAX_HEAPIFY(a, i, size);
}
else
{
Heap_Increase_Key(a, i, a[size]);
size--;
}
return temp;
}
int main()
{
int A[11] = { 16,4,10,14,7,9,3,2,8,1 };
BUILD_MAX_HEAP(A, 10);
for (int i = 0; i < 10; i++)
cout << A[i] << " ";
cout << endl;
Heap_Increase_Key_onecopy(A, 2, 100);
for (int i = 0; i < 10; i++)
cout << A[i] << " ";
cout << endl;
int c;
c = Heap_delete(A, 4,10);
for (int i = 0; i < 10; i++)
cout << A[i] << " ";
cout << endl;
/*
cout << "this is build max heap! " << endl;
BUILD_Min_HEAP(A, 10);
for (int i = 0; i < 10; i++)
cout << A[i] << " ";
cout << endl;
cout << "this return the max element in it " << endl;
int x;
x=Minimum(A, 10);
cout << x << endl;
cout << "this extract the max element" << endl;
Heap_Extract_Min(A, 10);
for (int i = 0; i < 10; i++)
cout << A[i] << " ";
cout << endl;
cout << "this is increase the element which number is 2 to 20" << endl;
Heap_decrease_key(A, 2, -22);
for (int i = 0; i < 10; i++)
cout << A[i] << " ";
cout << endl;
cout << "this is insert the element 200 to the postion of 10" << endl;
MIN_heap_insert(A, 9, -2);
for (int i = 0; i < 10; i++)
cout << A[i] << " ";
cout << endl;
*/
return 0;
}