数据结构-堆

堆(数据结构):堆可以被看成是一棵树,如:堆排序。

数组堆实现代码:

#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++开发二】

猜你喜欢

转载自blog.csdn.net/ydpawx/article/details/78187974