数据结构基础加强之最小堆的实现与堆排序

来源:互联网 发布:linux 没有wget命令 编辑:程序博客网 时间:2024/05/22 12:54

 数据结构基础加强之最小堆的实现与堆排序

二叉堆的形式:

最小堆:根结点的值是所有堆结点中最小者,并且每个结点的值比其孩子结点小。
最大堆:根结点的值是所有堆结点中最大者,并且每个结点的值比其孩子结点大。


最小堆通常都是一棵完全二叉树,可以用数组来存储最小堆的值。

堆中父结点与子结点 的关系:

heap[father * 2] = heap[leftChild];  heap[father * 2 + 1] = heap[rightChild];

最大堆与最小堆基本做法基本一致,只要把实现代码中的小于变大于,大于变小于即可

最小堆的初始化:依次将节点加入堆数组中,每次进入新的结点加到堆数组的尾部,依次与父结点相比较,如果小于父结点则交换二者的位置。

//添加元素public void add(int item){size++;heap[size] = item;int curr = size;while (heap[curr] < heap[getFather(curr)]) {swap(curr,getFather(curr));curr = getFather(curr);}}

最小堆的调整:一处最小堆的根节点之后,需要调整堆数组使之成为一个新的堆。

可以采用以下方式来调整堆:将堆数组最后一个元素放到堆数组的首部,依次与左右子结点比较,把较小的值与根节点交换,然后递归,直至当前节点是叶子节点为止。

//元素下移调整public void pushDown(int pos){int smallChild;while (!isLeaf(pos)) {smallChild = getLeftChild(pos);//在父节点知道的情况下,左节点不会出现越界情况,右节点可能越界if (smallChild <= size) { if (getRightChild(pos) <= size && heap[smallChild] > heap[smallChild + 1]) {smallChild++;}if (heap[pos] > heap[smallChild]) {swap(pos,smallChild);pos = smallChild;}else {return;}}else {return;}}}

堆排序的实现:

利用建立的堆实现堆排序比较简单。将数组中的元素依次加入最小堆中,每次取出堆数组的第一个元素,即最小值放到待排序数组的首部。每次取出堆数组第一个元素后,堆数组会自己调整,让它继续是一个最小堆。依次取出最数组的中的第一个元素,依次放入待排序数组中,直至堆数组为空,此时待排序数组是有序的。

堆排序实现代码:

import heap.Heap;public class HeapSort {public static void main(String[] args) {int[] array = { 1, 9, 6, 8, 7, 3, 4, 2, 0 };solution(array);for (int i : array) {System.out.print(i + " ");}}private static void solution(int[] array) {Heap heap = new Heap(10);for (int i : array) {heap.add(i);}for (int i = 0;i < array.length;i++) {array[i] = heap.delete();}}}
最小堆的实现代码:

public class Heap {private int[] heap;private int size;//当前节点数@SuppressWarnings("unused")private int max; //最大节点数//使用数组存储堆元素  根节点位于数组下表为1的元素public Heap(int max){this.max = max;heap = new int[max];size = 0;heap[0] = Integer.MIN_VALUE;}//获得父节点的位置public int getFather(int index){return index / 2;}//获得左子节点的位置public int getLeftChild(int index){return index * 2;}//获得右子节点的位置public int getRightChild(int index){return index * 2 + 1;}//判断节点是否为根节点public boolean isLeaf(int index){if (index > size / 2 && index < size) {return true;}else{return false;}}//判断堆是否为空public boolean isEmpty(){if (size == 0) {return true;}else{return false;}}//元素交换public void swap(int pos1,int pos2){int temp = heap[pos1];heap[pos1] = heap[pos2];heap[pos2] = temp;}//打印所有节点public void print(){for (int i = 1;i <= size;i++) {System.out.print(heap[i] + " ");}}//添加元素public void add(int item){size++;heap[size] = item;int curr = size;while (heap[curr] < heap[getFather(curr)]) {swap(curr,getFather(curr));curr = getFather(curr);}}//删除并返回根节点public int delete(){int firstItem = heap[1];swap(1, size);size--;if (size != 1) {pushDown(1);}return firstItem;}//元素下移调整public void pushDown(int pos){int smallChild;while (!isLeaf(pos)) {smallChild = getLeftChild(pos);//在父节点知道的情况下,左节点不会出现越界情况,右节点可能越界if (smallChild <= size) { if (getRightChild(pos) <= size && heap[smallChild] > heap[smallChild + 1]) {smallChild++;}if (heap[pos] > heap[smallChild]) {swap(pos,smallChild);pos = smallChild;}else {return;}}else {return;}}}}
具体代码可以参考:https://github.com/Li-JY/algorithm-and-datastructure/tree/master/src/heap


原创粉丝点击