一、堆的数据结构分析
1)堆的定义
n个元素的序列{k1,k2,......,kn}当满足以下条件时我们称之为堆
ki>=k2i且ki>=k2i+1(大根堆) 或 ki<=k2i且ki<=k2i+1(小根堆)
2)堆特点
i)由于堆的逻辑结构为一颗完全二叉树,且完全二叉树的特点为已知第i个节点,可以得其左右孩子的下标节点分别为2i与2i+1,故以上的定义公式即为在这一颗完全二叉树中,根节点的位置一定要同时比其左右孩子节点值大或者是小,大即为大根堆小即为小根堆。
ii)虽然堆的逻辑结构为一颗完全二叉树,但是在具体的程序实现中还是用一个一维数组进行数据存储,易于实现,同时方便操作。
iii)数据结构堆中最大的特点是在这一颗完全二叉树中根节点的数值总是这组数据最大的或者是最小的数据,堆排序正是利用堆的这个特点实现。
二、堆排序基本思想
堆排序主要是利用了大根堆(小根堆)堆顶记录的关键字最大(或最小)这一特征来实现,具体算法过程如下
- 初建堆,按堆的定义将排序序列r[1...n]调整为大根堆(这里把关键字按升序排序)
- 交换数据,将堆顶记录与堆尾记录进行交换(r[1]与r[n]进行数据交换)
- 调整堆,将从堆顶记录到刚刚交换的堆尾记录(不包含)进行调整,重新调整为一个堆
- 循环n-1次,直到交换了r[1]与r[2]为止,最终得到一个递增的有序序列
三、程序实现----JAVA实现
1、调整堆实现
假设r[s+1,m]已经是堆的情况下,按筛选法将r[s...m]调整为以r[s]为根的堆
public void AdjustHandle(int index,int last) {
//当前节点的下标为index-1
int leftindex=index*2-1;
int rightindex=index*2;
index--;
if(leftindex<=last-1&&rightindex<=last-1) {
int maxindex=list.get(leftindex)>=list.get(rightindex)? leftindex:rightindex;
if(list.get(index)<list.get(maxindex)) {
int tmp=list.get(index);
list.set(index, list.get(maxindex));
list.set(maxindex,tmp);
AdjustHandle(maxindex+1,last);
}
}
else
if(leftindex==last-1){
int maxindex=leftindex;
if(list.get(index)<list.get(maxindex)) {
int tmp=list.get(index);
list.set(index, list.get(maxindex));
list.set(maxindex,tmp);
AdjustHandle(maxindex+1,last);
}
}
}
2、将一个无序序列创建为一个堆 思想:在一颗完全二叉树中,所有序号大于n/2的节点都是叶子节点,,因此以这些节点为根的子树均已是堆。这样只需使用上面所介绍的调整方法从最后一个分支节点n/2到1位置依次调整为堆,最后即可整体成为堆
程序实现:
public void CreateHeap() {
for(int i=list.size()/2;i>=1;i--) {
this.AdjustHandle(i,list.size());
}
}
3、堆排序最终实现
i)创建堆
ii)通过n-1次交换数据,继而调整堆,最后可得有序序列
程序实现:
public void HeapSort() {
for(int i=list.size()-1;i>=1;i--) {
this.Swap(0, i);
this.ShowList();
this.AdjustHandle(1, i);
}
}
public void Swap(int index1,int index2) {
int tmp=list.get(index1);
list.set(index1, list.get(index2));
list.set(index2, tmp);
}
四、附综合程序
HeapAdjust.java
package com.jz.heapsort;
import java.util.ArrayList;
import java.util.List;
//堆排序的类
public class HeapAdjust {
private List<Integer> list=new ArrayList<Integer>();
public HeapAdjust() {
list.add(49);
list.add(38);
list.add(65);
list.add(97);
list.add(76);
list.add(13);
list.add(27);
list.add(49);
}
public void ShowList() {
for(int i=0;i<list.size();i++) {
System.out.print(list.get(i)+"\t");
}
System.out.println();
}
public void MyHeapAdjust() {
this.AdjustHandle(1,list.size());
}
public void AdjustHandle(int index,int last) {
//当前节点的下标为index-1
int leftindex=index*2-1;
int rightindex=index*2;
index--;
if(leftindex<=last-1&&rightindex<=last-1) {
int maxindex=list.get(leftindex)>=list.get(rightindex)? leftindex:rightindex;
if(list.get(index)<list.get(maxindex)) {
int tmp=list.get(index);
list.set(index, list.get(maxindex));
list.set(maxindex,tmp);
AdjustHandle(maxindex+1,last);
}
}
else
if(leftindex==last-1){
int maxindex=leftindex;
if(list.get(index)<list.get(maxindex)) {
int tmp=list.get(index);
list.set(index, list.get(maxindex));
list.set(maxindex,tmp);
AdjustHandle(maxindex+1,last);
}
}
}
//将一个无序序列创建为一个堆
public void CreateHeap() {
for(int i=list.size()/2;i>=1;i--) {
this.AdjustHandle(i,list.size());
}
}
public void HeapSort() {
for(int i=list.size()-1;i>=1;i--) {
this.Swap(0, i);
this.ShowList();
this.AdjustHandle(1, i);
}
}
public void Swap(int index1,int index2) {
int tmp=list.get(index1);
list.set(index1, list.get(index2));
list.set(index2, tmp);
}
}
附:以上皆为本人原创,转载请注明出处