排序算法之堆排序 Java 实现


1.知识补充


###1.0 完全二叉树
一棵深度为K,有n个节点的二叉树,对树中节点按照从上至下,从左至右的顺序进行编号,如果编号为i(1<=i<=n)与满二叉树的编号为i的位置一致,则称此树为完全二叉树。
完全二叉树和非完全二叉树示意图.jpg

1.1满二叉树

满二叉树:如果一棵二叉树所有分支都存在左右子节点,且所有的叶子节点都在同一层,则成这棵树为满二叉树。
满二叉树(a)与非满二叉树(b).jpg

1.2 完全二叉树的性质(重点)

如果对具有n个节点二叉树的根节点从0开始编号,则序号为i的节点的双亲结点为(i-1)/2,左孩子的编号为2i+1,右孩子为2i+2。如果从1开始编号,则双亲结点编号为i/2,左孩子结点序号为2i,右孩子结点序号为2i+1.

2 堆(千呼万唤始出来)

堆:n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质):
(1)ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n/2),当然,这是小根堆,大根堆则换成>=号。//k(i)相当于二叉树的非叶子结点,K(2i)则是左子节点,k(2i+1)是右子节点
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:
树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。

3.堆得建立


算法思路:
1.我们首先将数组进行初始化调整成大根堆。
2.然后进行排序,每次排序时,将最后一个序号n节点的值与根节点0的值进行替换,然后将节点又调整成堆。
3.然后将根节点与n-1进行交换重复步骤2。直到序列为有序

3.1以大根堆为例:

 /**
     * 堆调整算法
     * @param num   数组
     * @param s 调整节序号
     * @param l 数组排序最大的序号 
     */
  public static void HeapAdjust(int[] num,int s,int l){
      int i,j;
      int temp=num[s];
      i=s;
      // 根据二叉树的性质可知道每一个序号对应的子节点以及双亲节点
      for(j=2*i+1;j<=l;j=2*j+1){
          //判断如果j指向数值较大的节点
          if(j<l&&num[j]<num[j+1]){
              j=j+1;
          }
          //如果调整节点大于其子节点最大的值则无需调整
          if(temp>num[j]){
              break;
          }
          //如果小于则将子节点移动到根节点位置,如果还存在子节点则继续判断调整位置的子节点
          //准备继续向下 调整节点
          num[i]=num[j];
          i=j;
      }
      //最后插入数据
      num[i]=temp;
  }                             

3.2堆的建立

   /**
     * 堆建立初始化函数
     * @param nums 数组序列
     * @param l 最大序号
     */
  public static void HeapInit(int[] nums,int l){
      for (int i = (l-1) / 2; i >=0; i--) {
          HeapAdjust(nums, i, l);
      }
  }

3.3 堆的排序算法

  public static void HeapSort(int[] nums,int l){
     for(int i=l;i>0;i--){
         int temp=nums[0];
         nums[0]=nums[i];
         nums[i]=temp;
         //因为每次调整都是对根节点进行调整所以下列方法s永远为0
         HeapAdjust(nums,0,i-1);
     }
  }

3.4最后我们来看看效果

 public static void main(String[] args){
        int[] nums={3,2,4,9,8};
        //第一步根据节点创建堆
        for (int i = (4-1) / 2; i >=0; i--) {
            HeapAdjust(nums, i, 4);
        }
        //第二步排序
        HeapSort(nums,4);
        for(int n:nums){
            System.out.println(n);
        }

    }

输出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值