最小堆操作(元素的添加和删除)

先引用我一直很膜拜的牛人MoreWindows在堆排序中的一段内容,该内容详细讲述了最小堆,以及在最小堆中添加/删除元素的原理。

二叉堆的定义

二叉堆是完全二叉树或者是近似完全二叉树。

二叉堆满足二个特性:

1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。下图展示一个最小堆:

由于其它几种堆(二项式堆,斐波纳契堆等)用的较少,一般将二叉堆就简称为堆。

堆的操作——插入删除

堆的存储

一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。

下面先给出《数据结构C++语言描述》中最小堆的建立插入删除的图解,再给出本人的实现代码,最好是先看明白图后再去看代码。

下面的内容是我自己编写的一个在最小堆上添加、删除元素的算法示例。首先建立了一个堆操作的接口,方便以后对堆操作的扩展。

public interface HeapOperation {
	int[] addNumber(int[] array, int length, int num);
	int[] deleteNumber(int[] array, int length);
}


1.最小堆添加元素

最小堆添加元素的操作流程类似于 排序算法之插入算法,先将需要添加的元素插入数组尾部,然后按照插入算法对堆进行调整。

public int[] addNumber(int[] array, int length, int num) {
		int[] newArray = new int[length + 1];
		for(int i = 0; i < length; i++) {
			newArray[i] = array[i];
		}
		newArray[length] = num;
		MinHeapFixup(newArray, length + 1);
		return newArray;
	}

private void MinHeapFixup(int[] array, int length) {
		int i, j, temp;
		temp = array[length - 1];
		i = length - 1;
		j = (i - 1) / 2;
		while(j >= 0 && i != 0) {
			if(array[j] < array[i]) {
				break;
			}
			array[i] = array[j];
			i = j;
			j = (i - 1) / 2;
		}
		array[i] = temp;
	}


对函数MinHeapFixup进行简化,如下:

private void MinHeapFixup(int[] array, int i) {
		int k = i - 1;
		for(int j = (k-1)/2; j >= 0 && k!= 0 && array[j] > array[k]; k = j, j = (k-1)/2) {
			swap(array, k, j);
		}
	}


其中swap函数是将数组array的脚标为k和j的两个元素进行交换。

private void swap(int[] array, int i, int j) {
		array[i] = array[i] + array[j];
		array[j] = array[i] - array[j];
		array[i] = array[i] - array[j];
	}


2.最小堆删除元素

按照最小堆删除元素步骤,算法设计如下:

public int[] deleteNumber(int[] array, int length) {
		swap(array, 0, length - 1);
		return MixHeapFixdown(array, 0, length - 1);
	}

private int[] MixHeapFixdown(int[] array, int i, int n) {
		int temp = array[i];
		int j = 2 * i + 1;
		int[] newArray = new int[n];
		while(j < n) {
			if(j + 1 < n && array[j] > array[j+1]) {
				j++;
			}
			if(array[j] >= temp) {
				break;
			}
			array[i] = array[j];
			i = j;
			j = 2 * i + 1;
		}
		array[i] = temp;
		for(j = 0; j < n; j++) {
			newArray[j] = array[j];
		}
		return newArray;
	}


对上述算法进行验证,结果与理论结果一致。

public class Client {
	private static void print(int[] array) {
		for(int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " ");
		}
	}

	public static void main(String[] args) {
		int[] array = {10, 40, 30};
		MinHeapOperation mho = new MinHeapOperation();
		int[] arrayForAdd = mho.addNumber(array, array.length, 15);
		print(arrayForAdd);
		System.out.println();
		int[] arrayForDelete = mho.deleteNumber(arrayForAdd, arrayForAdd.length);
		print(arrayForDelete);
	}

}


已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页