大顶堆、小顶堆、堆排序

堆的定义:

     n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。

     大顶堆:k>= k2i 且k>= k2i+1。

     小顶堆:k<= k2i 且k<= k2i+1。

      堆序列可以理解成一个完全二叉树,该树任意一个结点的关键字的值都小于或等于它的孩子结点的关键字。例如:

      

堆排序:

  若在输出堆顶的最小值之后,使得剩余n-1个元素的序列重又建成一个堆,则得到n个元素的次小值。如此反复执行,便能得到一个有序序列,这个过程称之为堆排序

   实现堆排序需要解决两个问题:

   1.如何由一个无序序列建成一个堆?

    n个元素的序列,从最后一个节点的父节点开始建堆,这个父节点为第n/2个元素。然后依次往上递减(n/2--)筛选出最大值或最小值,将树顶端的最大值或是最小值与最后一个元素交换。方法buildMaxHeap()的功能。

   2.如何在输出堆顶元素之后,调整剩余元素成为一个新的堆?

   对剩下的n-1个元素重新建堆,重复1中方法。

package sort;
public class HeadSort {   

    //public int[] headSort(int[] sortArray)  
public void headSort(int[] sortArray)  
    {  
        for(int i=0;i<sortArray.length-1;i++)     //需进行n-1趟排序
        {  
           buildMaxHeap(sortArray,sortArray.length-1-i);  
           swap(sortArray,0,sortArray.length-1-i);  
        }  
        //return sortArray;  
    }  
    
    //交换两个数据的方法  
    public void swap(int[] data,int i,int j)  
    {  
        int temp = data[i];  
        data[i] = data[j];  
        data[j] = temp;  
    }  
    
    //建立大顶堆  
    public void buildMaxHeap(int[] data,int lastIndex)  
    {  
    //从lastIndex节点的父节点i开始建堆  
         for(int i=(lastIndex-1)/2;i>=0;i--)  
        {         
        int biggerIndex = 2*i+1;     //假设左节点的值是最大的
        //若存在右结点
        if(biggerIndex < lastIndex)  
               {  
                   //选出子节点中最大的值  
                   if(data[biggerIndex] <= data[biggerIndex+1])  
                  {  
                biggerIndex++;  
                  }  
              }
        //将左右结点父结点中的最大值放到父节点中
        if(data[i] <=data[biggerIndex])  
              {  
                 swap(data,i,biggerIndex);  
              }                    
        }  
    }   
      
    public static void main(String args[])  
    {  
        int a[] = {5,3,8,4,6,7,2,1};  
        HeadSort as = new HeadSort();
        as.headSort(a);
       // int[] result = new HeadSort().headSort(a);  
        for(int i=0;i<a.length;i++)  
        {  
            System.out.println(a[i]);  
        }  
    }       
}       
}  

        用于从多个数中找出最大(小)的n个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值