Common sorting algorithm java implementation

Insertion sort

/**
 * 插入排序
 * 感觉下面的写法和冒泡排序类似
 * 时间复杂度:
 *      最坏:O(n2)
 *      最好:O(n)
 *      平均:O(n2)
 */
package others;
public class insertSort {
    //所谓插入排序,其实就是类似于我们玩纸牌的时候的排序方法,每抽一张牌,都在前面已经排好序的牌中找一个合适的位置插入
    public static int[] sort(int[] array){
        //先判断数组是否符合规定,也就是长度
        if (array.length == 0 || array.length < 2){
            return array;
        }else {
            //采用两次for循环
            //i指向当前元素的位置,由于0前面没有任何元素,因此我们从下标为1的地方开始
            for (int i = 1; i < array.length; i++){
                //此处for循环用来查找元素i要插入的位置
                //用temp来临时保存当前的元素值
                int temp = array[i];
                int j =i-1;
                //此处j>=0应当放在array[j]>temp的前面
                //&&具有截断性,所以就不会导致j=-1时的array会报的错误了
                while(j>=0&&array[j]>temp){
                    array[j+1]=array[j];
                    j--;
                }
                array[j+1]=temp;
            }
        }
        return array;
    }
    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        array = insertSort.sort(array);
        for (int num : array){
            System.out.println(num);
        }

    }
}

Merge sort

/***
 *
 *  归并排序
 *  已完成
 **/
package others;

public class mergeSort {
    //给定一个数组和对应区域的起始和终止位置
    public static void merge(int[] array,int start,int end){
        //首先先判断起始地址是否小于终止地址,是的话执行,否则跳过,用来处理
        if (start < end){
            //获取要处理区间的中心mid
            int mid = (start + end) / 2 ;
            //递归调用merge处理index左边
            merge(array,start,mid) ;
            //递归调用merge处理index右边
            merge(array,mid + 1,end) ;
            //最后调用sort方法对此区间进行排序
            sort(array,start,mid,end) ;
        }
    }
    //其实这里才是归并排序的重点,
    public static void sort(int[] nums, int low, int mid, int high) {
        //创建一个和给定区间想用长度的新的int空间
        int[] temp = new int[high - low + 1];
        int i = low;// 左指针
        int j = mid + 1;// 右指针
        int k = 0;

        // 把较小的数先移到新数组中
        //此处是将两个有序的数组合并到一个新的数组中
        //将两个数组i和j位置处的元素进行比较,将较小的数放入到新数组中,对应的i或者j+1,直到有一方数组遍历完
        while (i <= mid && j <= high) {
            if (nums[i] < nums[j]) {
                temp[k++] = nums[i++];
            } else {
                temp[k++] = nums[j++];
            }
        }
        //由于我们不知道哪个数组是遍历完的那一个,所以我们对两个数组执行同样的操作
        //也就是把各自数组剩余的所有元素一次性放到新数组的后方
        //由于有一方数组是已经全部遍历的,因此下面两个while循环只有一个会执行
        // 把左边剩余的数移入数组
        while (i <= mid) {
            temp[k++] = nums[i++];
        }

        // 把右边边剩余的数移入数组
        while (j <= high) {
            temp[k++] = nums[j++];
        }

        // 最后把新数组中的数覆盖nums数组
        for (int k2 = 0; k2 < temp.length; k2++) {
            nums[k2 + low] = temp[k2];
        }
    }
    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        int end = array.length - 1;
        mergeSort.merge(array,0,end);
        for (int num : array){
            System.out.println(num);
        }
    }
}

Quick sort

package others;
//快排
public class quickSort {
    //快排
    /**
     *  快排的思想是,选择一个元素,通常是对应区间的第一个元素,
     *  将所有比他小的元素放到他的左边
     *  将所有比他大的元素放到他的右边去
     * */
    public static int[] sort(int[] array,int start,int end){
        //首先先判断数组是否符合规定
        if(array.length < 2 || array.length == 0 || start >= end){
            return array;
        }
        int min = start;
        int max = end;
        if (min == max){
            return array;
        }
        //保存临时值,这里的tempNum其实就是我们用来区分大数和小数的分界值,通常取第一个
        int tempNum = array[min];
        //当没有结束时
        while (min != max){
            //先找到区间右侧第一个比tempNum小的元素的位置
            while (min < max && array[max] > tempNum){
                max--;
            }if (min<max){
                quickSort.swap(array,min,max);
                //然后交换两个的位置,这样一来max右侧都是比tempNum大的数,同时也把这个比他小的值扔到了最前面去
                ++min;
            }
            //从区间左侧找到第一个比tempNum大的元素的位置,然后交换两个的位置,这样min左侧的数都比tempNum小,同时也把这个大数扔到了后面去
            while (min < max && array[min] <= tempNum){
                min++;
            }
            if (min < max) {
                quickSort.swap(array,min,max);
                --max;
            }
            //不断循环
        }
        if (min == max){
            array[max] = tempNum;
        }
        //递归调用sort对元素左侧的区域来一次,对元素右边的区域也来一次排序
        array = sort(array,start,min-1);
        array = sort(array,max + 1,end);
        return array;
    }
    //这个函数是用于交换两个元素的位置的
    public static void swap(int []array,int i, int j){
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        array = quickSort.sort(array,0,array.length-1);
        for (int num : array){
            System.out.println(num);
        }
    }
}

Select sort

//选择排序
package others;
//  每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。
public class selectSort {
    public static int[] srot(int[] array){
        int p = 0;
        int temp = 0;
        if (array.length < 2 || array.length == 0){
            return array;
        }
        for (int i = 0;i < array.length; i++){
            temp = i;
            for(int j = i; j < array.length; j++ ){
                if (array[j] < array[temp]){
                    temp = j;
                }
            }
            if (temp != i){
                p = array[i];
                array[i] = array[temp];
                array[temp] = p;
            }
        }
        return array;
    }

    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        array = selectSort.srot(array);
        for (int num : array){
            System.out.println(num);
        }
    }
}

Hill sort

/**
 * 希尔排序的时间复杂度是不确定的
 * 依赖于增量序列
 * 时间复杂度在O(n1.3~n2)
 */
package others;
/**
 * 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。
 * 所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插入排序;
 * 然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<;…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
 * 该方法实质上是一种分组插入方法。
 * */
public class shellSort {
    public static int [] sort(int[] array){
        int temp = 0;
        int t = 0;
        if (array.length == 0 || array.length < 2){
            return array;
        }
        temp = array.length;
        while(true){
            temp = temp / 2;
            for (int i = 0;i < temp ;i++){
                for (int index = i ;index < array.length ;index = index + temp){
                    for (int j = index; j < array.length; j = j + temp){
                        if((j + temp) < array.length) {
                            if (array[j] > array[j + temp]) {
                                t = array[j];
                                array[j] = array[j + temp];
                                array[j + temp] = t;
                            }
                        }
                    }
                }
            }
            if (temp == 1)
                break;
        }
        return array;
    }
    public static void main(String[] args){
        int array[] = {10,11,4,2,23,46,33,1};
        array = shellSort.sort(array);
        for (int num : array){
            System.out.println(num);
        }

    }
}

Heap sort

import java.util.Arrays;

public class HeapSort {

    //堆排序
    public static void heapSort(int[] array) {
        array = buildMaxHeap(array); //初始建堆,array[0]为第一趟值最大的元素
        for (int i = array.length - 1; i >= 1; i--) {
            int temp = array[0];  //将堆顶元素和堆底元素交换,即得到当前最大元素正确的排序位置
            array[0] = array[i];
            array[i] = temp;
            adjustHeap(array, 0, i);  //整理,将剩余的元素整理成大顶堆
        }
    }

    //自下而上构建大顶堆:将array看成完全二叉树的顺序存储结构
    private static int[] buildMaxHeap(int[] array) {
        //从最后一个节点array.length-1的父节点(array.length-1-1)/2开始,直到根节点0,反复调整堆
        for(int i=(array.length-2)/2;i>=0;i--){
            adjustHeap(array, i, array.length);
        }
        return array;

    }

    private static void adjustHeap(int[] array, int k, int length) {
        int k1=2*k+1;
        if(k1<length-1 && array[k1]<array[k1+1]){
            k1++;
        }
        if(k1>length-1||array[k]>=array[k1]){
            return;
        }else{
            int temp = array[k];  //将堆顶元素和左右子结点中较大节点交换
            array[k] = array[k1];
            array[k1] = temp;
            adjustHeap(array,k1,length);
        }
    }



    public static void main(String[] args) {
        int[] a = {87,45,78,32,17,65,53,9,122,133};
        heapSort(a);
        System.out.println(Arrays.toString(a));
    }
}

 

Guess you like

Origin blog.csdn.net/qq_20176001/article/details/91358496