数据结构之排序算法(一)-堆排序

继上篇文章讲到堆的实现之后http://blog.csdn.net/tuke_tuke/article/details/50357939,下面可以使用堆来实现堆排序。

在堆的基础上实现堆排序的思路很简单:(这里使用最小堆,当然最大堆也可以)

   最小堆MinHeap就是最小的数在堆的根元素的位置。首先把一组数建堆,然后再不断的移除堆的根元素,由于每次移除的根元素都是现有堆的最小元素,故可得到所有元素的从小到大的顺序。

MinHeap.java

package heapsort;

import java.util.ArrayList;

public class MinHeap <E extends Comparable>{
private ArrayList<E> list=new ArrayList<E>();//用数组实现堆
	
    public MinHeap(){}
    public MinHeap(E[] objects){
    	for(int i=0;i<objects.length;i++){
    		add(objects[i]);
    	}
    }   
    public void add(E newObject){//添加一个元素
    	list.add(newObject);
    	int currentIndex=list.size()-1;
    	
    	while(currentIndex>0){
    		int parentIndex=(currentIndex-1)/2;//找到该结点的父结点
    		if(list.get(currentIndex).compareTo(list.get(parentIndex))<0){
    			//如果当前结点的值小于父结点就交换位置
    			E temp=list.get(currentIndex);
    			list.set(currentIndex, list.get(parentIndex));
    			list.set(parentIndex, temp);   			
    		}
    		else
    			break;
    		currentIndex=parentIndex;
    	}    	
    }
    
    public E remove(){//删除并返回根结点
    	if(list.size()==0) return null;
    	
    	E removeObject=list.get(0);
    	list.set(0, list.get(list.size()-1));//把最后一个结点放在根结点的位置
    	list.remove(list.size()-1);
    	
    	int currentIndex=0;
    	while(currentIndex<list.size()){
    		int leftChildIndex=2*currentIndex+1;
    		int rightChildIndex=2*currentIndex+2;//左右孩子结点的坐标
    		
    		if(leftChildIndex>=list.size())break;
    		//比较左右孩子的值,使maxIndex指向值小的结点
    		 int minIndex=leftChildIndex;
    		 if(rightChildIndex<list.size()){
    			 if(list.get(minIndex).compareTo(list.get(rightChildIndex))>0){
    				 minIndex=rightChildIndex;
    			 }
    		 }
    		 //如果当前结点的值大于其左右孩子中的大的值,就交换两个结点
    		 if(list.get(currentIndex).compareTo(list.get(minIndex))>0){
    	          E temp=list.get(minIndex);
    	          list.set(minIndex, list.get(currentIndex));
    	          list.set(currentIndex, temp);
    	          currentIndex=minIndex;
    	    	}
    		 else
    			 break;
    	}
    	
    	return removeObject;   	
    	
    }
    
    public int getSize(){
    	return list.size();
    }
}
HeapSort.java

package heapsort;

import java.awt.List;

public class HeapSort {
	
	public static<E extends Comparable> void heapSort(E[] list){
		MinHeap<E> heap=new MinHeap<E>();//最小堆类
		//先把数组添加到堆中,建堆
		for(int i=0;i<list.length;i++){
			heap.add(list[i]);
		}
		//然后在一次删除根结点,根结点总是最值
		/*for(int i=list.length-1;i>=0;i--){//利用最大堆排序
			list[i]=heap.remove();			
		}*/
		for(int i=0;i<=list.length-1;i++){//利用最小堆排序,不断的移除堆的根元素
			list[i]=heap.remove();	//每次都会调整堆		
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
         Integer[] list={22,43,11,24,27,21,54,35,23};
         System.out.println("堆排序前的数组是:");
         for(int i=0;i<list.length;i++){
        	 System.out.print(list[i]+"  ");
         }
         heapSort(list);//堆排序
         System.out.println();
         System.out.println("堆排序后的数组是:");
         for(int i=0;i<list.length;i++){
        	 System.out.print(list[i]+"  ");
         }
	}

}


算法分析

   运行时间主要是消耗在初始构建堆在重建堆时的反复筛选上。
在构建堆的过程中,因为我们是完全二叉树从最下层最右边的非终端结点开始构建,将它与其孩子进行比较和若有必要的互换,对于每个非终端结点来说,其实最多进行两次比较和互换操作,因此整个构建堆的时间复杂度为O(n)。
在正式排序时,第i次取堆顶记录重建堆需要用O(logi)的时间(完全二叉树的某个结点到根结点的距离为log2i+1),并且需要取n-1次堆顶记录,因此,重建堆的时间复杂度为O(nlogn)。
总体来说,堆排序的时间复杂度为O(nlogn)。由于堆排序对原始记录的排序状态并不敏感,因此它无论是最好、最坏和平均时间复杂度均为O(nlogn)


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值