堆排序算法学习及其应用:优先队列

本文深入探讨堆排序算法及最大堆的构建与维护,详细解析堆中节点高度概念,阐述如何通过自底向上的方法建立最大堆,并利用堆排序算法进行高效数据排序。同时,提供了C++代码实现,帮助读者理解堆排序的具体操作流程。
摘要由CSDN通过智能技术生成

1、堆介绍:
堆排序:时间复杂度为O(nlgn),具有空间原址性;
堆中节点高度:该节点到叶节点最长简单路径上边的数目,n个元素的堆可以看作完全二叉树,堆的高度为lg(n)
最大堆:两个子树上所有节点的值均不大于它的根结点的值

2、维护堆的性质:
A[i]的值在最大堆中==“逐级下降”==,从而使得以下表i为根节点的子树重新遵循最大堆性质。
在这里插入图片描述
伪代码:(核心代码段)
在这里插入图片描述

3、建立最大堆:
自底向上的方法利用过程MAX_HEPITY把一个大小为n的数组转化为最大堆。
伪代码:
在这里插入图片描述
4、堆排序算法:
首先建立最大堆,然后将根节点A[1]与A[n]交换,利用MAX_HEPIFY调整交换后节点A[i]应该在的位置。
伪代码:
在这里插入图片描述
C++代码:
注意:此代码中堆顶元素为A[0]。

void HeapSort(int* A, int N) //算法入口
{
	for(int i = N/2;i>=0;i--){ //自底向上,建立最大堆
		max_heapify(A,i,N)}
	for(int i = N-1;i>0;i--){ // 交换堆顶元素到数组末尾,实现排序
		Swap(A[0],A[i]);
		max_heapify(A,0,i);
	}
}

//此处用循环代替了第2部分中描述的递归
void max_heapify(int* A,int i, int j) // j代表堆中元素个数
{
	int parent = i;
	int tmp; //用于记录父节点的值
	int child;
	for(;parent*2+1<=j-1;parent = child ){ // 在左孩子节点下标没超出数组范围时循环
		tmp = A[parent];
		child = parent*2+1;
		if(; child!=j-1 && A[child+1]>A[child]){ // 存在右孩子,且大于左孩子
			child= child +1; //最大孩子为右孩子
		}
		if(A[parent]>A[child]) break;
		else A[paernt] = A[child];
	}
	A[paernt] = tmp;
}

5、优先队列:
伪代码描述:

  1. heap_maximum(A) //返回堆最大值
    return A[0];
    
  2. heap_extract_maximum(A) //删除堆最大值并返回
    if(A.heap_size<1) error "heap underflow";
    max = A[0];
    A[0] = A[size-1];
    max_heapify(A,0,size-2);
    return max;
    
    将末尾元素放到堆顶并调用下筛代码
  3. heap_insert(A,key) // 插入新值
    A[size] = key;
    int i = size;
    while(i>0&&A[i/2]<A[i]){
    	swap(A[i/2],A[i]);
    	i = i/2;
    }
    
    先将插入的值放到末尾,然后其与父节点比较,大则上移。

总结:

1、记住此部分调整最大堆的代码(下筛):“2、维护堆的性质:”
2、建立最大堆,肯定是先建立小堆再扩展,因此先从最末尾的根节点开始建立。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值