大根堆和堆排序

本文介绍了一个使用C++实现的大根堆数据结构,并演示了如何通过插入、删除操作维护这个堆。此外,还展示了如何利用堆进行有效的排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大根堆实现

MaxHeap.h

#pragma once
#include<iostream>
using namespace std;
template<typename T>
class MaxHeap {
private:
	//堆
	T* heap;
	//实际容量
	int size;
	//总容量
	int maxCapacity;
	//最大堆的下调算法
	void filterDown(const int &start,const int &end);
	//最大堆的向上调整算法(从start开始向上直到0,调整堆)
	void filterUp(const int &start);
public:
	MaxHeap(int capacity=30);
	~MaxHeap();
	//获得data的索引,没有就返回-1
	int getIndex(const T &data) const;
	//插入data,成功返回true,失败返回false
	bool insert(const T &data);
	//移除data,成功返回true,失败返回false
	bool remove(const T &data);
	//打印大根堆
	void print()const;
};

 MaxHeap.cpp

#include "MaxHeap.h"
template<typename T>
MaxHeap<T>::MaxHeap(int capacity) {
	size = 0;
	maxCapacity = capacity;
	heap = new T[capacity];
}

template<typename T>
MaxHeap<T>::~MaxHeap() {
	size = maxCapacity = 0;
	delete[] heap;
}

//最大堆的向上调整算法(从start开始向上直到0,调整堆)
template<typename T>
void MaxHeap<T>::filterUp(const int &start) {
	//当前节点索引
	int current = start;
	//当前节点父亲
	int parent = (start - 1) >> 1;
	//当前节点值
	T temp = heap[current];
	while (current > 0) {
		//节点比父亲小
		if (temp <= heap[parent])break;
		//节点比父亲大
		heap[current] = heap[parent];
		current = parent;
		parent = (parent - 1) >> 1;
	}
	heap[current] = temp;
}

//插入data,成功返回true,失败返回false
template<typename T>
bool MaxHeap<T>::insert(const T &data) {
	if (size == maxCapacity)return false;
	heap[size] = data;
	filterUp(size);
	++size;
	return true;
}

//获得data的索引,没有就返回-1
template<typename T>
int MaxHeap<T>::getIndex(const T &data) const {
	for (int i = 0; i < size; ++i) {
		if (data == heap[i])return i;
	}
	return -1;
}

//最大堆的下调算法
template<typename T>
void MaxHeap<T>::filterDown(const int &start, const int &end) {
	//当前节点
	int current = start;
	//左孩子
	int child = start << 1 | 1;
	//当前节点值
	T temp = heap[current];
	while (child <= end) {
		//如果有右孩子,且右孩子比左孩子大,则son=右孩子
		if (child < end&&heap[child] < heap[child+1])++child;
		//调整结束了
		if (temp > heap[child])break;
		heap[current] = heap[child];
		current = child;
		child = current << 1 | 1;
	}
	heap[current] = temp;
}

//移除data,成功返回true,失败返回false
template<typename T>
bool MaxHeap<T>::remove(const T &data) {
	if (size <= 0)return false;
	int index = getIndex(data);
	if (index < 0)return false;
	--size;
	heap[index] = heap[size];
	filterDown(index, size - 1);
	return true;
}

//打印大根堆
template<typename T>
void MaxHeap<T>::print()const {
	for (int i = 0; i < size; ++i) {
		cout << heap[i] << ' ';
	}
	cout << endl;
}

main.cpp

#include<iostream>
#include "MaxHeap.cpp"
using namespace std;
int main() {
	int a[] = { 10, 40, 30, 60, 90, 70, 20, 50, 80 };
	int i, len = sizeof(a) / sizeof(a[0]);
	MaxHeap<int>* tree = new MaxHeap<int>();
	cout << "----依次添加----" << endl;
	for (int c : a) {
		cout << c << ' ';
		tree->insert(c);
	}
	cout << endl;
	cout << "----最大堆----" << endl;
	tree->print();

	i = 85;
	tree->insert(i);
	cout << "添加元素:" << i << endl;
	cout << "----最大堆----" << endl;
	tree->print();
	
	i = 60;
	tree->remove(i);
	cout << "删除元素:" << i << endl;
	cout << "----最大堆----" << endl;
	tree->print();

	return 0;
}

 堆排序(从小到大)

#include<iostream>
using namespace std;
template<typename T>
void heapAdjust(T a[], int parent, int len) {
	T temp = a[parent];
	//左孩子,从0开始的节点左孩子是2*i+1有孩子是2*i+2
	int child = 2 * parent + 1;
	while (child < len) {
		//如果右孩子比左孩子大
		if (child + 1 < len&&a[child] < a[child + 1])++child;
		//如果已经比孩子大了,退出
		if (temp >= a[child])break;
		a[parent] = a[child];
		parent = child;
		child = 2 * child + 1;
	}
	a[parent] = temp;
}
template<typename T>
void heapSort(T a[], int n) {
	//初建堆
	for (int i = n / 2 - 1; i >= 0; --i)heapAdjust(a, i, n);
	for (int i = n - 1; i >= 0; --i) {
		//根和最后一个节点交换(把最大的换下去)
		swap(a[i], a[0]);
		//重新调整
		heapAdjust(a, 0, i);
		//for (int j = 0; j < n; ++j)cout << a[j] << ' ';
		//cout << endl;
	}
}
int main() {
	/*
	12
	46 74 16 53 14 26 40 38 86 65 27 34
	*/
	int n;
	cin >> n;
	int *a = new int[n];
	for (int i = 0; i < n; ++i)cin >> a[i];
	cout << endl << endl << endl;
	heapSort(a, n);
	for (int j = 0; j < n; ++j)cout << a[j] << ' ';
	cout << endl;
	delete[] a;
	return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nightmare004

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值