您的位置:首页 > 编程语言 > Java开发

Java 堆排序

2017-05-30 22:20 169 查看
堆排序,我想了好几天,最后还是参考了一下别人的博客,看了许多的解释,不过还是下面这些最好理解:

http://www.ixywy.com/zsjz/2564.html (这篇的不是博客)

http://blog.csdn.net/zdp072/article/details/44227317 (csdn博客)

好了,代码如下:

package com.vgbh;

/*
* 堆排序
*/

public class heapSorting {

/*
堆排序算法思想:
堆排序,顾名思义,就是基于堆。

因此先来介绍一下堆的概念:
堆分为最大堆和最小堆,其实就是:完全二叉树或近似完全二叉树。
二叉树的特点:
1.最大堆要求节点的元素都要大于其孩子。
2.最小堆要求节点元素都小于其左右孩子。
有了上面的定义,我们可以得知,处于最大堆的根节点的元素一定是这个堆中的最大值。
其实我们的堆排序算法就是抓住了堆的这一特点,每次都取堆顶的元素,将其放在序列最后面,然后将剩余的元素重新调整为最大堆,依次类推,最终得到排序的序列。

本质上讲,堆排序是一种选择排序,每次都选择堆中最大的元素进行排序。只不过堆排序选择元素的方法更为先进,时间复杂度更低,效率更高。
*/

/*
步骤:
1 首先从第一个非叶子节点开始,比较当前节点和其孩子节点,将最大的元素放在当前节点,交换当前节点和最大节点元素。
2 将当前元素前面所有的元素都进行1的过程,这样就生成了最大堆
3 将堆顶元素和最后一个元素交换,列表长度减1。由此无序区减1,有序区加1
4 剩余元素重新调整建堆
5 继续3和4,直到所有元素都完成排序
*/

/*
时间复杂度:
堆排序的平均时间复杂度为O(nlogn),接近于最坏的时间复杂度。
在最好情况下,时间复杂度为O(1).
*/

/*
算法总结:
堆排序时间复杂度:O(nlogn)
堆排序对原始记录的排序状态并不敏感,其在性能上要远远好过于冒泡、简单选择、直接插入排序。
*/

private static int n = 10 ;//数组长度
private static int[] arr = new int
;//数组

static PublicOut pc = null ;//定义外部对象

public static int count = 0;//运行次数

public static void main(String[] args) {

pc = new PublicOut();
pc.data(arr, n);
pc.prin(arr, n);

heapSorting hs = new heapSorting();
hs.heap(arr);

pc.prin(arr, n);

//System.out.println("最后共运行" + count + "次。");

}

//数据结构的p281有详细的运算过程     详解:http://www.ixywy.com/zsjz/2564.html

//堆排序
public void heap (int[] arr) {
//将数组转化为大堆
for (int i=arr.length / 2; i>=0; i--) {
buildHeap(arr,i,arr.length);
}

//将最小值与最大值交换,并调整二叉树
for (int i=arr.length - 1; i>0; i--) {
swap(arr, 0, i);//将父元素和当前未经排序子序列的最后一个记录交换
buildHeap(arr, 0, i);//交换之后,重新比对二叉树,不符合则要调整。
}

}

/*
* 创建堆
* arr:数组
* x:需要构建堆的根节点的序号
* y:数组长度
*/
public void buildHeap (int[] arr,int x,int y) {
count++;
int child ;
int father ;
for (father = arr[x]; leftChild(x) < y; x = child) {
child = leftChild(x);

//如果左子树小于右子树,则需要比较右子树和父节点
if (child != y-1 && arr[child] < arr[child+1]) {
child++;//自增可以指向父节点
}

//如果父节点小于孩子节点,则需要交换
if (father < arr[child]) {
arr[x] = arr[child];
} else {
break;//大堆未被破坏,不需要调整
}
}
arr[x] = father;

}

//交换元素
public void swap (int[] arr,int x,int y) {
int tmp = arr[x];
arr[x] = arr[y];
arr[y] = tmp;
}

//获取左孩子结点
public int leftChild (int i) {
return 2 * i + 1;
}

}


如果关于堆排序还有不会的,可以发邮件到我的邮箱。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 堆排序