TopK问题
现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。
1 、堆的概念
- 堆中某个节点的值总是不大于或不小于其父节点的值;
- 堆总是一棵完全二叉树。
- 按照层序遍历的结果储存在数组中
- 堆的基本作用是快速找集合中的最值
2、堆的实现
2.1堆向下调整建大堆
前提:左右子树必须已经是一个堆,才能调整,即只有一个不满足堆的性质
private static void CreateBig(int[] arr, int index) {int max &#61; index * 2 &#43; 1;while (max < arr.length) {if (max &#43; 1 < arr.length && arr[max &#43; 1] > arr[max]) {max&#43;&#43;;}if (arr[index] < arr[max]) {int t &#61; arr[max];arr[max] &#61; arr[index];arr[index] &#61; t;index &#61; max;max &#61; 2 * index &#43; 1;} else {break;}}}
2.2堆向下调整建小堆
private static void CreateSmall(int[] arr, int index) {int min &#61; index * 2 &#43; 1;while (min < arr.length) {if (min &#43; 1 < arr.length && arr[min &#43; 1] < arr[min]) {min&#43;&#43;;}if (arr[index] <&#61; arr[min]) {break;}int t &#61; arr[min];arr[min] &#61; arr[index];arr[index] &#61; t;index &#61; min;min &#61; 2 * min &#43; 1;}}
2.3向上调整建大堆
&#64;Overridepublic void adjustUp(int[] array, int index) { int parent &#61; (index - 1) / 2;while (parent >&#61; 0) {if (item[index] > item[parent]) {int t &#61; item[index];item[index] &#61; item[parent];item[parent] &#61; t;index &#61; parent;parent &#61; (index - 1) / 2;} else {break;}}}
2.4建堆
给出一个数组&#xff0c;逻辑上是一个二叉树&#xff0c;但是还不是堆&#xff0c;从倒数的第一个非叶子节点的子树开始调整&#xff0c;一直调整到根节点的树&#xff0c;就可以调整成堆。
时间复杂度为O(N*logN)&#xff0c;实际是O&#xff08;N&#xff09;
private static void CreateHeap(int[] arr) {for (int i &#61; (arr.length - 1 - 1) / 2; i >&#61; 0; i--) {CreateBig(arr,i);}}
2.3堆的插入、查看、删除
public class IHeapImpl implements IHeap {private int[] item;private int userSize;public IHeapImpl(int[] arr) {this.item &#61;Arrays.copyOf(arr,arr.length);this.userSize &#61; 0;} &#64;Overridepublic void add(int item) {if (Full()) {this.item &#61; Arrays.copyOf(this.item, 2 * this.item.length &#43; 1);}this.item[userSize] &#61; item;this.userSize&#43;&#43;;adjustUp(this.item, this.userSize - 1);}&#64;Overridepublic void adjustUp(int[] array, int index) { int parent &#61; (index - 1) / 2;while (parent >&#61; 0) {if (item[index] > item[parent]) {int t &#61; item[index];item[index] &#61; item[parent];item[parent] &#61; t;index &#61; parent;parent &#61; (index - 1) / 2;} else {break;}}}&#64;Overridepublic int peek() {if (isEmpty()) {throw new UnsupportedOperationException("堆为空");}return this.item[0];}&#64;Overridepublic int pop() {if (isEmpty()) {throw new UnsupportedOperationException("堆为空");}int old&#61;this.item[0];int t &#61; this.item[0];this.item[0] &#61; this.item[this.userSize - 1];this.item[this.userSize - 1] &#61; t;this.userSize--;adjustDown(this.userSize , 0);return old;}&#64;Overridepublic void adjustDown(int len, int index) {int max &#61; index * 2 &#43; 1;while (max < len) {if (max &#43; 1 < len && this.item[max] < this.item[max &#43; 1]) {max&#43;&#43;;}if (item[index] >&#61; item[max]) {break;}int t &#61; item[index];item[index] &#61; item[max];item[max] &#61; t;index &#61; max;max &#61; index * 2 &#43; 1;}}&#64;Overridepublic void createHeap(int[] array) {this.userSize&#61;array.length;for (int i &#61; (array.length - 1 - 1) / 2; i >&#61; 0; i--) {adjustDown(this.userSize, i);}}&#64;Overridepublic void show() {for (int i &#61; 0; i < this.userSize; i&#43;&#43;) {System.out.print(item[i] &#43; " ");}}&#64;Overridepublic boolean Full() {return this.userSize &#61;&#61; this.item.length;}&#64;Overridepublic boolean isEmpty() {return this.userSize &#61;&#61; 0;}
}