常用算法之堆排原理介绍与java实践
2016-04-09 21:04
561 查看
堆排是一种常见的排序算法,空间复杂度为o(1),时间复杂度是o(nlogn)。
原理介绍:
思想类似与冒泡排序、选择排序。逐步求取每个子树的最大值,直至最大值到达最顶层索引值为0的堆顶。
堆排是利用堆进行排序的方法。可分为大堆和小堆,即数值越大,所处堆的层级越靠上。
其中,堆在计算机中是一种数据结构,再细致点讲,是一个完全二叉树。
如果堆的底层用数组存储数据的话,则存在如下性质:
1、某元素序号为i,则其左右子树的序号分别为2i+1, 2i+2。
2、父节点的序号为(i-1)/2取整数。
算法步骤:
1、根据数组构建堆,此时,堆无序。构建堆的方法很简单:思想类似于广度优先。具体见后文源代码。
2、根据数组,构建有序堆(大堆或者小堆):从最后一个索引值开始,循环排序,并整理。具体见后文源代码。
3、构建出有序堆后,堆顶即是最值(最大或最小),将堆顶元素(即索引值为0)与堆内最大索引值交换。
4、忽略最大值元素后,对剩下元素组成的数组,循环步骤2、3,直到遍历完所有元素。
java源代码如下:
public class HeapSort {
public static void main(String[] args) {
int[] data9 = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };
int[] data6 = new int[] { 3, 1, 5, 6, 9, 10 };
print(data9);
System.out.println("排序开始.........");
heapSort(data9);
System.out.println("排序后的数组:");
print(data9);
}
public static void swap(int[] data, int i, int j) {
if (i == j) {
return;
}
data[i] = data[i] + data[j];
data[j] = data[i] - data[j];
data[i] = data[i] - data[j];
}
public static void heapSort(int[] data) {
for (int i = 0; i < data.length; i++) {
createMaxdHeap(data, data.length - 1 - i); //从最后一个元素开始
swap(data, 0, data.length - 1 - i);
print(data);
}
}
public static void createMaxdHeap(int[] data, int lastIndex) {
for (int i = (lastIndex - 1) / 2; i >= 0; i--) { // (lastIndex - 1) / 2 : 表示父节点索引
int k = i; // 保存当前正在判断的节点
while (2 * k + 1 <= lastIndex) { // 若当前节点的子节点存在
int biggerIndex = 2 * k + 1; // biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点
if (biggerIndex < lastIndex) { // 若右子节点存在,否则此时biggerIndex应该等于 lastIndex
if (data[biggerIndex] < data[biggerIndex + 1]) { // 若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的值
biggerIndex++;
}
}
if (data[k] < data[biggerIndex]) { // 若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k
swap(data, k, biggerIndex);
k = biggerIndex;
} else {
break;
}
}
}
}
public static void print(int[] data) {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + "\t");
}
System.out.println();
}
}
运行结果如下:
5 3
6 2 1
9 4
8 7
排序开始.........
3 8 6
7 1
5 4 2
9
2 7 6
3 1
5 4 8
9
4 3 6
2 1
5 7 8
9
4 3 5
2 1
6 7 8
9
1 3 4
2 5
6 7 8
9
2 3 1
4 5
6 7 8
9
1 2 3
4 5
6 7 8
9
1 2 3
4 5
6 7 8
9
1 2 3
4 5
6 7 8
9
排序后的数组:
1 2 3
4 5
6 7 8
9
参考文章:
1、http://jingyan.baidu.com/article/ab0b56308e59b3c15afa7d29.html
原理介绍:
思想类似与冒泡排序、选择排序。逐步求取每个子树的最大值,直至最大值到达最顶层索引值为0的堆顶。
堆排是利用堆进行排序的方法。可分为大堆和小堆,即数值越大,所处堆的层级越靠上。
其中,堆在计算机中是一种数据结构,再细致点讲,是一个完全二叉树。
如果堆的底层用数组存储数据的话,则存在如下性质:
1、某元素序号为i,则其左右子树的序号分别为2i+1, 2i+2。
2、父节点的序号为(i-1)/2取整数。
算法步骤:
1、根据数组构建堆,此时,堆无序。构建堆的方法很简单:思想类似于广度优先。具体见后文源代码。
2、根据数组,构建有序堆(大堆或者小堆):从最后一个索引值开始,循环排序,并整理。具体见后文源代码。
3、构建出有序堆后,堆顶即是最值(最大或最小),将堆顶元素(即索引值为0)与堆内最大索引值交换。
4、忽略最大值元素后,对剩下元素组成的数组,循环步骤2、3,直到遍历完所有元素。
java源代码如下:
public class HeapSort {
public static void main(String[] args) {
int[] data9 = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };
int[] data6 = new int[] { 3, 1, 5, 6, 9, 10 };
print(data9);
System.out.println("排序开始.........");
heapSort(data9);
System.out.println("排序后的数组:");
print(data9);
}
public static void swap(int[] data, int i, int j) {
if (i == j) {
return;
}
data[i] = data[i] + data[j];
data[j] = data[i] - data[j];
data[i] = data[i] - data[j];
}
public static void heapSort(int[] data) {
for (int i = 0; i < data.length; i++) {
createMaxdHeap(data, data.length - 1 - i); //从最后一个元素开始
swap(data, 0, data.length - 1 - i);
print(data);
}
}
public static void createMaxdHeap(int[] data, int lastIndex) {
for (int i = (lastIndex - 1) / 2; i >= 0; i--) { // (lastIndex - 1) / 2 : 表示父节点索引
int k = i; // 保存当前正在判断的节点
while (2 * k + 1 <= lastIndex) { // 若当前节点的子节点存在
int biggerIndex = 2 * k + 1; // biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点
if (biggerIndex < lastIndex) { // 若右子节点存在,否则此时biggerIndex应该等于 lastIndex
if (data[biggerIndex] < data[biggerIndex + 1]) { // 若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的值
biggerIndex++;
}
}
if (data[k] < data[biggerIndex]) { // 若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k
swap(data, k, biggerIndex);
k = biggerIndex;
} else {
break;
}
}
}
}
public static void print(int[] data) {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + "\t");
}
System.out.println();
}
}
运行结果如下:
5 3
6 2 1
9 4
8 7
排序开始.........
3 8 6
7 1
5 4 2
9
2 7 6
3 1
5 4 8
9
4 3 6
2 1
5 7 8
9
4 3 5
2 1
6 7 8
9
1 3 4
2 5
6 7 8
9
2 3 1
4 5
6 7 8
9
1 2 3
4 5
6 7 8
9
1 2 3
4 5
6 7 8
9
1 2 3
4 5
6 7 8
9
排序后的数组:
1 2 3
4 5
6 7 8
9
参考文章:
1、http://jingyan.baidu.com/article/ab0b56308e59b3c15afa7d29.html
相关文章推荐
- 基于java中stack与heap的区别,java中的垃圾回收机制的相关介绍
- Grow heap (frag case) 堆内存过大的深入解析
- 深入Java虚拟机
- Converting HEAP to MyISAM in SHOW PROCESSLIST
- 内部代码kghasp1发现某一Heap大小为0
- JDK5.0中JVM堆模型、GC垃圾收集详细解析
- 十大基本算法
- 排列组合
- tomcat OutOfMemoryError: PermGen space
- 优先堆也可以用链表
- STL学习记录(十四):其它几种算法
- 堆和栈的区别(转载)
- java heap out of memory分析
- 基础算法 冒泡排序
- 基础算法 快速排序
- 二叉堆--C语言实现
- davlik heap out of memory
- C/C++程序占用内存分析
- 排序算法(2)-堆排序