堆排序是简单选择排序的改进,相同点是都是选择最小或者是最大元素与最后面的元素进行交换,不同点是在元素比较的过程当中元素有交换,而这种交换跟冒泡排序的交换不一样,它都是有效的交换。
//堆排序 public class HeapSort { public void heapSort(int[] r) { int n=r.length; //循环建堆,建一次大顶堆,取得一个最大的数放到最后,剩余的重新建堆 for(int i=0;i<n-1;i++) { buildMaxHeap(r,n-1-i); swap(r,0,n-1-i);//将堆顶元素跟最后的数交换 } } public void swap(int[] r,int i,int j) { int stemp=r[i]; r[i]=r[j]; r[j]=stemp; } public void buildMaxHeap(int[] r,int lastindex) { //从最后一个父节点i开始调整堆使它成为大顶堆 for(int i=(lastindex-1)/2;i>=0;i--) { //将父节点标记为k int k=i; //2*k+1是父节点的左子节点,判断是不是又子节点,如果有找出子节点较大的节点 while(2*k+1<=lastindex) { //首先将左节点作为较大的节点 int biggerchilder=2*k+1; //如果存在右节点 if(biggerchilder<lastindex) { //比较两个节点的大小,将bigerchilder总是指向较大的节点 if(r[biggerchilder]<r[biggerchilder+1]) { biggerchilder++; } } //将较大的节点与父节点比较 if(r[biggerchilder]>r[k]) { //如果子节点大则与父节点交换 swap(r,k,biggerchilder); //交换之后,交换的位置大顶堆被破坏,进入while循环调整堆 k=biggerchilder; } else{ break; } } } } public static void main(String[] args) { HeapSort b=new HeapSort(); int[] a={4,8,3,6,9,7,5,2,1}; b.heapSort(a); for(int i=0;i<a.length;i++) System.out.println(a[i]); } }
建大顶堆的方法改进:
1 public void buildMaxHead(int[] r,int lastindex) 2 { 3 int length=r.length; 4 int i=0; 5 if(lastindex==length-1)//判断是不是第一次建堆,如果是第一次那么从最后一个父节点调整成大顶堆,如果是取得第一个最大值,进行后续的调整时那么从根节点开始调整 6 i=(lastindex-1)/2; 7 for(;i>=0;i--) 8 { 9 int k=i; 10 while(2*k+1<=lastindex) 11 { 12 int biggerchild=2*k+1; 13 if(biggerchild<lastindex) 14 { 15 if(r[biggerchild]<r[biggerchild+1]) 16 { 17 biggerchild++; 18 } 19 } 20 if(r[biggerchild]>r[k]) 21 { 22 swap(r,k,biggerchild); 23 k=biggerchild; 24 } 25 else break; 26 } 27 } 28 }