算法-堆排序

堆排序算法

堆排序算法是基于选择排序思想的算法,其利用堆结构和二叉树的一些性质来完成数据的排序。
堆排序的关键是首先构造堆结构。堆结构是一种树结构,准确来说是一个完全二叉树。
在这个树中每个结点对应于原始数据的一个记录,并且每个结点应满足以下条件:(最小堆,最大堆)
1如果按照从小到大的顺序排序,要求非叶结点的数据要大于或等于其左,右子结点的数据。
2如果按照从大到小的顺序排序,要求非叶结点的数据要小于或等于其左,右子结点的数据。

过程

一个完整的堆排序需要经过反复的两个步骤:构造堆结构和堆排序输出。 筛运算进行结点数据的调整,直到所有结点最后满足堆结构的条件为止。
筛运算主要针对非叶结点进行调整。

二叉堆的定义

二叉堆是完全二叉树或者是近似完全二叉树。 二叉堆满足二个特性:
1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。
当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。

堆的存储

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

代码

public class HeapSort {
    void swap(int[] data,int i,int j){//交换结点
        if(i==j){
            return;
        }
        int temp=data[i];
        data[i]=data[j];
        data[j]=temp;
    }

    void createMaxHeap(int[] data,int lastIndex){
        //从 堆结构中最后一个结点lastIndex 开始重新构造堆结构
        for(int node=(lastIndex-1)/2;node>=0;node--){//(lastIndex-1)/2为lastIndex的父结点下标
            //保存当前正在判断的节点
            int current=node;
            //若当前结点的子结点存在
            while(2*current+1<=lastIndex){
                //biggerIndex总是记录较大结点的下标,先赋值为当前判断结点的左子结点
                int biggerIndex=2*current+1;//左子结点
                if(biggerIndex<lastIndex){
                    //若右子结点存在,否则此时biggerIndex应该等于lastIndex
                    if(data[biggerIndex]<data[biggerIndex+1]){
                        //若右子结点值比左子结点值大,则biggerIndex记录的是右子结点的下标值
                        biggerIndex++;//右子结点
                    }
                }
                if(data[current]<data[biggerIndex]){
                    //若当前结点值比子结点最大值小,则交换两者的值,交换后将biggerIndex值赋值给current
                    swap(data,current,biggerIndex);
                    current=biggerIndex;//重新调整 子树的堆结构
                }else{
                    break;
                }
            }
        }
    }

    void toHeadpSort(int[] data){
        for(int i=0;i<data.length-1;i++){
            createMaxHeap(data,data.length-1-i);//构造堆结构 
            swap(data,0,data.length-1-i);//堆排序输出
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值