算法体系结构第六课

一、堆结构
采用一个数组进行堆结构的存储
heapSize以内的数便是堆结构
在这里插入图片描述

每个子节点的父节点下标:

							(i - 1) / 2

父节点的左孩子和右孩子的下标:

					2 * i + 1			2 * i + 2

二、heapInsert:(加进来的数进行调堆)
加到末尾的数不断与自己的父节点进行比较,直到到达根节点或者比自己的父节点的值小,就停下;

while (arr[index] > arr[(index - 1) / 2]) {
    
    
	swap(arr, index, (index - 1) / 2);
	index = (index - 1) / 2;
}

此代码有两个终止条件:
1.当index为0时,(index - 1) / 2也为0,终止;
2.index对应的值比(index - 1) / 2对应的值小,终止;

三、heapIfy(对某个值进行下沉)
判断它的左孩子是否存在,如果不存在,也就是左孩子下标小于heapSize,那么右孩子也必不存在;
如果右孩子存在则将俩孩子比较取最大的那个,再和父节点比较;
如果还是老子大,就直接break出来别比了,如果老子小,就和大的那个孩子交换,再跳到大的孩子的下标,继续比较;

记忆点:斜坡猜拳,比高位低的俩人先猜,猜输了就降位;

四、pop弹出最大数
如果是大根堆,把根节点的值和堆末尾的值进行调换,heapSize减一进行逻辑删除,调出前堆末尾的值,让调到根结点的值进行heapIfy即可;

记忆点:调换同时删除,下沉
	   门被很大的力气弹开
	   互换人质,换的时候把对面全干了,扔到海里

五、某位置的数发生波动,值突然变了(不知是变大还是变小),要求调堆
来个heapIfy,再来个heapInsert,总会调对;

六、时间复杂度
N个数的时间复杂度的上限是O(NlogN),其实要小一点,增加到了2N个数时,对于后面一个N而言,每个数的时间复杂度其实要比logN大一点,所以最好情况(下限)是O(NlogN),那不就是O(N*logN)嘛;

七、堆排序
1.调堆
(1)如果数组是一个元素一个元素的给的,那就只能用第一种调堆方式,就是一个一个地上浮;
(2)如果数组是一股脑给的,则可以用第二种方法:从最后一个元素进行下沉

2.排序
最后一个元素和第一个元素交换位置,这里可以设计的比较精巧,同时也是pop的实现方法:

int heapSize = arr.length;
swap(arr, 0, --heapSize);

让到达根节点的元素在新的heapSize上进行下沉;
重复上面代码即可;

记忆点: 上面的上浮,下面的下沉 
		盘古开天,女娲捏泥娃娃

八、给每个元素移动不超过k步就可以排好的数组排序
前k + 1个数里必定有一个是整个数组中最小的数

因为它最多移k位就要到达下标0

把这k + 1个数放进堆里,(用一个index变量,最终index会来到k + 1)
弹出堆顶放入数组的0位置,把现在index对应的元素值压到堆里,重复;
index越界时,堆中还有元素,故直接把堆里的全部弹出,用数组依次接受即可

记忆点: 俩兄弟还有燃豆子秸秆煮的豆子汤
		走了一步-->> + 1,把豆子放进锅里
		煮沸了的汤表面有颗豆子弹到了碗里,又拿了一颗新的扔进去
		最后把豆子全部倒到碗里
桩子:
	 剪刀(猜拳)---船头---混沌(泥巴)---锅子(瓷器)

Guess you like

Origin blog.csdn.net/dgytjhe/article/details/119516365