您的位置:首页 > 编程语言 > Java开发

Java实现堆排序

2015-03-26 13:08 176 查看
上篇博文用Java实现了堆的基本操作,包括建立堆,移除堆顶的元素等。

我们知道,堆是一种弱序的数据结构,也就是说堆中的元素并非完全有序,但是我们可以利用堆的一些操作特性实现排序,使关键字完全有序。基本步骤包括以下几点:

1、初始化堆,直接将关键字依次插入到堆中,而不必每次进行调整。(此时确切的讲,堆数组不满足堆的特性,也暂时称不上是堆)

2、以数组中最后一个元素的父结点为基准,对其进行向下调整,调整完成后,继续对该结点的上一个结点进行向下调整。等对所有元素调整完成后,此时的数组才是真正意义上的堆。(在这里我们并没有在第一步进行数据插入的时候就对每个关键字进行堆的向上调整,因为这样做会调用N次向上调整,而用这里的方法向下调整,只需要调用N/2次向下调整)

3、将堆顶元素取出,将堆最后一个元素放到堆顶,并将取出的堆顶元素放到堆尾,堆的大小减一。对堆顶元素进行向下调整。依次进行这步操作,我们会发现数组尾部的元素关键字是依次有序的,原因就是我们每次从堆顶取出的元素都是最大(大顶堆)或最小值(小顶堆)。

上述三步的代码:

Heap heap = new Heap(9);
for(int i = 0; i < heap.getMaxSize(); i++){
	heap.insertNodeUnsort(i,new HeapNode( (int)(java.lang.Math.random()*100) )  );//这里插入结点,当前结点数并不自增,所以要手动增加
	heap.setCurrentSize(i+1);
}
for(int j = (heap.getCurrentSize()-1-1)/2; j >=0 ;j--){//调整成堆
	heap.trickleDown(j);
}

for(int k = heap.getCurrentSize()-1; k > 0; k--){
	HeapNode temp = heap.deleteRootNode();//删除结点后,结点数自减
	heap.insertNodeUnsort(heap.getCurrentSize(), temp);//当前结点数的下标的位置是之前最后一个结点的位置
	
}
heap.displayHeap();
若仅仅对一个给定的堆进行关键字的有序排序,则只需要进行第三个for循环就可以了。

public HeapNode deleteRootNode(){
		if(currentSize == 0){
			return null;
		}
		HeapNode root = heapArray[0];//需要时可将其返回
		heapArray[0] = heapArray[--currentSize];
		trickleDown(0);//删除根结点后,将最后一个结点放到堆顶,对其向下进行调整;
		return root;
	}
    public void trickleDown(int index){
        int leftChild ;
        int rightChild ;
        while(index < currentSize && index >= 0){
            leftChild = 2*index + 1;
            rightChild = 2*index + 2;
            if(leftChild >= currentSize){//如果左孩子不存在
                return;
            }else if(rightChild >= currentSize){//如果左孩子存在,右孩子不存在
                if(heapArray[leftChild].getKey() > heapArray[index].getKey()){
                    swapNode(heapArray,index,leftChild);
                    index = leftChild;
                }else
                    return;
            }
            else{//如果左右孩子都存在
                if(heapArray[leftChild].getKey() > heapArray[rightChild].getKey()){//若左孩子大
                    if(heapArray[leftChild].getKey() > heapArray[index].getKey()){//若左孩子比当前值大
                        swapNode(heapArray,index,leftChild);
                        index = leftChild;
                    }
                    else
                        return;
                }else{
                    if(heapArray[rightChild].getKey() > heapArray[index].getKey()){
                        swapNode(heapArray,index,rightChild);
                        index = rightChild;
                    }
                    else
                        return;
                }
            }//end of if-else
        }//while
    }//end of method
    public void swapNode(HeapNode[] array, int index1, int index2){
        HeapNode temp = array[index1];
        array[index1] = array[index2];
        array[index2] = temp;
    }
public boolean insertNodeUnsort(int index, HeapNode node){
		if(maxSize == currentSize){
			return false;
		}
		heapArray[index] = node;
		return true;
	}
堆排序的完整代码:

package test2;
class HeapNode{
private int key;
public HeapNode(int key){
this.key = key;
}
public void setKey(int key){
this.key = key;
}
public int getKey(){
return key;
}
}
public class Heap {
private HeapNode[] heapArray;
private int maxSize;
private int currentSize;

public Heap(int maxSize){
this.maxSize = maxSize;
heapArray = new HeapNode[maxSize];
currentSize = 0;
}
public boolean insertNodeUnsort(int index, HeapNode node){ if(maxSize == currentSize){ return false; } heapArray[index] = node; return true; }
public void trickleDown(int index){
        int leftChild ;
        int rightChild ;
        while(index < currentSize && index >= 0){
            leftChild = 2*index + 1;
            rightChild = 2*index + 2;
            if(leftChild >= currentSize){//如果左孩子不存在
                return;
            }else if(rightChild >= currentSize){//如果左孩子存在,右孩子不存在
                if(heapArray[leftChild].getKey() > heapArray[index].getKey()){
                    swapNode(heapArray,index,leftChild);
                    index = leftChild;
                }else
                    return;
            }
            else{//如果左右孩子都存在
                if(heapArray[leftChild].getKey() > heapArray[rightChild].getKey()){//若左孩子大
                    if(heapArray[leftChild].getKey() > heapArray[index].getKey()){//若左孩子比当前值大
                        swapNode(heapArray,index,leftChild);
                        index = leftChild;
                    }
                    else
                        return;
                }else{
                    if(heapArray[rightChild].getKey() > heapArray[index].getKey()){
                        swapNode(heapArray,index,rightChild);
                        index = rightChild;
                    }
                    else
                        return;
                }
            }//end of if-else
        }//while
    }//end of method
    public void swapNode(HeapNode[] array, int index1, int index2){
        HeapNode temp = array[index1];
        array[index1] = array[index2];
        array[index2] = temp;
    }
    public HeapNode deleteRootNode(){
        if(currentSize == 0){
            return null;
        }
        HeapNode root = heapArray[0];//需要时可将其返回
        heapArray[0] = heapArray[--currentSize];
        trickleDown(0);//删除根结点后,将最后一个结点放到堆顶,对其向下进行调整;
        return root;
    }
class HeapApp{
    public static void main(String args[]){
        Heap heap = new Heap(5);
        for(int i = 0; i < heap.getMaxSize(); i++){
            heap.insertNodeUnsort(i,new HeapNode( (int)(java.lang.Math.random()*100) )  );//这里插入结点,当前结点数并不自增,所以要手动增加
            heap.setCurrentSize(i+1);
        }
        heap.displayHeap();
        for(int j = (heap.getCurrentSize()-1-1)/2; j >=0 ;j--){//调整成堆
            heap.trickleDown(j);
        }
        heap.displayHeap();
        for(int k = heap.getCurrentSize()-1; k > 0; k--){
            HeapNode temp = heap.deleteRootNode();//删除结点后,结点数自减
            heap.insertNodeUnsort(k, temp);//当前结点数的下标的位置是之前最后一个结点的位置
            
        }
        heap.displayHeap();
//        heap.insertNode(1);
//        heap.insertNode(2);
//        heap.insertNode(3);
//        heap.insertNode(9);
//        
//        heap.deleteRootNode();        
//        heap.displayHeap();
//        
//        heap.changeNodeKey(2, 8);
//        heap.displayHeap();
        
    }
}



运行结果:

31 44 52 52 75 81 82 85 93
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐