排序算法

一、冒泡排序-稳定:

思路:从第一个元素开始,比较每对相邻元素,如果第一个比第二个大,则交换位置。
一轮相邻元素两两相比后,在最后一个位置的就是最大值。
再接着第二轮相邻元素两两相比,在倒数第二个位置就是第二最大值。
这样经过n轮之后就排序好了。

/**
     * 冒泡排序-稳定:
     *
     * 从第一个元素开始,比较每对相邻元素,如果第一个比第二个大,则交换位置。
     * 一轮相邻元素两两相比后,在最后一个位置的就是最大值。
     * 再接着第二轮相邻元素两两相比,在倒数第二个位置就是第二最大值。
     * 这样经过n轮之后就排序好了
     *
     * @param array
     */
    public static void bubbleSort(int[] array){
        if(array!=null && array.length>0){
            int n = array.length;
            for(int i=0;i<n;i++){
                for(int j=0;j<n-1-i;j++){
                    if(array[j]>array[j+1]){
                        int t = array[j];
                        array[j] = array[j+1];
                        array[j+1] = t;
                    }
                }
            }
        }
    }

二、选择排序-不稳定:
思路:从第一个元素开始,将第一个元素和后面的元素依次比较,如果第一个元素大于当前元素,则交换位置。
一轮比较之后,第一个位置就会是最小值。
接着从第二个元素开始,将第二个元素和后面的元素依次比较,如果第二个元素大于当前元素,则交换位置。
这一轮比较之后,第二个位置就会是第二最小值。
这样经过n-1轮比较之后就排序好了

/**
     * 选择排序-不稳定:
     *
     * 从第一个元素开始,将第一个元素和后面的元素依次比较,如果第一个元素大于当前元素,则交换位置。
     * 一轮比较之后,第一个位置就会是最小值。
     * 接着从第二个元素开始,将第二个元素和后面的元素依次比较,如果第二个元素大于当前元素,则交换位置。
     * 这一轮比较之后,第二个位置就会是第二最小值。
     * 这样经过n-1轮比较之后就排序好了
     *
     * @param array
     */
    public static void selectionSort(int[] array){

        if(array!=null &&array.length>0){
            int n = array.length;
            for(int i=0;i<n-1;i++){
                int minIndex = i;
                for(int j=i+1;j<n;j++){
                    if(array[minIndex]>array[j]){
                        minIndex = j;
                    }
                }
                if(minIndex!=i){
                    int t = array[i];
                    array[i] = array[minIndex];
                    array[minIndex] = t;
                }
            }
        }
    }

三、插入排序-稳定:在已经排好序的元素里面从后往前比较,插入对应的位置。
思路:第一个元素(这个元素已排好序,因为这是第一个元素)
从第二个元素开始,在已经排好序的元素里面 从后往前依次比较,如果第二个元素小于当前元素,则插入当前元素前面。
从第三个元素开始,在已经排好序的元素里面 从后往前依次比较,如果第三个元素小于当前元素,则插入当前元素前面。
这样重复之后就排序好了

/**
     * 插入排序-稳定:在已经排好序的元素里面从后往前比较,插入对应的位置。
     *
     * 第一个元素(这个元素已排好序,因为这是第一个元素)
     * 从第二个元素开始,在已经排好序的元素里面 从后往前依次比较,如果第二个元素小于当前元素,则插入当前元素前面。
     * 从第三个元素开始,在已经排好序的元素里面 从后往前依次比较,如果第三个元素小于当前元素,则插入当前元素前面。
     * 这样重复之后就排序好了
     *
     * @param array
     */
    public static void insertionSort(int[] array){

        if(array!=null && array.length>0){
            int n = array.length;
            for(int i=1;i<n;i++){
                int temp  = array[i];
                for(int j=i-1;j>=0;j--){
                    if(temp<array[j]){
                        array[j+1] = array[j];
                        array[j] = temp;
                    }
                }
            }
        }
    }

四、希尔排序-不稳定
思路:确定一个增量序列 [t1,t2,…,tk],tk=1
根据增量序列的个数k,做k趟 插入排序
每趟排序,根据对应的增量ti(元素间隔)分成一组,这一组里面的元素做直接插入排序。
当增两ti=1的时候,元素间隔是1,其实就是直接插入排序

/**
     * 希尔排序-不稳定:
     *
     * 确定一个增量序列 [t1,t2,…,tk],tk=1
     * 根据增量序列的个数k,做k趟 插入排序
     * 每趟排序,根据对应的增量ti(元素间隔)分成一组,这一组里面的元素做直接插入排序。
     * 当增两ti=1的时候,元素间隔是1,其实就是直接插入排序,
     *
     * @param array
     */
    public static void shellSort(int[] array){

        if(array!=null && array.length>0){
            int n = array.length;
            int gap = 1;
            int gapLen = 1;
            while( gap<n/3 ){
                gap = 3*gap+1;
                gapLen++;
            }
            //确定增量序列
            int[] gapArray = new int[gapLen];
            for(int i=0;i<gapLen;i++){
                gapArray[i] = gap;
                gap/=3;
            }
            System.out.print("增量序列:");
            print(gapArray);

            for(int i=0;i<gapLen;i++){
                //做每组的直接插入排序
                for(int j=gapArray[i];j<n;j+=gapArray[i]){

                    int temp = array[j];
                    for(int k=j-gapArray[i];k>=0;k-=gapArray[i]){
                        if(temp<array[k]){
                            array[ k+gapArray[i] ] = array[k];
                            array[k] = temp;
                        }
                    }

                }
            }
        }
    }

五、归并排序-稳定:(分治思想,二分)
思路:将元素分成2组,这2组又分别可以再分2组,直到组合两组组里面只剩一个元素,再将两组两个元素合并成有序。

/**
     * 归并排序-稳定:(分治思想,二分)
     * 将元素分成2组,这2组又分别可以再分2组,直到组合两组组里面只剩一个元素,再将两组两个元素合并成有序
     *
     * @param array
     */
    public static int[] mergeSort(int[] array){

        if(array.length<2){
            return array;
        }
        int n = array.length;
        int mid = n/2;
        int[] left = Arrays.copyOfRange(array,0,mid);
        int[] right = Arrays.copyOfRange(array,mid,n);
        return merge(mergeSort(left),mergeSort(right));
    }
    public static int[] merge(int[] left,int[] right){

        int leftLen = left.length;
        int rightLen = right.length;
        int[] merge = new int[leftLen+rightLen];
        int i=0,j=0,k=0;
        while(i<leftLen && j<rightLen ){
            if(left[i]<right[j]){
                merge[k++] = left[i++];
            }else{
                merge[k++] = right[j++];
            }
        }
        while(i<leftLen){
            merge[k++]=left[i++];
        }
        while(j<rightLen){
            merge[k++]=right[j++];
        }
        return merge;
    }

六、快排-不稳定
思路:首先找到一个基准,然后将所有小于基准的元素放到基准左边,所有大的放到基准右边
这个时候,基准左边的元素都比基准小,右边的都比基准大
接着又分别将基准左边的元素、右边的元素 重复上面操作

/**
     * 快排-不稳定
     * 首先找到一个基准,然后将所有小于基准的元素放到基准左边,所有大的放到基准右边
     * 这个时候,基准左边的元素都比基准小,右边的都比基准大
     * 接着又分别将基准左边的元素、右边的元素 重复上面操作
     *
     * @param array
     */
    public static void quickSort(int[] array,int left,int right){

        if(left>=right){
            return ;
        }

        int temp = array[left];
        int n = right;
        while(left<right){
            while( left<right && array[right]>=temp ){
                right--;
            }
            if(left<right){
                array[left++] = array[right];
            }
            while( left<right && array[left]<=temp ){
                left++;
            }
            if(left<right){
                array[right--]=array[left];
            }
        }
        array[left] = temp;

        quickSort(array,0,left-1);
        quickSort(array,left+1,n);
    }

七、堆排序-不稳定:构造小顶堆,调整小顶堆的过程
思路:小顶堆:每个父节点的值都比左右孩子值都小的完全二叉树,根值是最小的
父节点和左右孩子的位置关系:
父节点的位置:i (从0开始)
左孩子的位置:2*i+1
有孩子的位置:2*i+2

/**
     * 堆排序-不稳定:构造小顶堆,调整小顶堆的过程
     * 小顶堆:每个父节点的值都比左右孩子值都小的完全二叉树,根值是最小的
     * 父节点和左右孩子的位置关系:
     * 父节点的位置:i (从0开始)
     * 左孩子的位置:2*i+1
     * 有孩子的位置:2*i+2
     *
     * @param array
     */
    public static void heapSort(int[] array){
        int n = array.length;
        //建立初堆
        for(int i=n/2-1;i>=0;i--){
            heapAdjust(array,i,n);
        }
        //调整堆
        for(int i=n-1;i>0;i--){
            int t  = array[0];
            array[0] = array[i];
            array[i] = t;
            heapAdjust(array,0,i);
        }
    }
    public static void heapAdjust(int[] array,int i,int n){
        for(int j=i;j<n;j++){
            int left = 2*j+1;
            int right = 2*j+2;
            if(left<n){
                if(array[j]>array[left]){
                    int t = array[j];
                    array[j]=array[left];
                    array[left]=t;
                }
            }
            if(right<n){
                if(array[j]>array[right]){
                    int t = array[j];
                    array[j] = array[right];
                    array[right] = t;
                }
            }
        }
    }

 

所有:

/**排序算法
 * @author chen jia hao
 */
public class SortTest {
    public static void main(String[] args){

        Scanner scanner  = new Scanner(System.in);
        while(scanner.hasNext()){
            int n = scanner.nextInt();
            scanner.nextLine();
            int[] array = new int[n];
            for(int i=0;i<n;i++){
                array[i] = scanner.nextInt();
            }

            //bubbleSort(array);
           // selectionSort(array);
          //  insertionSort(array);
           // shellSort(array);
            //array = mergeSort(array);
           //quickSort(array,0,n-1);
            heapSort(array);
            print(array);
        }
    }

    /**
     * 冒泡排序-稳定:
     *
     * 从第一个元素开始,比较每对相邻元素,如果第一个比第二个大,则交换位置。
     * 一轮相邻元素两两相比后,在最后一个位置的就是最大值。
     * 再接着第二轮相邻元素两两相比,在倒数第二个位置就是第二最大值。
     * 这样经过n轮之后就排序好了
     *
     * @param array
     */
    public static void bubbleSort(int[] array){
        if(array!=null && array.length>0){
            int n = array.length;
            for(int i=0;i<n;i++){
                for(int j=0;j<n-1-i;j++){
                    if(array[j]>array[j+1]){
                        int t = array[j];
                        array[j] = array[j+1];
                        array[j+1] = t;
                    }
                }
            }
        }
    }

    /**
     * 选择排序-不稳定:
     *
     * 从第一个元素开始,将第一个元素和后面的元素依次比较,如果第一个元素大于当前元素,则交换位置。
     * 一轮比较之后,第一个位置就会是最小值。
     * 接着从第二个元素开始,将第二个元素和后面的元素依次比较,如果第二个元素大于当前元素,则交换位置。
     * 这一轮比较之后,第二个位置就会是第二最小值。
     * 这样经过n-1轮比较之后就排序好了
     *
     * @param array
     */
    public static void selectionSort(int[] array){

        if(array!=null &&array.length>0){
            int n = array.length;
            for(int i=0;i<n-1;i++){
                int minIndex = i;
                for(int j=i+1;j<n;j++){
                    if(array[minIndex]>array[j]){
                        minIndex = j;
                    }
                }
                if(minIndex!=i){
                    int t = array[i];
                    array[i] = array[minIndex];
                    array[minIndex] = t;
                }
            }
        }
    }

    /**
     * 插入排序-稳定:在已经排好序的元素里面从后往前比较,插入对应的位置。
     *
     * 第一个元素(这个元素已排好序,因为这是第一个元素)
     * 从第二个元素开始,在已经排好序的元素里面 从后往前依次比较,如果第二个元素小于当前元素,则插入当前元素前面。
     * 从第三个元素开始,在已经排好序的元素里面 从后往前依次比较,如果第三个元素小于当前元素,则插入当前元素前面。
     * 这样重复之后就排序好了
     *
     * @param array
     */
    public static void insertionSort(int[] array){

        if(array!=null && array.length>0){
            int n = array.length;
            for(int i=1;i<n;i++){
                int temp  = array[i];
                for(int j=i-1;j>=0;j--){
                    if(temp<array[j]){
                        array[j+1] = array[j];
                        array[j] = temp;
                    }
                }
            }
        }
    }

    /**
     * 希尔排序-不稳定:
     *
     * 确定一个增量序列 [t1,t2,…,tk],tk=1
     * 根据增量序列的个数k,做k趟 插入排序
     * 每趟排序,根据对应的增量ti(元素间隔)分成一组,这一组里面的元素做直接插入排序。
     * 当增两ti=1的时候,元素间隔是1,其实就是直接插入排序,
     *
     * @param array
     */
    public static void shellSort(int[] array){

        if(array!=null && array.length>0){
            int n = array.length;
            int gap = 1;
            int gapLen = 1;
            while( gap<n/3 ){
                gap = 3*gap+1;
                gapLen++;
            }
            //确定增量序列
            int[] gapArray = new int[gapLen];
            for(int i=0;i<gapLen;i++){
                gapArray[i] = gap;
                gap/=3;
            }
            System.out.print("增量序列:");
            print(gapArray);

            for(int i=0;i<gapLen;i++){
                //做每组的直接插入排序
                for(int j=gapArray[i];j<n;j+=gapArray[i]){

                    int temp = array[j];
                    for(int k=j-gapArray[i];k>=0;k-=gapArray[i]){
                        if(temp<array[k]){
                            array[ k+gapArray[i] ] = array[k];
                            array[k] = temp;
                        }
                    }

                }
            }

        }

    }

    /**
     * 归并排序-稳定:(分治思想,二分)
     * 将元素分成2组,这2组又分别可以再分2组,直到组合两组组里面只剩一个元素,再将两组两个元素合并成有序
     *
     * @param array
     */
    public static int[] mergeSort(int[] array){

        if(array.length<2){
            return array;
        }
        int n = array.length;
        int mid = n/2;
        int[] left = Arrays.copyOfRange(array,0,mid);
        int[] right = Arrays.copyOfRange(array,mid,n);
        return merge(mergeSort(left),mergeSort(right));
    }
    public static int[] merge(int[] left,int[] right){

        int leftLen = left.length;
        int rightLen = right.length;
        int[] merge = new int[leftLen+rightLen];
        int i=0,j=0,k=0;
        while(i<leftLen && j<rightLen ){
            if(left[i]<right[j]){
                merge[k++] = left[i++];
            }else{
                merge[k++] = right[j++];
            }
        }
        while(i<leftLen){
            merge[k++]=left[i++];
        }
        while(j<rightLen){
            merge[k++]=right[j++];
        }
        return merge;
    }


    /**
     * 快排-不稳定
     * 首先找到一个基准,然后将所有小于基准的元素放到基准左边,所有大的放到基准右边
     * 这个时候,基准左边的元素都比基准小,右边的都比基准大
     * 接着又分别将基准左边的元素、右边的元素 重复上面操作
     *
     * @param array
     */
    public static void quickSort(int[] array,int left,int right){

        if(left>=right){
            return ;
        }

        int temp = array[left];
        int n = right;
        while(left<right){
            while( left<right && array[right]>=temp ){
                right--;
            }
            if(left<right){
                array[left++] = array[right];
            }
            while( left<right && array[left]<=temp ){
                left++;
            }
            if(left<right){
                array[right--]=array[left];
            }
        }
        array[left] = temp;

        quickSort(array,0,left-1);
        quickSort(array,left+1,n);
    }

    /**
     * 堆排序-不稳定:构造小顶堆,调整小顶堆的过程
     * 小顶堆:每个父节点的值都比左右孩子值都小的完全二叉树,根值是最小的
     * 父节点和左右孩子的位置关系:
     * 父节点的位置:i (从0开始)
     * 左孩子的位置:2*i+1
     * 有孩子的位置:2*i+2
     *
     * @param array
     */
    public static void heapSort(int[] array){
        int n = array.length;
        //建立初堆
        for(int i=n/2-1;i>=0;i--){
            heapAdjust(array,i,n);
        }
        //调整堆
        for(int i=n-1;i>0;i--){
            int t  = array[0];
            array[0] = array[i];
            array[i] = t;
            heapAdjust(array,0,i);
        }
    }
    public static void heapAdjust(int[] array,int i,int n){
        for(int j=i;j<n;j++){
            int left = 2*j+1;
            int right = 2*j+2;
            if(left<n){
                if(array[j]>array[left]){
                    int t = array[j];
                    array[j]=array[left];
                    array[left]=t;
                }
            }
            if(right<n){
                if(array[j]>array[right]){
                    int t = array[j];
                    array[j] = array[right];
                    array[right] = t;
                }
            }
        }
    }


    public static  void print(int[] array){
        if(array!=null && array.length>0){
            for(int i=0,len=array.length-1;i<len;i++){
                System.out.print(array[i]+" ");
            }
            System.out.println(array[array.length-1]);
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值