C++ 数据结构学习 ---- 完全二叉堆

目录

1 头文件

2. 相关函数

2.1 建堆函数

2.2 删除函数

2.3 获取函数

2.4 插入函数

2.5 上滤函数

2.6 下滤函数

3. 完整代码

4. 运行结果及截图​编辑


1 头文件

#include "Vector.h" //借助多重继承机制,基于向量
#include "PQ.h" //按照优先级队列ADT实现的

#define  Parent(i)         ( ( ( i ) - 1 ) >> 1 ) //PQ[i]的父节点(floor((i-1)/2),i无论正负)
#define  LChild(i)         ( 1 + ( ( i ) << 1 ) ) //PQ[i]的左孩子
#define  RChild(i)         ( ( 1 + ( i ) ) << 1 ) //PQ[i]的右孩子
#define  InHeap(n, i)      ( ( ( -1 ) < ( i ) ) && ( ( i ) < ( n ) ) ) //判断PQ[i]是否合法
#define  LChildValid(n, i) InHeap( n, LChild( i ) ) //判断PQ[i]是否有一个(左)孩子
#define  RChildValid(n, i) InHeap( n, RChild( i ) ) //判断PQ[i]是否有两个孩子
#define  Bigger(PQ, i, j)  ( lt( PQ[i], PQ[j] ) ? j : i ) //取大者(等时前者优先)
#define  ProperParent(PQ, n, i) /*父子(至多)三者中的大者*/ \
            ( RChildValid(n, i) ? Bigger( PQ, Bigger( PQ, i, LChild(i) ), RChild(i) ) : \
            ( LChildValid(n, i) ? Bigger( PQ, i, LChild(i) ) : i \
            ) \
            ) //相等时父节点优先,如此可避免不必要的交换

template <typename T> void heapify(T* A, Rank n); //Floyd建堆算法
template <typename T> Rank percolateDown(T* A, Rank n, Rank i); //下滤
template <typename T> Rank percolateUp(T* A, Rank i); //上滤


template <typename T> struct PQ_ComplHeap : public PQ<T>, public Vector<T> { //完全二叉堆
	friend class UniPrint; //演示输出使用,否则不必设置友类
	PQ_ComplHeap() { } //默认构造
	PQ_ComplHeap(T* A, Rank n) { this->copyFrom(A, 0, n); heapify(this->_elem, n); } //批量构造
	void insert(T); //按照比较器确定的优先级次序,插入词条
	T getMax(); //读取优先级最高的词条
	T delMax(); //删除优先级最高的词条
}; //PQ_ComplHeap


2. 相关函数

2.1 建堆函数



//Floyd建堆算法,O(n)时间
template <typename T> void heapify(T* A, const Rank n) { 
	for (Rank i = n / 2 - 1; 0 <= i; i--) //自底而上,依次
{
		percolateDown(A, n, i); //下滤各内部节点
  /*DSA*///for ( int k = 0; k < n; k++ ) {
  /*DSA*///  int kk = k; while ( i < kk ) kk = (kk - 1) / 2;
  /*DSA*///  i == kk ? print(A[k]) : print("    " );
  /*DSA*///}; printf("\n");
 }
}
//暴力建堆,O (n^2)时间
template <typename T> void bheapify(T* A, const Rank n) {
	for (Rank i = n / 2 - 1; 0 <= i; i--) //自底而上,依次
	{

		for (int k = 0; k < n; k++) {
			int kk = k; while (i < kk) kk = (kk - 1) / 2;
			i == kk ? std::cout << A[k] : std::cout << "   ";
		};
		std::cout << std::endl;
	}
}




2.2 删除函数

 //删除非空完全二叉堆中优先级最高的词条
template <typename T> T PQ_ComplHeap<T>::delMax() {
	T maxElem = this->_elem[0]; this->_elem[0] = this->_elem[--this->_size]; //摘除堆顶(首词条),代之以末词条
	percolateDown(this->_elem, this->_size, 0); //对新堆顶实施下滤
	return maxElem; //返回此前备份的最大词条
}

2.3 获取函数

//取优先级最高的词条
template <typename T> T PQ_ComplHeap<T>::getMax() { return this->_elem[0]; }

2.4 插入函数


//将词条插入完全二叉堆中
template <typename T> void PQ_ComplHeap<T>::insert(T e) { 
	Vector<T>::insert(e); //首先将新词条接至向量末尾
	percolateUp(this->_elem, this->_size - 1); //再对该词条实施上滤调整
}

2.5 上滤函数

//对向量中的第i个词条实施上滤操作,i < _size
template <typename T> Rank percolateUp(T* A, Rank i) {
	while (0 < i) { //在抵达堆顶之前,反复地
		Rank j = Parent(i); //考查[i]之父亲[j]
		if ( lt(A[i], A[j]) ) break; //一旦父子顺序,上滤旋即完成;否则
		swap(A[i], A[j]); i = j; //父子换位,并继续考查上一层
	} //while
	return i; //返回上滤最终抵达的位置
}

2.6 下滤函数

//对向量前n个词条中的第i个实施下滤,i < n
template <typename T> Rank percolateDown(T* A, Rank n, Rank i) {
	Rank j; //i及其(至多两个)孩子中,堪为父者
	while (i != (j = ProperParent(A, n, i))) //只要i非j,则
	{
		swap(A[i], A[j]); i = j;
	} //二者换位,并继续考查下降后的i
	return i; //返回下滤抵达的位置(亦i亦j)
}

3. 完整代码

#include<iostream>
#include "PQ_ComplHeap.h"
#include "Dice.h"

using namespace std;
template <typename T> void testPQ_ComplHeap(int n) {
    PQ_ComplHeap<int> pqch;
    while (pqch.size() < 2 * n) {
       // cout << endl;
        switch (dice(3)) {
        case 0: { //删除,成功率 <= 33.3%
            if (pqch.size() < 1) break;//边界条件,删除的前提是堆中存在最少一个元素
            cout << "删除:" << pqch.getMax() ;
            int oldsize = pqch.size();
            pqch.delMax();
            int newsize = pqch.size();
            if (oldsize > newsize) cout << "删除成功!" << endl;
            else cout << "删除失败!" << endl;
            break;
        }
        default :  { //插入,成功率 <= 66.6%
            T key = dice((T)n * 12); 
            cout << "插入:" << key << " ";
            int oldsize = pqch.size();
            pqch.insert(key);
            int newsize = pqch.size();
            if (newsize>oldsize) cout << "插入成功!" << endl;
            else cout << "插入失败!" << endl;
            break;
        }
        } //switch
    } //whil
    while (pqch.size() > 0) {
        cout << "删除:" << pqch.getMax();
        pqch.delMax();
        if (pqch.size()) cout << "删除成功!" << endl;
        else cout <<endl<< "已全部删除!" << endl;
    }
}


int main() {
	srand((unsigned int)time(NULL));
	int i = rand() % 20;
	testPQ_ComplHeap<int>(i);
	
	//PQ_ComplHeap<int> pqch;
	//pqch.insert(5);
	//pqch.insert(10);
	//pqch.insert(4);
	//cout << pqch.getMax() << endl;
	//pqch.delMax();
	//cout << pqch.getMax() << endl;
	//pqch.delMax();
	//cout << pqch.getMax() << endl;

	system("pause");
	return 0;
}

4. 运行结果及截图

   以上所有代码参考邓俊辉老师的《c++语言版数据结构》!

猜你喜欢

转载自blog.csdn.net/qq_58240448/article/details/128115471