堆、堆排序和优先队列

1.堆排序同样具有空间原址性:任何时候都只需要常熟个额外的元素空间存储临时数据。因此,堆排序是集合了目前已经讨论的两种排序算法优点的一种排序算法
2.堆的用途:
排序
优先队列

3堆是一个数组,可以看成是一个近似的完全二叉树,树上的每个节点都对应数组的一个元素。除了最底层外,该树是完全充满的,而且是从左至右填充。
 A.length通常给出数组元素的个数
 A.heap-size表示有多少个堆元素存储在数组中,虽然A[1..A.length]可能都存有数据,但是只有A[1..A.heap-size]中存放的是堆的有效元素,0 <= A.heap-size <= A.length
 树的根节点是A[1]
 PARENT(i) --->  return i/2 的下取整
 LEFT(i)   --->  return 2i
 RIGHT(i)  --->  return 2i+1

维持堆的稳定性MAX-HEAPIFY(A, i),伪代码:

MAX-HEAPIFY(A, i){            //时间复杂度为O(h)
l = LEFT(i)
r = RIGHT(I)
if(l <= A.heap-size and A[l] > A[i])
largest = l;
else largest = i;
if(r <= A.heap-size and A[r] > A[largest])
largest = r;
if(largest != r)
exchange A[i] with A[largest]
MAX-HEAPIFY(A,largest);
}

建堆
使用MAX-HEAPIFY把一个大小为n=A.length的数组转换成最大堆。
BUILD-MAX-HEAP(A)
1.A.heap-size = A.length
2.for(i = A.length/2的下取整 to  1)
MAX-HEAPIFY(A, i)

堆排序
HEAPSORT(A)
BUILD-MAX-HEAP(A)
1 for(int i = A.length downto 2)
   exchange A[1] with A[i]
A.heap-size = A.heap-size -1
MAX-HEAPIFY(A, 1);
快速排序的性能一般会优于堆排序。

代码详见如下:

//数组是从1号位开始的
int leftChild(int i){
	return 2 * i;
}

int rightChild(int i){
	return 2 * i + 1;
}

int parent(int i){
	return i >> 1;
}

void swap(int *A, int i, int j){
	int temp = A[i];
	A[i] = A[j];
	A[j] = temp;
}

//维持最大堆的性质
void maxHeapify(int *A, int i){ 
	int l = leftChild(i);
	int r = rightChild(i);

	int largest = i;
	//与左孩子比较
	if (l <= heap_size && A[l] > A[largest]){
		largest = l;
	}
	//与右孩子比较
	if (r <= heap_size && A[r] > A[largest]){
		largest = r;
	}
	//自顶向下递归
	if (largest != i){
		swap(A, i, largest);
		maxHeapify(A, largest);
	}
}

//自底向上建堆
void createMaxHeap(int *A, int length){
	heap_size = length;
	for (int i = heap_size >> 1; i >= 1; i--){
		maxHeapify(A, i);
	}
}

//堆排序

void heapsort(int *A, int length){
	createMaxHeap(A, length);
	for (int i = length; i >= 2; i--){
		swap(A, 1, i);
		heap_size--;
		maxHeapify(A, 1);
	}
}

优先队列:

优先队列(priority queue)是一种用来维护一组元素构成的集合S的数据结构,其中的每一个元素都有一个相关的值,成为关键字(key)。

#define MAX_QUEUE_NUM 20

template<typename T>
class MaxPriorityQueue{
public:
	MaxPriorityQueue();
	~MaxPriorityQueue();
	bool empty(); //判断队列是否为空
	T& top();     //返回最大元素
	T& pop();   //删除最大元素
	int length();
	void push(T &t);  //插入一个元素
	void display();   //打印优先队列
private:
	int size;     //队列个数
	T *K;         //关键字数组
	int leftChild(int i);
	int rightChild(int i);
	int parent(int i);
	void maxHeapify(int i);
	void swap(int i, int j);
};

template<typename T>
int MaxPriorityQueue<T>::length(){
	return size;
}

template<typename T>
MaxPriorityQueue<T>::MaxPriorityQueue(){
	K = new T[MAX_QUEUE_NUM];
	size = 0;
}

template<typename T>
MaxPriorityQueue<T>::~MaxPriorityQueue(){

}

template<typename T>
bool MaxPriorityQueue<T>::empty(){
	if (size > 0){
		return false;
	}
	else{
		return true;
	}
}

template<typename T>
int MaxPriorityQueue<T>::leftChild(int i){
	return i << 1;
}

template<typename T>
int MaxPriorityQueue<T>::rightChild(int i){
	return (i << 1) + 1;
}

template<typename T>
int MaxPriorityQueue<T>::parent(int i){
	return i >> 1;
}

template<typename T>
void MaxPriorityQueue<T>::swap(int i, int j){
	T temp = K[i];
	K[i] = K[j];
	K[j] = temp;
}

template<typename T>
void MaxPriorityQueue<T>::maxHeapify(int i){
	int largest = i;
	int l = leftChild(i);
	int r = rightChild(i);
	if (l <= size && K[l] > K[largest])
		largest = l;
	if (r <= size && K[r] > K[largest])
		largest = r;
	if (largest != i){
		swap(i, largest);
		maxHeapify(largest);
	}
}

template<typename T>
T& MaxPriorityQueue<T>::top(){
	return K[1];
}

template<typename T>
T& MaxPriorityQueue<T>::pop(){
	if (size < 1){
		exit(0);
	}
	T max = K[1];
	K[1] = K[size];
	size--;
	maxHeapify(1);
	return max;
}

template<typename T>
void MaxPriorityQueue<T>::push(T &t){
	size++;
	K[size] = t;
	int i = size;
	int j = parent(i);
	while (i > 1 && K[parent(i)] < t){
		swap(i, parent(i));
		i = parent(i);
	}
}

template<typename T> 
void MaxPriorityQueue<T>::display(){
	int count = 1;
	int index = 1;
	for (int i = 1; i <= size; i++){
		cout << K[i] << "  ";
		if (i % count == 0){
			cout << endl;
			count = 2 * index + count;
			index++;
		}
	}
	cout << endl;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值