堆(数据结构):堆可以被看成是一棵树,如:堆排序。
数组堆实现代码:
#include <iostream>
#define MAX 11
using namespace std;
typedef struct Heap
{
int nSize; //堆大小
int *pnData; //存放堆元素
}ARRAYHEAP,*LPARRAYHEAP;
//调整位置
int PosKey(LPARRAYHEAP pHeap, int nPos)
{
while (nPos > 1)
{
int nMax = pHeap->pnData[nPos];
int nParent = nPos / 2;
if (nMax > pHeap->pnData[nParent])
{
//当前的值大于了父结点的值 ----向上渗透
pHeap->pnData[nPos] = pHeap->pnData[nParent];
pHeap->pnData[nParent] = nMax;
//交换序号
nPos = nParent;
}
else
{
break;
}
}
return 1;
}
//插入结点
int InsertNode(LPARRAYHEAP pHeap, int nData)
{
//堆元素增加
++pHeap->nSize;
//无规则入栈
pHeap->pnData[pHeap->nSize] = nData;
//pHeap->nSize 就等于下标
PosKey(pHeap, pHeap->nSize);
return 1;
}
//根结点大于孩子结点的值,左右是没有 关系
//分堆进行比较 1 2 4 8 16
int PopMaxHeap(LPARRAYHEAP pHeap)
{
//层次遍历
int nMax = pHeap->pnData[1]; //0 小标没有
int nPos = 1;
int nChild = nPos * 2;
while (nChild <= pHeap->nSize)
{
int nTemp = pHeap->pnData[nChild]; //每一层中第一个元素
//进行左右比较,nChild下标下面的元素和nChild+1 元素进行比较
if (nChild + 1 <= pHeap->nSize&&nTemp < pHeap->pnData[nChild + 1])
{
++nChild; //nChild=nChild+1
nTemp = pHeap->pnData[nChild];
}
pHeap->pnData[nPos] = nTemp;
nPos = nChild;
nChild *= 2;
}
pHeap->pnData[nPos] = pHeap->pnData[pHeap->nSize];
--pHeap->nSize;
return nMax;
}
int main()
{
ARRAYHEAP Heap;
//初始化堆
Heap.pnData = new int[MAX];
Heap.nSize = 0;
for (int i = 1; i <= 10; i++)
{
InsertNode(&Heap, i);
}
//输出堆的那段内存
for (int i = 1; i <= 10; i++)
{
cout << Heap.pnData[i] << " ";
}
cout << "出堆:" << endl;
while (Heap.nSize > 0)
{
cout << PopMaxHeap(&Heap) << " ";
}
cout << endl;
system("pause");
return 0;
}
链式堆:
MaxHeap.cpp
#define _SCL_SECURE_NO_WARNINGS
#include <iostream>
#include "maxHeap.h"
using namespace std;
int main()
{
maxHeap<int> myHeap(4);
myHeap.push(10);
myHeap.push(50);
myHeap.push(40);
myHeap.push(20);
myHeap.push(70);
myHeap.push(80);
//普通输出堆
cout <<"堆容量:" <<myHeap.size() << endl;
cout << "堆元素是:" << endl;
cout << myHeap << endl;
//堆排序 按照pop方式出堆
cout << "最大的元素是:" << myHeap.top() << endl;
myHeap.pop();
cout << "堆容量:" << myHeap.size() << endl;
cout << "最大的元素是:" << myHeap.top() << endl;
myHeap.pop();
cout << "堆容量:" << myHeap.size() << endl;
cout << "最大的元素是:" << myHeap.top() << endl;
myHeap.pop();
cout << "堆容量:" << myHeap.size() << endl;
cout << "最大的元素是:" << myHeap.top() << endl;
myHeap.pop();
cout << "堆容量:" << myHeap.size() << endl;
system("pause");
return 0;
}
changeLength1D.h
#include "myExceptions.h"
using namespace std;
template <class T>
void changeLength1D(T* &a, int oldLength, int newLength)
{
if (newLength < 0)
{
throw illegalParameterValue("新的数组的大小必须大于零");
}
T *temp = new T[newLength];
int maxLength = oldLength>newLength ? oldLength : newLength;
copy(a, a + maxLength,temp); //拷贝数据
delete[] a; //释放原来指针绑定的堆内存
a = temp; //重新绑定
}
maxHeap.h
#include "changeLength1D.h"
#include "maxPriorityQueue.h"
#include "myExceptions.h"
#include <sstream>
using namespace std;
template <class T>
class maxHeap :public maxPriorityQueue<T>
{
public:
//构造函数+析构函数
maxHeap(int init)
{
//流 ostringstream sstream头文件
//防御性编程
if (init < 1)
{
ostringstream strerr;
strerr << "初始化容量=" << init << " 必须大于0";
//调用成员函数 str() 从ostringstream 转换为string类型
throw illegalParameterValue(strerr.str()); //可以这样写嘛?
}
heapSize = 0; //堆的起始大小为0
arrayLength = init+1; //是从数组序号为1的地方开始的
heap = new T[arrayLength]; //差生堆需要的空间
}
~maxHeap()
{
delete[] heap;
}
bool empty() const
{
return heapSize == 0;
}
int size() const
{
return heapSize;
}
const T& top()
{
if (heapSize == 0)
throw MaxHeapEmpty();
return heap[1];
}
void pop();
void push(const T& theElement);
void output(ostream& out) const;
//初始化数组 ----->把数组元素入堆,入堆的数据
private:
int heapSize; //堆的长度
T *heap; //数组存储 动态分配
int arrayLength; //数组长度
};
template<class T>
void maxHeap<T>::push(const T& theElement)
{
if (heapSize == arrayLength - 1)
{
//永远*2扩充数组
changeLength1D(heap, arrayLength, arrayLength * 2);
arrayLength *= 2;
}
int currentPos = ++heapSize; //从1开始存储,或者从堆最后面开始存储
//如果堆里面本来就存在数据
while (currentPos != 1 && heap[currentPos / 2] < theElement)
{
//满足: 根结点比孩子大
heap[currentPos] = heap[currentPos / 2];
currentPos /= 2;
}
heap[currentPos] = theElement;
}
//从小开始,从大开始
template<class T>
void maxHeap<T>::pop()
{
//为空处理下
if (heapSize == 0)
throw MaxHeapEmpty();
heap[1].~T(); //析构数组的第一个位置
T lastElement = heap[heapSize--]; //每次出堆进行减操作
int currentPos = 1;
int child = 2;
//找到最大那个lastElement
while (child <= heapSize)
{
//出堆只要比较一层
//找一层最大的
if(child < heapSize&&heap[child] < heap[child + 1])
child++;
//找到后比较
if (lastElement >= heap[child])
//不处理
break;
//如果不是最大值,就进行交换
heap[currentPos] = heap[child];
currentPos = child;
child *=2;
}
heap[currentPos] = lastElement;
}
template <class T>
void maxHeap<T>::output(ostream& out) const
{
//流迭代器
copy(heap + 1, heap + heapSize + 1, ostream_iterator<T>(out, " "));
}
//没有任何区别
template <class T>
ostream& operator<<(ostream& out, const maxHeap<T>& x)
{
x.output(out);
return out;
}
maxPriorityQueue.h
using namespace std;
template <class T>
//ADT 抽象数据类型
class maxPriorityQueue
{
//队列的基本操作
public:
virtual ~maxPriorityQueue(){};
virtual bool empty() const = 0;
virtual int size() const = 0;
virtual const T& top() = 0;
virtual void pop() = 0;
virtual void push(const T& theElement) = 0;
};
myException.h
#ifndef myExceptions_
#define myExceptions_
#include <iostream>
#include<string>
using namespace std;
class illegalParameterValue
{
public:
illegalParameterValue(string theMessage="值有问题")
{
message = theMessage;
}
void outputMesage()
{
cout << message << endl;
}
private:
string message;
};
class MaxHeapEmpty
{
public:
MaxHeapEmpty(string theMessage = "栈为空")
{
message = theMessage;
}
void outputMesage()
{
cout << message << endl;
}
private:
string message;
};
#endif
点击链接加入群聊【博毅创为C/C++开发二】