[JavaDS]堆排序

堆中某个结点的值总是不大于或者不小于其父结点的值

堆总是一个完全二叉树

堆排序

如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储
在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为
小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

//堆排序 :
//时间复杂度:(nlog2n)
//空间复杂度:O(1)
//不稳定

接口:

package f.DS.Tree;
interface Heap {
    //初始化建立大根堆
    public void initHeap(int[] array);
    //向上调整,从孩子节点开始调整
    void AdjustDown(int child,int len);
    void AdjustUp(int child);
    // 插入 item 到堆中
    void pushHeap(int item);
    // 返回堆顶元素,删除数据元素
    int popHeap();
    // 返回堆顶元素,不删除数据元素
    int getHeapTop();
    //堆排序
    void HeapSort();
    //打印堆
    void show();
}

方法:

package f.DS.Tree;
import java.util.Arrays;
public class TestHeap implements Heap{
    private int[] elem;//定义数组elem[]
    private int usedSize;//定义数组的有效长度
    private  static final int DEFAULT_SIZE=10;//定义常量DEFAULT_SIZE
    public TestHeap(){
        this.elem=new int[DEFAULT_SIZE];//初始化elem[]
        this.usedSize=0;
    }
//    创建一个大根堆
    @Override
    public void initHeap(int[] array) {
        for (int i=0;i<array.length;i++){
            this.elem[i]=array[i];
            this.usedSize++;
        }
        for(int i=(array.length-1-1)/2;i>0;i--){//最后一棵字数的父亲结点(array.length-1-1)/2
            AdjustDown(i,this.usedSize);//每棵树向下调整 整棵树从下往上调整
        }
    }
    //判断是否为满
    public boolean isFull(){
        return this.usedSize==this.elem.length;
    }
    //每棵树向下调整 整棵树从下往上调整
    @Override
    public void AdjustDown(int root, int len) {
    int parent=root;//定义父节点
    int child=2*parent+1;//定义孩子结点
    while (child<len){
      if(child+1<len&&elem[child]<elem[child+1]){
          ++child;
      }
      //child下标存放左右孩子最大值
        if(elem[child]>elem[parent]){
          //交换
            int tmp=elem[child];
            elem[child]=elem[parent];
            elem[parent]=tmp;
            parent=child;
            child=2*parent+1;
        }else{
          break;
        }
    }
    }
    @Override
    public void AdjustUp(int child) {
    int parent = (child-1)/2;
    while (child>0){
        if(elem[child]>elem[parent]){
          int tmp=elem[child];
            elem[child]=elem[parent];
            elem[parent]=tmp;
            child=parent;
            parent=(child-1)/2;
        }else{
            break;
        }
    }//child==0时退出循环 大根堆排序结束
    }
    // 插入 item 到堆中
    @Override
    public void pushHeap(int item) {
    if(isFull()){
        this.elem=Arrays.copyOf(this.elem,2*this.elem.length);
    }
    this.elem[this.usedSize]=item;
    this.usedSize++;
    AdjustUp(this.usedSize-1);
    }

    public boolean isAmpty(){
        return this.usedSize==0;
    }
    // 返回堆顶元素,删除数据元素
    @Override
    public int popHeap() {
        if (isAmpty()) {
            throw new UnsupportedOperationException("堆为空");
        }
            int oldData=elem[0];
            int tmp = elem[0];
            elem[0] = elem[this.usedSize-1];
            elem[this.usedSize-1] = tmp;
            this.usedSize--;
            AdjustDown(0, this.usedSize );//向下调整为大根堆
            return oldData;
    }
    // 返回堆顶元素,不删除数据元素
    @Override
    public int getHeapTop() {
        if (isAmpty()) {
            throw new UnsupportedOperationException("堆为空");
        }
        return elem[0];
    }
    //堆排序
    @Override
    public void HeapSort() {
    int end=this.usedSize-1;
    while (end>0){
        int tmp = elem[0];
        elem[0] = elem[end];
        elem[end] = tmp;
        AdjustDown(0,end);
        end--;//调整后 再调整下标的前一个
    }
    }
    //打印堆
    @Override
    public void show() {
    for(int i=0;i<this.usedSize;i++){
        System.out.print(elem[i]+"  ");
    }
        System.out.println(" ");
    }
    public static void main(String[] args) {
        TestHeap testHeap=new TestHeap();
        int[] array={0,1,2,3,4,5,6,7,8,9};
        testHeap.initHeap(array);
        testHeap.show();
        testHeap.HeapSort();
        testHeap.show();
    }
}
//

输出结果:

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值