大根堆的实现
注意:数据存储在heap数组中,而且是从下标1开始存储的
#ifndef _MAX_HEAP_
#define _MAX_HEAP_
#include <iostream>
#include <assert.h>
using namespace std;
const int HeapIncreMent = 20;
template<typename T>
class MaxHeap
{
public:
MaxHeap(int capacity = 100);
~MaxHeap();
public:
const T& FindMax()const;
bool IsMaxHeap() const;
/*插入或删除元素*/
void Insert(const T& x);
void DeleteMax();
void DeleteMax(T& maxItem);
/*输出堆*/
friend ostream& operator<< <>(ostream& cout,MaxHeap& Heap);
private:
int maxSize;
int curSize;
T* heap;
private:
void BuildHeap();
void HeapAdjust(int hole);
};
template<typename T>
MaxHeap<T>::MaxHeap(int capacity):curSize(0),maxSize(capacity)
{
heap = new T[maxSize];
}
template<typename T>
MaxHeap<T>::~MaxHeap()
{
if (heap != NULL)
{
maxSize = 0;
curSize = 0;
delete[] heap;
heap = NULL;
}
}
template<typename T>
const T& MaxHeap<T>::FindMax() const
{
return heap[1];
}
/*新插入的元素总是和自己的双亲比较,直到找到自己的位置*/
template<typename T>
void MaxHeap<T>::Insert(const T& insertItem)
{
if (curSize == maxSize - 1)
{
maxSize += HeapIncreMent;
T* newHeap = new T[maxSize];
memcpy(newHeap,heap,maxSize);
delete heap;
heap = newHeap;
}
//插入元素,刚开始放入叶子处,之后依次与其双亲比较
int hole = ++curSize;//首先把元素放入最后面
heap[0] = insertItem;//做监视哨,减少while循环中的比较次数
while (insertItem > heap[hole/2])
{
heap[hole] = heap[hole/2];//把双亲放到孩子处,腾出位置放待插项
hole /= 2;
}
heap[hole] = insertItem;
}
/*从hole位置开始向下调整,有孩子时继续比较*/
/*调整时,总是与自己的孩子比较,直到没孩子或是比自己孩子都大为止*/
/*与孩子比较时,先找到一个孩子中比较大的,之后再与这个大的比较*/
template<typename T>
void MaxHeap<T>::HeapAdjust(int hole)
{
T adjustItem = heap[hole];
for (int child = 2 * hole;child <= curSize;child *= 2)//有孩子才继续比较
{
if (child < curSize && heap[child] < heap[child + 1])
{
child++;//child总是指向值最大的那个孩子
}
if (heap[child] > adjustItem)
{
//孩子大于被调整项,孩子要移到双亲的位置,为双亲腾出位置,之后继续比较
heap[hole] = heap[child];
}
else
{
break;
}
hole = child;
}
//循环结束,此时hole就是目标位置
heap[hole] = adjustItem;
}
/*所有元素均在数组中,调用此函数建堆*/
template<typename T>
void MaxHeap<T>::BuildHeap()
{
for (int i = curSize / 2;i > 0;i--)
{
HeapAdjust(i);
}
}
template<typename T>
void MaxHeap<T>::DeleteMax(T& maxItem)
{
assert(curSize > 0);
maxItem = heap[1];
heap[1] = heap[curSize--];
HeapAdjust(1);
}
template<typename T>
void MaxHeap<T>::DeleteMax()
{
assert(curSize > 0);
heap[1] = heap[curSize--];
HeapAdjust(1);
}
//测试函数
template<typename T>
bool MaxHeap<T>::IsMaxHeap() const
{
assert(curSize > 0);
for (int hole = curSize;hole > 1;hole /= 2)
{
if(heap[hole] > heap[hole/2])
{
return false;
}
}
return true;
}
template<typename T>
ostream& operator<<(ostream& cout,MaxHeap<T>& Heap)
{
for (int i = 1;i <= Heap.curSize;i++)
{
cout<<Heap.heap[i]<<" ";
}
cout<<endl;
return cout;
}
#endif //_MAX_HEAP_
int main()
{
int num = 0;
int maxNum = 0;
MaxHeap<int> maxHeap;
//测试Insert函数
for (int i = 0;i < 20;i++)
{
num = rand()%100;
maxHeap.Insert(num);
}
cout<<maxHeap<<endl;
bool isMaxHeap = maxHeap.IsMaxHeap();
if (isMaxHeap)
{
cout<<"这是个大根堆"<<endl;
}
else
{
cout<<"这不是个大根堆"<<endl;
}
//测试FindMax函数
cout<<maxHeap.FindMax()<<endl;
//测试DeleteMax函数
maxHeap.DeleteMax();
cout<<maxHeap<<endl;
maxHeap.DeleteMax(maxNum);
cout<<maxNum<<endl;
isMaxHeap = maxHeap.IsMaxHeap();
if (isMaxHeap)
{
cout<<"这是个大根堆"<<endl;
}
else
{
cout<<"这不是个大根堆"<<endl;
}
system("pause");
}
堆排序
注意:数据从下标1开始存储的
#include <iostream>
using namespace std;
const int len = 20;
void swap(int& m,int& n)
{
int tmp = m;
m = n;
n = tmp;
}
void HeapAdjust(int arr[],int hole,int curSize)
{
int adjustItem = arr[hole];
for (int child = 2 * hole;child <= curSize;child *= 2)
{
if (child < curSize && arr[child] < arr[child + 1])
{
child++;//child总是指向值最大的那个孩子
}
if (arr[child] > adjustItem)
{
//孩子大于被调整项,孩子要移到双亲的位置,为双亲腾出位置,之后继续比较
arr[hole] = arr[child];
}
else
{
break;
}
hole = child;
}
//循环结束,此时hole就是目标位置
arr[hole] = adjustItem;
}
//从小到大排序,建立一个大根堆,先输出最大数放到数组的最后面,次之放到其前面
void HeapSort(int arr[],int curSize)
{
//建堆
for (int hole = curSize / 2;hole > 0;hole--)
{
HeapAdjust(arr,hole,curSize);
}
//调整堆
for (int i= curSize;i >= 1;i--)
{
//堆顶元素和最后一个元素互换
swap(arr[i],arr[1]);
//重新调整堆--调整堆顶位置
//这时待排序元素个数为i-1。需要排序的序列为1 - i-1
//要对第一个位置(0)进行调整
HeapAdjust(arr,1,i-1);
}
}
int main()
{
int arr[len+1];//下标为0的位置不用
for (int i = 1;i <= len;i++)
{
arr[i]=rand()%1000;
}
//输出排序前的序列
for (int i = 1;i <= len;i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
HeapSort(arr,len);
//输出排序后的序列
for (int i = 1;i <= len;i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
system("pause");
return 1;
}
优先队列
注意:数据从下标1开始存储的,值越高优先级越大
#ifndef _PRIORITY_QUEUE_H_
#define _PRIORITY_QUEUE_H_
#include <iostream>
#include <assert.h>
using namespace std;
const int HeapIncreMent = 20;
template<typename T>
class PriQueue
{
public:
PriQueue(int capacity = 100);
PriQueue(const PriQueue& priQueue);
~PriQueue();
public:
/*查找元素*/
int Find(const T& insertItem)const;
const T& FindMax()const;
bool IsMaxHeap() const;
/*插入或删除元素*/
void Insert(const T& insertItem);
void DeleteMax();
void DeleteMax(T& maxItem);
/*删除、增加和减少某一优先级*/
void Delete(int loc);
void DecreaseKey(int loc,unsigned int det);
void IncreaseKey(int loc,unsigned int det);
PriQueue& operator =(const PriQueue& priQueue);
/*输出优先队列*/
friend ostream& operator<< <>(ostream& cout,PriQueue& priQueue);
private:
int maxSize;
int curSize;
T* heap;
private:
void BuildHeap();
void PercolateUp(int hole);
void PercolateDown(int hole);
};
template<typename T>
PriQueue<T>::PriQueue(int capacity):curSize(0),maxSize(capacity)
{
heap = new T[maxSize];
}
template<typename T>
PriQueue<T>::PriQueue(const PriQueue& priQueue):curSize(priQueue.curSize),maxSize(priQueue.maxSize)
{
heap = new T[maxSize];
for (int i = 1;i <= curSize;i++)
{
heap[i] = priQueue.heap[i];
}
}
template<typename T>
PriQueue<T>::~PriQueue()
{
if (heap != NULL)
{
maxSize = 0;
curSize = 0;
delete[] heap;
heap = NULL;
}
}
template<typename T>
const T& PriQueue<T>::FindMax() const
{
return heap[1];
}
/*新插入的元素总是和自己的双亲比较,直到找到自己的位置*/
template<typename T>
void PriQueue<T>::Insert(const T& insertItem)
{
if (curSize == maxSize - 1)
{
maxSize += HeapIncreMent;
T* newHeap = new T[maxSize];
memcpy(newHeap,heap,maxSize);
delete heap;
heap = newHeap;
}
//插入元素,刚开始放入叶子处,之后依次与其双亲比较
int hole = ++curSize;
heap[curSize] = insertItem;//把元素放入最后面
PercolateUp(hole);
}
template<typename T>
void PriQueue<T>::PercolateUp(int hole)
{
heap[0] = heap[hole];//做监视哨,减少while循环中的比较次数
while (heap[0] > heap[hole/2])
{
heap[hole] = heap[hole/2];//把双亲放到孩子处,腾出位置放待插项
hole /= 2;
}
heap[hole] = heap[0];
}
/*从hole位置开始向下调整,有孩子时继续比较*/
/*调整时,总是与自己的孩子比较,直到没孩子或是比自己孩子都大为止*/
/*与孩子比较时,先找到一个孩子中比较大的,之后再与这个大的比较*/
template<typename T>
void PriQueue<T>::PercolateDown(int hole)
{
T adjustItem = heap[hole];
for (int child = 2 * hole;child <= curSize;child *= 2)//有孩子才继续比较
{
if (child < curSize && heap[child] < heap[child + 1])
{
child++;//child总是指向值最大的那个孩子
}
if (heap[child] > adjustItem)
{
//孩子大于被调整项,孩子要移到双亲的位置,为双亲腾出位置,之后继续比较
heap[hole] = heap[child];
}
else
{
break;
}
hole = child;
}
//循环结束,此时hole就是目标位置
heap[hole] = adjustItem;
}
/*所有元素均在数组中,调用此函数建堆*/
template<typename T>
void PriQueue<T>::BuildHeap()
{
for (int i = curSize / 2;i > 0;i--)
{
PercolateDown(i);
}
}
template<typename T>
void PriQueue<T>::DeleteMax(T& maxItem)
{
assert(curSize > 0);
maxItem = heap[1];
heap[1] = heap[curSize--];
PercolateDown(1);
}
template<typename T>
void PriQueue<T>::DeleteMax()
{
assert(curSize > 0);
heap[1] = heap[curSize--];
PercolateDown(1);
}
/*删除、增加和减少某一优先级*/
/*先把loc的值变为最大,上升到堆顶,在删除堆顶*/
template<typename T>
void PriQueue<T>::Delete(int loc)
{
assert(loc > 0);
heap[loc] += FindMax();
PercolateUp(loc);//把loc位置的值变最大
DeleteMax();
}
template<typename T>
void PriQueue<T>::DecreaseKey(int loc,unsigned int det)
{
assert(loc > 0);
heap[loc] -= det;//值变小,大根堆中应该向下移动
PercolateDown(loc);
}
template<typename T>
void PriQueue<T>::IncreaseKey(int loc,unsigned int det)
{
assert(loc > 0);
heap[loc] += det;
PercolateUp(loc);
}
template<typename T>
bool PriQueue<T>::IsMaxHeap() const
{
assert(curSize > 0);
for (int hole = curSize;hole > 1;hole /= 2)
{
if(heap[hole] > heap[hole/2])
{
return false;
}
}
return true;
}
template<typename T>
int PriQueue<T>::Find(const T& insertItem) const
{
for (int i = 1;i <= curSize;i++)
{
if (insertItem == heap[i])
{
return i;
}
}
return -1;
}
template<typename T>
PriQueue<T>& PriQueue<T>::operator =(const PriQueue& priQueue)
{
if (this != &priQueue)
{
if (maxSize <= priQueue.curSize)
{
maxSize = priQueue.maxSize;
T* tmp = new T[maxSize];
heap = tmp;
}
curSize = priQueue.curSize;
for (int i = 1;i <= curSize;i++)
{
heap[i] = priQueue.heap[i];
}
}
return *this;
}
template<typename T>
ostream& operator<<(ostream& cout,PriQueue<T>& priQueue)
{
for (int i = 1;i <= priQueue.curSize;i++)
{
cout<<priQueue.heap[i]<<" ";
}
cout<<endl;
return cout;
}
#endif _PRIORITY_QUEUE_H_
int main()
{
int num = 0;
int maxNum = 0;
PriQueue<int> priQueue;
//测试Insert函数
for (int i = 0;i < 10;i++)
{
num = rand()%100;
priQueue.Insert(num);
}
//测试IsMaxHeap函数
bool isMaxHeap = priQueue.IsMaxHeap();
if (isMaxHeap)
{
cout<<"这是个大根堆"<<endl;
}
else
{
cout<<"这不是个大根堆"<<endl;
}
cout<<priQueue<<endl;
//测试拷贝构造函数
PriQueue<int> priQueue1(priQueue);
cout<<priQueue1<<endl;
//测试赋值构造函数
PriQueue<int> priQueue2;
priQueue2 = priQueue;
cout<<priQueue2<<endl;
//测试FindMax函数
cout<<"堆顶元素:"<<priQueue.FindMax()<<endl;
//测试DeleteMax函数
priQueue.DeleteMax();
cout<<"删除优先级最大的元素后的序列:"<<endl<<priQueue<<endl;
priQueue.DeleteMax(maxNum);
cout<<"优先级最大的元素:"<<maxNum<<endl;
cout<<"删除优先级最大的元素后的序列:"<<endl<<priQueue<<endl;
isMaxHeap = priQueue.IsMaxHeap();
if (isMaxHeap)
{
cout<<"这是个大根堆"<<endl;
}
else
{
cout<<"这不是个大根堆"<<endl;
}
/*删除、增加和减少某一优先级*/
priQueue.IncreaseKey(5,maxNum/2);
cout<<priQueue<<endl;
priQueue.DecreaseKey(2,maxNum/2);
cout<<priQueue<<endl;
priQueue.Delete(2);
cout<<priQueue<<endl;
system("pause");
}
测试代码
for (int hole = curSize;hole > 1;hole /= 2)
{
assert(heap[hole] <= heap[hole/2]);//孩子要小于双亲
}