最小堆:每个节点的值都小于其左孩子和右孩子节点的值。
1.按完全二叉树的顺序插入要排序的元素。
2.若此元素a大于它的根节点b,则a和b交换位置。![](https://img-blog.csdnimg.cn/9dea4adf35794eed94b900f932390c8d.PNG?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAd2VpeGluXzUxMzkyNzI0,size_20,color_FFFFFF,t_70,g_se,x_16)
取数据时:
1.取得根节点的数据,然后把完全二叉树的最后一个节点放到根节点的位置上。
2.从根节点,重新对堆排序。
循环
(1)若根节点(把此数据记为a)大于 最小值的孩子节点,则交换。
(2)若仍不符合最小堆,从a当前的位置进一步和它的孩子节点交换,即执行(1);
(3)若符合了最小堆,则退出循环。
public void swap(ArrayList<Long> list, int last, int now) {
Long mid = list.get(last);
list.set(last, list.get(now));
list.set(now, mid);
}
//往堆中放入数据
public void put(ArrayList<Long> list, long num) {
list.add(num); //把num放到堆的完全二叉树的最后一个节点。
int now = list.size() - 1; //
while (now > 1) {
int last = now / 2; //获取父节点的位置。
if (list.get(last) > list.get(now)) { //比较父节点和子节点的大小。
swap(list, last, now); //若父节点大于子节点,则交换。
} else break; //若子节点大于父节点,则不用改用,加入此元素后即为最小堆。
//把父节点的位置给子节点,为了与父节点上面的节点作比较,。
now = last; //父子节点交换后,子节点再与 父节点以上的节点 比较。
}
}
//从堆中取数据
public long get(ArrayList<Long> list) {
Long res = list.get(0); //获取根节点,即为取得的数据。
list.set(1, list.get(list.size() - 1)); //把完全二叉树中的最后一个节点(称作a)放到根节点的位置。
list.remove(list.size() - 1); //由于取走了原本的根节点,所以堆的数据少了一个。
int now = 1; //当前a所在的位置为根节点1
/*调整最小堆。*/
while (now * 2 <= list.size() - 1) {
int next = now * 2; //next是a的左孩子。
//找出a的左右孩子中最小的那个,记为b;
if (now * 2 < list.size() - 1 && list.get(next) > list.get(next + 1))
next++;
//若最小的孩子b的值 > a 那么最小堆成立,直接break;
if (list.get(next) > list.get(now))
break;
//否则,交换。
else swap(list, now, next);
now = next;
}
return res;
}