Java实现快速排序和堆排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_41144773/article/details/89439446
快速排序原理:
选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。一般选择序列的第一个元素。一次循环:从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有继续比较下一个,直到找到第一个比基准值小的值才交换。找到这个值之后,又从前往后开始比较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的值才交换。直到从前往后的比较索引>从后往前比较的索引,结束第一次循环,此时,对于基准值来说,左右两边就是有序的了。
public class FastSort{

    public static void main(String []args){
        int[] a = {12,20,5,16,15,1,30,45,23,9};
        int start = 0;
        int end = a.length-1;
        sort(a,start,end);
        for(int i = 0; i<a.length; i++){
            System.out.println(a[i]);
        }

    }

    public static void sort(int[] a,int low,int high){
        int start = low;
        int end = high;
        //第一个数字key为基准值
        int key = a[low];

        while(end>start){
            //从后往前end--,比较a[end]小于key,交换a[end]和key
            while(end>start&&a[end]>=key)  //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
                end--;
            if(a[end]<=key){
                int temp = a[end];
                a[end] = a[start];
                a[start] = temp;
            }
            //从前往后比较
            while(end>start&&a[start]<=key)//如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
                start++;
            if(a[start]>=key){
                int temp = a[start];
                a[start] = a[end];
                a[end] = temp;
            }
            //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
        }
        //递归
        if(start>low) sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
        if(end<high) sort(a,end+1,high);//右边序列。从关键值索引+1到最后一个
    }

}

堆排序的基本思想:将待排序序列构造成一个大顶堆,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了

public class heapSort {

    public static void main(String[] args)
    {
        int [] a={17,8,45,84,2,94};
        int len=a.length;
        /**
         * 循环建堆
         */
        for(int i=0;i<len-1;i++){
            /**
             * 建堆,建一次最大堆,寻到一个待排序序列的最大数
             */
            buildMaxHeap(a,len-1-i);
            /**
             * 交换堆顶(待排序序列最大数)和最后一个元素
             */
            swap(a,0,len-1-i);
        }

        for(int j=0;j<len;j++){
            System.out.print(a[j]+" ");
        }
    }


    /**
     * 对数组 从0到lastIndex建大顶堆
     */
    public static void buildMaxHeap(int[] arr, int lastIndex){
        /**
         * 从最后一个节点(lastIndex)的父节点开始
         */
        for(int i=(lastIndex-1)/2;i>=0;i--){
            /**
             * k保存正在判断的节点
             */
            int k=i;
            /**
             * 如果当前k节点的子节点存在
             */
            while(k*2+1<=lastIndex){
                /**
                 * k节点的左子节点的索引
                 */
                int biggerIndex=2*k+1;
                /**
                 * 如果k节点的左子节点biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
                 */
                if(biggerIndex<lastIndex){
                    /**
                     * 若果右子节点的值较大
                     */
                    if(arr[biggerIndex]<arr[biggerIndex+1]){
                        /**
                         * biggerIndex总是记录较大子节点的索引
                         */
                        biggerIndex++;
                    }
                }
                /**
                 * 如果k节点的值小于其较大的子节点的值 ,交换他们
                 */
                if(arr[k]<arr[biggerIndex]){
                    swap(arr,k,biggerIndex);
                    /**
                     * 将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
                     */
                    k=biggerIndex;
                }else{
                    /**
                     * 当前判断结点k(父结点),大于他的两个子节点时,跳出while循环
                     */
                    break;
                }
            }
        }
    }
    /**
     * 交换下标为i、j的两个元素
     */
    private static void swap(int[] data, int i, int j) {
        int tmp=data[i];
        data[i]=data[j];
        data[j]=tmp;
    }

至此结束。。

猜你喜欢

转载自blog.csdn.net/sinat_41144773/article/details/89439446