最大堆的实现及堆排序

最大最小堆的原理及C++实现

参考资料

B站浙大数据结构课程-堆的原理与实现

堆排序算法说明

堆的原理

最大堆,每个节点都比其左右子节点大。且是完全二叉树

从根节点到任意节点路径上结点序列的有序性。

在这里插入图片描述
在这里插入图片描述

抽象数据描述

在这里插入图片描述

创建

在这里插入图片描述

插入

在这里插入图片描述

删除

在这里插入图片描述

排序

堆排序算法说明

  1. 将待排序序列构建成一个堆 H[0……n-1],根据(升序降序需求)选择大顶堆或小顶堆;
  2. 把堆首(最大值)和堆尾互换;
  3. 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
  4. 重复步骤 2,直到堆的尺寸为 1。
    在这里插入图片描述

实现及测试

#pragma once
#include "aux_sort.h"

//完全二叉树,根节点序号为1,序号按层级从左往右增加
//一个节点为i,则其父节点序号为 i/2, 左子节点为 2*i, 右子节点为 2*i+1
//                  9[1]
//                 /    \
//             8[2]     7[3]
//             /  \      /  \
//          6[4] 5[5]  4[6]  3[7] 

class MaxHeap{
public:
	MaxHeap(int maxSize);
	 void insert(int element);
	 int popMax();
	 vector<int> getSortedVec(); //堆排序
	 static MaxHeap* InitMaxHeap1(vector<int>& nums); //insert, O(nlogn)
	 static MaxHeap* InitMaxHeap2(vector<int>& nums); //adjust O(n)
	 static void _adjust(MaxHeap* heap, int index);
	 friend ostream& operator<<(ostream & os, MaxHeap& heap);
private:
	vector<int> arr;
	int size;
	int capacity;
};

MaxHeap::MaxHeap(int maxSize)
	:arr(maxSize+1)
{
	size = 0;
	capacity = maxSize;
	arr[0] = INT_MAX; //为了方便跳出循环, 哨兵
}

void MaxHeap::insert(int element){
	if(size==capacity){
		cout<<"The heap is full."<<endl;
		return;
	}
	int i = ++size;
	for (; arr[i/2]<element; i/=2){
		arr[i] = arr[i/2];
	}
	arr[i] = element;
}

int MaxHeap::popMax(){
	//从最大堆中取出最大的元素(堆顶),删除。
	//然后将堆尾的元素放到堆顶,然后判断其子节点是否比他大,大的话,就把该元素下移
	if(size==0){
		cout<<"The heap is empty."<<endl;
		return INT_MIN;
	}
	int maxItem = arr[1]; //记录最大元素
	int tmp = arr[size--]; //取出最尾元素,并 对 size减一
	int parent, child;
	for (parent=1; parent*2<=size/*存在左子节点*/; parent=child)
	{
		//让child 为左右子节点中较大的那个
		child = parent*2; //先设为左子节点
		if(child<size && arr[child]<arr[child+1]) //如果存在右子节点且右比左大
			{child = child+1; /*设为右子节点*/ }
		if(tmp<arr[child]){
			arr[parent] = arr[child];
		}
		else{
			break;
		}
	}
	arr[parent] = tmp;
	return maxItem;
}

MaxHeap* MaxHeap::InitMaxHeap1(vector<int>& nums){
	int len = nums.size();
	MaxHeap* heap = new MaxHeap(len);
	for (int i=0; i<len; ++i){
		heap->insert(nums[i]);
	}
	return heap;
}

MaxHeap* MaxHeap::InitMaxHeap2(vector<int>& nums){
	int len = nums.size();
	MaxHeap* heap = new MaxHeap(len);
	heap->size = len;
	for (int i=0; i<len; ++i){
		heap->arr[i+1] = nums[i];
	}
	//从最后一个有子节点的节点开始,即  size/2, ~ 1
	for (int i=heap->size/2; i>=1; --i){
		_adjust(heap, i);
	}
	return heap;
}

void MaxHeap::_adjust(MaxHeap* pheap, int index){
	MaxHeap& heap = (*pheap);
	int leftChild = index*2;
	int rightChild = leftChild+1;
	int largest = index;
	if (leftChild<=heap.size && heap.arr[leftChild]>heap.arr[largest])
		largest = leftChild;
	if (rightChild<=heap.size && heap.arr[rightChild]>heap.arr[largest])
		largest = rightChild;
	if (largest!=index)
	{
		//swap (index, largest)
		int tmp = heap.arr[index];
		heap.arr[index] = heap.arr[largest];
		heap.arr[largest] = tmp;
		_adjust(pheap, largest);
	}
}

//平均时间复杂度  最好情况  最坏情况  空间复杂度  排序方式  稳定
//     nlogn       nlogn   nlogn         1        in      no

vector<int> MaxHeap::getSortedVec(){
	//把堆首(最大值)和堆尾互换;
	//把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
	//重复以上步骤,直到堆的尺寸为 1。
	vector<int> pre = arr;
	int preSize = size;
	for (int i=size; i>=1; --i)
	{
		int tmp = arr[1];
		arr[1] = arr[size];
		arr[size] = tmp;
		--size;
		_adjust(this, 1);
	}
	vector<int> result(++arr.begin(), arr.end()); //返回arr[1,size]
	arr = pre;
	size = preSize;
	return result;
}

ostream& operator<<(ostream & out, MaxHeap& heap){
	int levelEnd = 1;
	int levelCount = 1;
	for (int i=1; i<=heap.size; ++i){
		out<<heap.arr[i]<<" ";
		if(i==levelEnd){
			out<<endl;
			levelEnd += 2*levelCount;
			levelCount *= 2;
		}
	}
	return out;
}

void testHeap()
{
	vector<int> arr;
	for (int i = 0; i < 11; i++){
		arr.push_back(rand()%20);
	}
	cout<<"Input arr: "<<arr<<endl;
	
	MaxHeap* heap = MaxHeap::InitMaxHeap1(arr);
	cout<<"The max heap initialized1 from arr:\n"<<*heap<<endl<<endl;

	MaxHeap* heap2 = MaxHeap::InitMaxHeap2(arr);
	cout<<"The max heap initialized2 from arr:\n"<<*heap2<<endl;

	cout<<"Sorted arr from heap: \n"<<heap2->getSortedVec()<<endl;

	heap2->popMax();
	heap2->insert(24);
	cout<<"After pop max and insert 24:\n"<<*heap2<<endl;
	cout<<"sorted arr: \n"<<heap2->getSortedVec()<<endl;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值