前言
昨天看了codeship的视频,视频讲到程序员在学习的时候总要输出点什么,不然学了就忘记。我非常有感触,之前学过spring源码,dubbo源码,springbatch源码基本上看完了就忘记,为了巩固知识,我决定定期输出文档来作为自己的学习笔记。刚好最近在学习算法,那么我的博客就从算法写起。
简介
- 什么是堆
堆是一颗完全二叉树并且堆中每个节点的值都大于等于小于等于子树中每个节点的值。 - 时间复杂度
堆排序是一种原地排序算法,时间复杂度为O(nlog^n)
上图就是一个小顶堆因为上图是一棵完全二叉树并且满足任意一个节点的值都小于等于子节点的值 - 堆的数据存储:
一般用数组存储存储堆的数据比较简单易懂,我下面笔记都是用数组来对堆进行讲解。 - 建堆
建堆的过程是一个从无到有的过程
public class Heap {
private int[] arr;
//当前数量
private int count;
//堆数组大小
private int n;
public Heap(int[] arr, int count, int n) {
this.arr = arr;
this.count = count;
this.n = n;
}
/**
* 堆插入
* @param data
*/
public void insert(int data) {
if (n<=count){
return;
}
count++;
arr[count] = data;
int i=count;
int temp=0;
while (i/2>0 && arr[i/2] < arr[i]) {
temp = arr[i];
arr[i] = arr[i/2];
arr[i/2] = temp;
i=i/2;
}
}
/**
* 删除对顶元素
*/
public void removeMax() {
if (count == 0) {
return;
}
arr[1] = arr[count];
heapify();
}
public void heapify() {
int maxPos = 1;
int i=1;
while (true) {
if (2*i < n && arr[i] < arr[2*i]) {
maxPos = 2*i;
}
if ((2*i +1) < n && arr[maxPos] < arr[2*i + 1]) {
maxPos = 2*i +1;
}
if (i == maxPos) {
break;
}
int temp;
temp = arr[i];
arr[i] = arr[maxPos];
arr[maxPos] = temp;
i = maxPos;
}
}
/**
* 数组堆化
* 下标为0的位置没有数据
*/
public void arr2Heap(int[] a, int n) {
for (int i=n/2;i >= 1; i--) {
arr2Heapify(a, n, i);
}
}
public void arr2Heapify(int[] b, int m, int j) {
while(true) {
int maxPos = j;
if (j*2 <= m && b[j] < b[j*2]) {
maxPos = j*2;
}
if ((j*2 + 1) <= m && b[maxPos] < b[2*j+1]) {
maxPos = 2*j+1;
}
if (j == maxPos) {
break;
}
int temp;
temp = b[j];
b[j]=b[maxPos];
b[maxPos] = temp;
j= maxPos;
}
}
/**
* 1.首先建堆
* 2.大顶堆第一个元素就是最大,把它和最后一个元素n交换
* 3.重新构建n-1堆
* @param a
* @param i
*/
public void sort(int[] a, int i) {
//建堆
arr2Heap(a,i);
int k = i;
while(k>1) {
//交换
int temp;
temp = a[1];
a[1] = a[k];
a[k] = temp;
arr2Heapify(a,--k,1);
}
}
}