我们今天来学习二叉树的链式存储,但是在我们学习之前我们先来看一下我们昨天学习的顺序存储:二叉树;
我们之前说堆有两种方法:
1.向下调整建堆:
我们找到最后一个非叶子结点,把他作为起始下标;然后进行向下调整,完成后一i--;这样不断重复,直到i变成0,我们的堆就建完了;
我们来看这图片,我们的下标为2的结点是叶子节点,所以我们就要从1(叶子节点)开始,往前遍历,直到i变成0;
向下调整建堆的时间复杂度是O(n);
//在这里说明一下:向下调整方法的时间复杂度是O(log(n));//对于一个具有n个结点的堆来说,堆的高度就是我们的时间复杂度:log2^(n+1);这就可以化成log(n);所以这就是我们的向下调整的时间复杂度;
:向下调整建堆的时间复杂度是O(n);
因为向下调整是除了叶子节点之外,所有的结点都要进行向下调整的;所以是n*log(n),直接化简成n了;
2.向上调整建堆:
从第一个结点我们进行排列,进行相声调整建堆;最后成堆;
我们今天来说一个新的东西:
TOP-K问题
TOP-K问题:即求数据结合中前K个最⼤的元素或者最⼩的元素,⼀般情况下数据量都⽐较⼤。 ⽐如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。 对于Top-K问题,能想到的最简单直接的⽅式就是排序,但是:如果数据量⾮常⼤,排序就不太可取了 (可能数据都不能⼀下⼦全部加载到内存中)。最佳的⽅式就是⽤堆来解决;
因为这样排序的话,数据是非常多的,排序是不可取的,这里的话,我们就可以使用堆排序来解决;
我们要存储10亿个整数;需要4G的内存空间;但是我们现在只有1G,或者是跟小的空间;那么我们怎么才可以完成在10亿空间里面找数据呢?
我们可以把10亿的数据的四分之一拿出来存起来,然后对其进行建堆:
1.(我们把他的最后一个非叶子节点作为我们的第一个下标,进行循环直到我们的下标变成负数,我们的根节点也是要进行向下调整的)建堆完成以后;
2.我们遍历剩下来的数据,我们把每个数据进行遍历,看他是不是大于或者小于我们的堆顶,然后我们就根据我们是要这些个数据里面最大的那些数据,还是最小的数据;
如果想要大的部分的数据的话,我们就建小堆,我们的堆顶就是最小的数据,然后我们进行遍历,如果数据是大于我们的堆顶,我们就把他换进来,因为这时候除了我们的堆顶,我们的其他的堆都是正常的堆的数据结构,所以的话,这时候就满足我们的向下调整法,所以我们这时候就使用一个也向下调整;
这样不断地进行遍历,直到我们的数据遍历完,我们就结束了;然后这时候的堆,就是我们要求的,这时候的堆就是我们要的这些个数据里面最大的或者最小的那部分数据;
当我们想要一大片数据里面的最大的部分的时候,我们采用堆排序,我们创建小堆。
当我们想要一大片数据里面的最小的部分的时候,我们采用堆排序,我们创建大堆。