堆逻辑上是完全二叉树,物理上保存在数组中,有大堆、小堆之分。
大堆是满足任意结点的值都大于其子树中结点的值,而小堆是满足任意结点的值都小于其子树中结点的值。
堆的作用是找最值。
堆中有两种操作向上调整、向下调整,在大小堆中都有也有一定的差别。运用向上调整、向下调整可以实现建堆的过程。下面看看堆中的这些操作。
下面是数组中元素的交换:
//交换
public void swap(int[] arr,int i,int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
一、向下调整
大(小)堆的向下调整,就是将数据按照完全二叉树的结构,符合大(小)堆的特征。代码如下:
//大堆的向下调整
public void shiftDownBig(int[] arr,int sz,int parent) {
int child = 2*parent+1;
while (child < sz) {
if (child+1 < sz && arr[child+1] > arr[child]) {
child++;
}
if (arr[child] > arr[parent]) {
swap(arr,child,parent);
parent = child;
child = 2*parent+1;
} else {
break;
}
}
}
//小堆的向下调整
public void shiftDownSmall(int[] arr,int sz,int parent) {
int child = 2*parent+1;
while (child < sz) {
if (child+1 < sz && arr[child+1] < arr[child]) {
child++;
}
if (arr[child] < arr[parent]) {
swap(arr,child,parent);
parent = child;
child = 2*parent+1;
} else {
break;
}
}
}
建堆
根据向下调整,可以完成建堆,利用循环,代码如下:
//建堆
public void createHeapBig(int[] arr) {
for (int i = (arr.length-2)/2;i >= 0;i--) {
shiftDownBig(arr,arr.length,i);
}
}
public void createHeapSmall(int[] arr) {
for (int i = (arr.length-2)/2;i >= 0;i--) {
shiftDownSmall(arr,arr.length,i);
}
}
向上调整
大(小)堆的向上调整,就是将数据按照完全二叉树的结构,符合大(小)堆的特征。代码如下:
//大堆的向上调整
public void shiftUpBig(int[] arr,int sz,int child) {
int parent = (child-1)/2;
while (child > 0) {
if (arr[child] > arr[parent]) {
swap(arr,child,parent);
child = parent;
parent = (child-1)/2;
} else {
break;
}
}
}
//小堆的向上调整
public void shiftUpSmall(int[] arr,int sz,int child) {
int parent = (child-1)/2;
while (child > 0) {
if (arr[child] < arr[parent]) {
swap(arr,child,parent);
child = parent;
parent = (child-1)/2;
} else {
break;
}
}
}
建堆
根据向上调整,也可以完成建堆,利用循环,代码如下:
//建堆
public void createHeapUpBig(int[] arr) {
for (int i = (arr.length - 2)/2;i >= 0;i--) {
shiftUpBig(arr,arr.length,i);
}
}
public void createHeapUpSmall(int[] arr) {
for (int i = (arr.length - 2)/2;i >= 0;i--) {
shiftUpSmall(arr,arr.length,i);
}
}
以上就是堆中的向上调整、向下调整,并且用这些方法完成建堆的操作过程。