每日一题———37.堆排序

前言

数据结构每日一题

声明:因个人能力有限,本文仅是个人的学习记录笔记,有错误之处还望指出

概念

:n个关键序列L[1,2…n],满足下面一条性质称为堆
大根堆:满足L(i) >= L(2i) 且L(i)>=L(2i+1)
小根堆:满足L(i) <= L(2i) 且L(i)<=L(2i+1)
可以类比二叉树,(2i左边叶子节点,2i+1右边叶子节点),但是不一样的是,在大根堆中只需要满足:根 >= 左 右与顺序无关,小根堆也一样:只要满足:根 < 左 右即可

思想(建立大根堆)

  1. 先把所有的非终端节点(n/2)都检查一遍,是否满足大根堆的要求(根 >左 右子树端点
  2. 不满足则进行调整,将更小的元素下坠,一直到满足要求
//建立大根堆
void BuildMaxHeap(int a[],int len){
	for(int i=len/2; i>0;i++)	//从非终端节点开始向前调整
		HeadAdjust(a,i,len);
}

//下坠调整
void HeadAdjust(int a[],int k,int len){
	a[0]=a[k];	//暂时存放根节点
	//从左孩子开始,沿K较大的节点向下调整
	for(int i=2*k;i<=len;i*=2){
		if(i<len&&a[i] <a[i+1])		//选取key较大的子节点下标
			i++;
		if(a[0] >= a[i])	break;	//结束筛选,都已经满足 根 > 左 右的情况
		else{
			a[k]=a[i];		//将a[i]调整到双亲上
			k=i;
		}
	}
	a[k]=a[i];		//将被筛选的节点放入最终位置
}

结论

  1. 基于大根堆的序列:递增序列
  2. 基于小根堆的序列:递减序列
  3. 在比较的时候如果根节点有两个孩子比较两次,否则比较一次即可
  4. 将整棵树调整为大根堆,关键字比较的次数不超过 4n,建堆的时间复杂度为0(N),对其排序的时间复杂度为nlog2n
  5. 堆是一棵完全二叉树,采用一维数组存储,但不是二叉排序树
  6. 在有n个节点的堆中插入 / 删除元素的时间复杂度为log2n,
而塞过 2021-6-21

你可能感兴趣的:(每日一题,堆数据结构,大根堆,小根堆,建堆算法,时间复杂度)