希尔排序&归并排序&快速排序

public abstract class IArraySort {
    //排序
    public abstract int[] sort(int[] sourceArray);

    public void swap(int arr[],int i,int j){
        int temp = arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

    public void printArr(int arr[]){
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }
}

希尔排序

/**
 * 选择一个增量序列 t1,t2,..tk ,  其中ti>tj,且tk=1
 * 按增量序列个数k,对序列进行k趟排序
 * 每趟排序,根据对应的增量ti,将待排序序列分割成若干个长度为ti的子序列,分别对各子序列进行直接插入排序
 *      ,当增量因子为1时,整个序列作为一个表来处理,表长度即为整个序列长度
 *
 * 增量序列 初始化,  gap = len/2 ;  gap = gap/2
 */
public class ShellSort extends IArraySort {
    public static void main(String[] args) {
        int[] sourceArray = {20,40,32,67,33,1,40,20,89,300,400,15,15,2,1,20,89,400};
        ShellSort shellSort = new ShellSort();
        int result[] = shellSort.sort(sourceArray);
        shellSort.printArr(result);
    }
    public int[] sort(int[] sourceArray) {
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
        int gap = arr.length/2;
        int j,newNumber;
        while(gap>0){
            //对子序列进行插入排序
            for (int i=gap;i<arr.length;i++){
                j = i;
                newNumber=arr[j];
                while(j>=gap&&newNumber<arr[j-gap]){
                    arr[j] = arr[j-gap];
                    j = j-gap;  //注意这里不是j--。而是隔gap
                }
                if (j!=i)
                    arr[j] = newNumber;
            }
            gap=gap/2;      //缩小增量序列
        }
        return arr;
    }
}

归并排序--递归实现

//归并排序---递归实现
//  1--3   2--4  ==》  1--2--3--4

/**
 * 1. 申请临时空间,大小为待排序数组的大小,该空间用来存放合并后的序列
 * 2. 分: 将数组一分为2     (1,2,3,4)   middle=(0+3)/2=1
 * 3. 递归的进行【分】操作,直到序列的长度为1
 * 4. 合: 将序列1和序列2合并到临时数组中,并将临时数组的数据导回原数组Arr
 */
public class MergeSortDemo extends IArraySort{
    public static void main(String[] args) {
        int[] sourceArray = {20,40,32,67,33,1,40,20,89,300,400,15,15,2,1,20,89,400};
        MergeSortDemo mergeSort = new MergeSortDemo();
        int[] result = mergeSort.sort(sourceArray);
        mergeSort.printArr(result);
    }

    public int[] sort(int[] sourceArray) {
        int tempArr[] = new int[sourceArray.length];
        return MergeSort(sourceArray,tempArr,0,sourceArray.length-1);
    }

    /**
     * 归并排序
     * @param arr       待排序数组
     * @param tempArr   临时数组
     * @param low       待排序数组起始位置
     * @param high      待排序数组结束位置
     * @return
     */
    private int[] MergeSort(int arr[],int tempArr[],int low,int high){
        //递归出口:当子序列只有一个元素时
        if (low<high){
            //1. 分: 将数组一分为2     (1,2,3,4)   middle=(0+3)/2=1
            int middle = (low+high)/2;
            MergeSort(arr,tempArr,low,middle);
            MergeSort(arr,tempArr,middle+1,high);
            //2. 合: 在临时数组中将子序列进行归并,并将结果导入arr
            Merge(arr,tempArr,low,middle,high);
        }
        return arr;
    }

    /**
     * 合并子序列    1--3   2--4  ==》  1--2--3--4
     * @param arr        待排序数组
     * @param tempArr    临时数组
     * @param low        第一个子序列起始下标
     * @param middle     第一个子序列结束下标
     * @param high       第二个子序列结束下标
     */
    private void Merge(int[] arr, int[] tempArr, int low, int middle, int high) {
        int i=low;          //标志第一个子序列当前元素
        int j=middle+1;     //标志第二个子序列当前元素
        int index=low;

        while (i<=middle&&j<=high){
            if (arr[i]<=arr[j])
                tempArr[index++] = arr[i++];
            else
                tempArr[index++] = arr[j++];
        }
        //跳出循环2种可能,  两个子序列合并完了; 一个子序列合并完了;
        while (i<=middle)     //子序列1没完,把剩余元素全加进来
            tempArr[index++]=arr[i++];

        while (j<=high)
            tempArr[index++]=arr[j++];

        //比较关键:将排好序后的临时数组中的元素重新导入到arr
        for (int k=low;k<=high;k++)
            arr[k]=tempArr[k];
    }
}

归并排序--非递归实现

//归并排序  --非递归实现

//1. 申请临时空间tempArr,  第一次合并后将数组从arr导入tempArr,   第二次合并将数组从tempArr导入arr
//1. 取2,4,8...个元素为一组,进行合并
public class MergeSortDemo2 extends IArraySort{
    public static void main(String[] args) {
        int[] sourceArray = {20,40,32,67,33,1,40,20,89,300,400,15,15,2,1,20,89,400};
        MergeSortDemo2 mergeSort = new MergeSortDemo2();
        int[] result = mergeSort.sort(sourceArray);
        mergeSort.printArr(result);
    }

    public int[] sort(int[] sourceArray) {
        int tempArr[] = new int[sourceArray.length];
        return MergeSort(sourceArray,tempArr);
    }

    /**
     * 归并排序
     * @param arr       待排序数组
     * @param tempArr   临时数组
     * @return
     */
    private int[] MergeSort(int arr[],int tempArr[]){
        int length=1;
        while (length<=arr.length){
            MergePass(arr,tempArr,length);        //将待排序数组归并到临时数组
            length = length * 2;
            MergePass(tempArr,arr,length);        //将临时数组归并到待排序数组
            length = length * 2;
        }
        return arr;
    }

    //将待排序数组src  归并  到target数组
    private void MergePass(int[] src, int[] target, int length) {
        int N = src.length;
        int i;
        for(i=0;i<=N-2*length;i+=length*2){
            //归并指定长度子序列         如长度为2=>下标:0 1 3
            Merge(src,target,i,i+length-1,i+2*length-1);
        }
        //剩余元素不够划分
        if (i+length<=N){
            //还剩2个子序列,其中第二个子序列不满
            Merge(src,target,i,i+length-1,N-1);
        }else {
            //还剩下1个子序列
            for (int j=i;j<N;j++)
                target[j]=src[j];
        }
    }


    /**
     * 合并子序列    1--3   2--4  ==》  1--2--3--4
     * @param arr        待排序数组
     * @param tempArr    临时数组
     * @param low        第一个子序列起始下标
     * @param middle     第一个子序列结束下标
     * @param high       第二个子序列结束下标
     */
    private void Merge(int[] arr, int[] tempArr, int low, int middle, int high) {
        int i=low;          //标志第一个子序列当前元素
        int j=middle+1;     //标志第二个子序列当前元素
        int index=low;

        while (i<=middle&&j<=high){
            if (arr[i]<=arr[j])
                tempArr[index++] = arr[i++];
            else
                tempArr[index++] = arr[j++];
        }
        //跳出循环2种可能,  两个子序列合并完了; 一个子序列合并完了;
        while (i<=middle)     //子序列1没完,把剩余元素全加进来
            tempArr[index++]=arr[i++];

        while (j<=high)
            tempArr[index++]=arr[j++];

        //比较关键:将排好序后的临时数组中的元素重新导入到arr
        /*for (int k=low;k<=high;k++)
            arr[k]=tempArr[k];*/
    }
}

快速排序

//快速排序

/**
 * 1. 选主元pivot
 * 2. 划分左右子集,  所有比pivot小的放在左边,比pivot大的元素放右边。 这个称为分区(partition)操作
 * 3. 递归地将左子集和右子集进行快速排序
 */
public class QuickSort extends IArraySort {
    public static void main(String[] args) {
        int[] sourceArray = {20,40,32,67,33,1,40,20,89,300,400,15,15,2,1,20,89,400};
        QuickSort quickSort = new QuickSort();
        int[] result = quickSort.sort(sourceArray);
        quickSort.printArr(result);
    }

    public int[] sort(int[] sourceArray) {
        return quickSort(sourceArray,0,sourceArray.length-1);
    }

    private int[] quickSort(int[] arr,int left,int right){
        if (left<right){
            int partitionIndex = partition(arr,left,right);     //分区,并返回pivot下标
            quickSort(arr,left,partitionIndex-1);          //递归对左子集进行快速排序
            quickSort(arr,partitionIndex+1,right);          //递归对右子集进行快速排序
        }
        return arr; //递归出口,子集只有一个元素
    }

    private int partition(int[] arr,int left,int right){
        //设置基准值pivot
        int pivot = left;
        int i=pivot+1;
        int j=right;
        while (i<j){
            while (i<j&&arr[i]<=arr[pivot]) i++;
            while (i<j&&arr[j]>arr[pivot]) j--;
            //冲突,交换i和j
            if (i<j){
               swap(arr,i,j);
               i++;j--;
            }
        }
        if (arr[i]>=arr[pivot]){
            swap(arr,pivot,i-1);
            return i-1;
        }else {
            swap(arr,pivot,i);
            return i;
        }
    }
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值