C++实现最大堆、最小堆、最大索引堆、最小索引堆

12 篇文章 0 订阅

1、实现四种堆

2、简单使用10000000/ 1千万int型测试排序性能

测试结果如下:

Heap Sort Using Max Heap : 14.378 s
Heap Sort Using Min Heap : 10.443 s
Heap Sort Using Index Max Heap : 11.391 s
Heap Sort Using Index Min Heap : 11.605 s

#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <iostream>
#include <ctime>
#include <cassert>
#include <string>
#include <algorithm>

using namespace std;

//随机数生成
int *generateRandomArray(int n, int rangeL, int rangeR) {

	assert(rangeL <= rangeR);
	int *arr = new int[n];
	srand((unsigned)time(NULL));
	for (int i = 0; i < n; i++)
		arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
	return arr;
}
//排序检验
template<typename T>
bool isSorted(T arr[], int n) {

	for (int i = 0; i < n - 1; i++)
		if (arr[i] > arr[i + 1])
			return false;
	return true;
}

//时间测试
template<typename T>
void testSort(const string &sortName, void(*sort)(T[], int), T arr[], int n) {

	clock_t startTime = clock();
	sort(arr, n);
	clock_t endTime = clock();

	assert(isSorted(arr, n));
	cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;

	return;
}

//数组复制
int *copyIntArray(int a[], int n) {

	int *arr = new int[n];
	copy(a, a + n, arr);
	return arr;
}
//打印
template<typename T>
void printArray(T arr[], int n) {

	for (int i = 0; i < n; i++)
		cout << arr[i] << " ";
	cout << endl;
	return;
}

//最大堆
template<typename T>
class MaxHeap {

private:
	T *data;
	int count;
	int capacity;

	void shiftUp(int k) {
		while (k > 1 && data[k / 2] < data[k]) {
			swap(data[k / 2], data[k]);
			k /= 2;
		}
	}

	void shiftDown(int k) {
		while (2 * k <= count) {
			int j = 2 * k;
			if (j + 1 <= count && data[j + 1] > data[j]) j++;
			if (data[k] >= data[j]) break;
			swap(data[k], data[j]);
			k = j;
		}
	}

public:

	MaxHeap(int capacity) {
		data = new T[capacity + 1];
		count = 0;
		this->capacity = capacity;
	}

	MaxHeap(T arr[], int n) {
		data = new T[n + 1];
		capacity = n;

		for (int i = 0; i < n; i++)
			data[i + 1] = arr[i];
		count = n;

		for (int i = count / 2; i >= 1; i--)
			shiftDown(i);
	}

	~MaxHeap() {
		delete[] data;
	}

	int size() {
		return count;
	}

	bool isEmpty() {
		return count == 0;
	}

	void insert(T item) {
		assert(count + 1 <= capacity);
		data[count + 1] = item;
		shiftUp(count + 1);
		count++;
	}

	T extractMax() {
		assert(count > 0);
		T ret = data[1];
		swap(data[1], data[count]);
		count--;
		shiftDown(1);
		return ret;
	}

	T getMax() {
		assert(count > 0);
		return data[1];
	}
};

//最小堆
template<typename T>
class MinHeap {

private:
	T *data;
	int count;
	int capacity;

	void shiftUp(int k) {
		while (k > 1 && data[k / 2] > data[k]) {
			swap(data[k / 2], data[k]);
			k /= 2;
		}
	}

	void shiftDown(int k) {
		while (2 * k <= count) {
			int j = 2 * k;
			if (j + 1 <= count && data[j + 1] < data[j]) j++;
			if (data[k] <= data[j]) break;
			swap(data[k], data[j]);
			k = j;
		}
	}

public:

	MinHeap(int capacity) {
		data = new T[capacity + 1];
		count = 0;
		this->capacity = capacity;
	}

	MinHeap(T arr[], int n) {
		data = new T[n + 1];
		capacity = n;

		for (int i = 0; i < n; i++)
			data[i + 1] = arr[i];
		count = n;

		for (int i = count / 2; i >= 1; i--)
			shiftDown(i);
	}

	~MinHeap() {
		delete[] data;
	}

	int size() {
		return count;
	}

	bool isEmpty() {
		return count == 0;
	}

	void insert(T item) {
		assert(count + 1 <= capacity);
		data[count + 1] = item;
		shiftUp(count + 1);
		count++;
	}

	T extractMin() {
		assert(count > 0);
		T ret = data[1];
		swap(data[1], data[count]);
		count--;
		shiftDown(1);
		return ret;
	}

	T getMin() {
		assert(count > 0);
		return data[1];
	}
};


//最大索引堆
template<typename T>
class IndexMaxHeap {

private:
	T *data;
	int *indexes;
	int *reverse;

	int count;
	int capacity;

	void shiftUp(int k) {

		while (k > 1 && data[indexes[k / 2]] < data[indexes[k]]) {
			swap(indexes[k / 2], indexes[k]);
			reverse[indexes[k / 2]] = k / 2;
			reverse[indexes[k]] = k;
			k /= 2;
		}
	}

	void shiftDown(int k) {

		while (2 * k <= count) {
			int j = 2 * k;
			if (j + 1 <= count && data[indexes[j + 1]] > data[indexes[j]])
				j += 1;

			if (data[indexes[k]] >= data[indexes[j]])
				break;

			swap(indexes[k], indexes[j]);
			reverse[indexes[k]] = k;
			reverse[indexes[j]] = j;
			k = j;
		}
	}

public:
	IndexMaxHeap(int capacity) {

		data = new T[capacity + 1];
		indexes = new int[capacity + 1];
		reverse = new int[capacity + 1];
		for (int i = 0; i <= capacity; i++)
			reverse[i] = 0;

		count = 0;
		this->capacity = capacity;
	}

	~IndexMaxHeap() {
		delete[] data;
		delete[] indexes;
		delete[] reverse;
	}

	int size() {
		return count;
	}

	bool isEmpty() {
		return count == 0;
	}

	// 传入的i对用户而言,是从0索引的
	void insert(int i, T item) {
		assert(count + 1 <= capacity);
		assert(i + 1 >= 1 && i + 1 <= capacity);

		i += 1;
		data[i] = item;
		indexes[count + 1] = i;
		reverse[i] = count + 1;
		count++;

		shiftUp(count);
	}

	T extractMax() {
		assert(count > 0);

		T ret = data[indexes[1]];
		swap(indexes[1], indexes[count]);
		reverse[indexes[count]] = 0;
		reverse[indexes[1]] = 1;
		count--;
		shiftDown(1);
		return ret;
	}

	int extractMaxIndex() {
		assert(count > 0);

		int ret = indexes[1] - 1;
		swap(indexes[1], indexes[count]);
		reverse[indexes[count]] = 0;
		reverse[indexes[1]] = 1;
		count--;
		shiftDown(1);
		return ret;
	}

	T getMax() {
		assert(count > 0);
		return data[indexes[1]];
	}

	int getMaxIndex() {
		assert(count > 0);
		return indexes[1] - 1;
	}

	bool contain(int i) {
		assert(i + 1 >= 1 && i + 1 <= capacity);
		return reverse[i + 1] != 0;
	}

	T getT(int i) {
		assert(contain(i));
		return data[i + 1];
	}

	void change(int i, T newT) {

		assert(contain(i));
		i += 1;
		data[i] = newT;

		int j = reverse[i];
		shiftUp(j);
		shiftDown(j);
	}

};

//最小索引堆
template<typename T>
class IndexMinHeap {

private:
	T *data;
	int *indexes;
	int *reverse;

	int count;
	int capacity;

	void shiftUp(int k) {

		while (k > 1 && data[indexes[k / 2]] > data[indexes[k]]) {
			swap(indexes[k / 2], indexes[k]);
			reverse[indexes[k / 2]] = k / 2;
			reverse[indexes[k]] = k;
			k /= 2;
		}
	}

	void shiftDown(int k) {

		while (2 * k <= count) {
			int j = 2 * k;
			if (j + 1 <= count && data[indexes[j]] > data[indexes[j + 1]])
				j += 1;

			if (data[indexes[k]] <= data[indexes[j]])
				break;

			swap(indexes[k], indexes[j]);
			reverse[indexes[k]] = k;
			reverse[indexes[j]] = j;
			k = j;
		}
	}

public:
	IndexMinHeap(int capacity) {

		data = new T[capacity + 1];
		indexes = new int[capacity + 1];
		reverse = new int[capacity + 1];

		for (int i = 0; i <= capacity; i++)
			reverse[i] = 0;

		count = 0;
		this->capacity = capacity;
	}

	~IndexMinHeap() {
		delete[] data;
		delete[] indexes;
		delete[] reverse;
	}

	int size() {
		return count;
	}

	bool isEmpty() {
		return count == 0;
	}

	void insert(int index, T item) {
		assert(count + 1 <= capacity);
		assert(index + 1 >= 1 && index + 1 <= capacity);

		index += 1;
		data[index] = item;
		indexes[count + 1] = index;
		reverse[index] = count + 1;
		count++;
		shiftUp(count);
	}

	T extractMin() {
		assert(count > 0);

		T ret = data[indexes[1]];
		swap(indexes[1], indexes[count]);
		reverse[indexes[count]] = 0;
		reverse[indexes[1]] = 1;
		count--;
		shiftDown(1);
		return ret;
	}

	int extractMinIndex() {
		assert(count > 0);

		int ret = indexes[1] - 1;
		swap(indexes[1], indexes[count]);
		reverse[indexes[count]] = 0;
		reverse[indexes[1]] = 1;
		count--;
		shiftDown(1);
		return ret;
	}

	T getMin() {
		assert(count > 0);
		return data[indexes[1]];
	}

	int getMinIndex() {
		assert(count > 0);
		return indexes[1] - 1;
	}

	bool contain(int index) {

		return reverse[index + 1] != 0;
	}

	T getT(int index) {
		assert(contain(index));
		return data[index + 1];
	}

	void change(int index, T newT) {

		assert(contain(index));
		index += 1;
		data[index] = newT;

		shiftUp(reverse[index]);
		shiftDown(reverse[index]);
	}

};




template<typename T>
void heapSortUsingMaxHeap(T arr[], int n) {

	MaxHeap<T> maxheap = MaxHeap<T>(n);
	for (int i = 0; i < n; i++)
		maxheap.insert(arr[i]);

	for (int i = n - 1; i >= 0; i--)
		arr[i] = maxheap.extractMax();

}

template<typename T>
void heapSortUsingIndexMaxHeap(T arr[], int n) {

	IndexMaxHeap<T> indexMaxheap = IndexMaxHeap<T>(n);
	for (int i = 0; i < n; i++)
		indexMaxheap.insert(i, arr[i]);

	for (int i = n - 1; i >= 0; i--)
		arr[i] = indexMaxheap.extractMax();

}

template<typename T>
void heapSortUsingMinHeap(T arr[], int n) {

	MinHeap<T> minheap = MinHeap<T>(n);
	for (int i = 0; i < n; i++)
		minheap.insert(arr[i]);

	for (int i = 0; i < n; i++)
		arr[i] = minheap.extractMin();

}

template<typename T>
void heapSortUsingIndexMinHeap(T arr[], int n) {

	IndexMinHeap<T> indexMinheap = IndexMinHeap<T>(n);
	for (int i = 0; i < n; i++)
		indexMinheap.insert(i, arr[i]);

	for (int i = 0; i < n; i++)
		arr[i] = indexMinheap.extractMin();

}



int main() {

	int n = 10000000;
	cout << "Test for Random Array, size = " << n << ", random range [0, " << n << "]" << endl;

	int *arr1 = generateRandomArray(n, 0, n);

	testSort("Heap Sort Using Max Heap", heapSortUsingMaxHeap, arr1, n);

	int *arr2 = copyIntArray(arr1, n);
	testSort("Heap Sort Using Min Heap", heapSortUsingMinHeap, arr2, n);
	delete[] arr2;

	int *arr3 = copyIntArray(arr1, n);
	testSort("Heap Sort Using Index Max Heap", heapSortUsingIndexMaxHeap, arr3, n);
	delete[] arr3;

	int *arr4 = copyIntArray(arr1, n);
	testSort("Heap Sort Using Index Min Heap", heapSortUsingIndexMinHeap, arr4, n);
	delete[] arr4;


	delete[] arr1;
	cout << endl;

	system("pause");
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值