堆排序

来源:互联网 发布:淘宝怎么买私人物品 编辑:程序博客网 时间:2024/05/17 21:50
package arithmetic;import java.io.PrintStream;import java.math.*;import java.util.Arrays;/* * 小顶堆的自适应程序 * */public class Heap {/* * data@ 待排序的数组 *  s@ 除 data[s] 均满足堆的特性 *  n数组的长度 * */public static void adjust(int data[],int s,int n){int parent = s;//顶堆的结点int j = 2*parent;//其子结点while(j<n){if(j+1<n&&data[j]>data[j+1])//取出两个子结点中的一个最小的j++;if(data[parent]>data[j])//把子结点中最小的那个与其父亲结点的值比较,如果小,与父亲结点交换{int temp = data[parent];data[parent] = data[j];data[j] = temp;parent = j ;//父亲结点为当前的结点j = 2*j;//当前结点下移}else{break;}}}/* * 这个利用完全二叉树的一个很重要的性质:最后一个非叶子结点为 第 n/2个 * 1.从最后一个非叶子结点开始,把其代表的堆都自适应成一个极小堆0 * 2.然后从整个堆的最后一个元素开始,与堆顶交换,然后再自适应成一个堆 * */public static void sort(int data[],int n){for(int i=n/2;i>0;i--){adjust(data,i,n);}for(int i=n-1;i>0;i--)//从堆的最后一个元素开始{int temp = data[1];data[1] = data[i];data[i] = temp;//交换数据后自适应成堆 adjust(data,1,i);}}public static void main(String args[]) throws Exception{int data[] = {0,35,18,20,65,40,46,58,25};// 0 为填充数 data[0] 无用,使节点下标从1开始int test[] = new int[1000];for(int i=999;i>0;i--){test[i] = i;}System.setOut(new PrintStream("F:\\test.txt"));sort(test,1000);for(int i=1;i<1000;i++)System.out.println(test[i]);}}/* *  * 堆排序 * 小顶堆:堆顶点的值比两个叶子节点的值都要小,把子节点还可以看作一个堆,也满足以上面条件  * 堆排序思路: * 1.先将待排序的数据存入在数组中 * 2.将数据利用筛选法创建成一个小顶堆 * 3.取出当前小顶堆的堆头与叶子结点的最后一个交换,后又形成一个不符条件的堆 * 4.然后再利用筛选法将不符全条件的堆适应成一个符和条件的堆 *  *  * 筛选法: * 从当前堆顶元素不满足堆的条件,其余都满足的堆顶点开始 * 拿其与其两个叶子结点中比较小的相比较,如果堆顶元素比它们的结果大, * 那么就要拿堆顶元素与叶子结点中比较小的那个交换,从而使自己又达到一个堆 * 而对于其子叶结点也是使用相同的方法 * 有一个问题:为什么在构建堆的过程中,要从下到上构造,也就是为什先选择最后一个非叶子结点[n/2]?而不是从第一结点开始 * 答:在排序的时候,我们是在一个极小顶堆的基础上拿去了一个堆顶的元素,而下面的堆都是符合堆的条件的,只有第一个不符合, * 而当我们构建堆的时候,也是用的这种方法,我们找到一个只有顶堆不符合堆的条件后,然后再进行适应,而 * 在一个错乱的数据里怎么才能找到一个只有顶堆不符合条件的结点,这个很难办,那我们就认为所有的叶子结点 * 都符合极小堆的条件,而对于第一个非叶子结点,我们就不能保证,我们我们就从最后一个非叶子结点开始构建 * */ 


 

原创粉丝点击