常用排序算法

import java.util.*;

public class Sort {
    public static void main(String[] args) {
        Sort s = new Sort();
        int[] array = new int[]{1, 6, 2, 7, 3, 9, 10};
//        int[] array=new int[]{6,3};
        s.countSort(array);
        for (int i : array)
            System.out.print(i + " ");
    }

    /**
     * 冒泡排序
     * 从头到尾,比较大小,大的向后放
     * 时间复杂度O(n^2)
     * 空间复杂度O(1)
     */
    public void bubbleSort(int[] array) {
        int temp;
        for (int i = 1; i < array.length; i++) {
            for (int j = 0; j < array.length - i; j++) {
                if (array[j] > array[j + 1]) {
                    temp = array[j + 1];
                    array[j + 1] = array[j];
                    array[j] = temp;
                }
            }
        }
    }

    /**
     * 选择排序
     * 每次从数组中找出最大值,将其与最后一个元素交换
     * 时间复杂度O(n^2)
     * 空间复杂度O(1)
     */
    int max, temp;

    public void selectSort(int[] array) {
        for (int i = array.length - 1; i > 0; i--) {
            //在剩余元素中寻找最大值
            max = 0;
            for (int j = 0; j <= i; j++) {
                if (array[j] > array[max]) {
                    max = j;
                }
            }
            //最大值放到最后
            temp = array[i];
            array[i] = array[max];
            array[max] = temp;
        }
    }

    /**
     * 插入排序
     * 从数组中取出一个元素,查找其在新数组中的位置,进行插入
     * 有序数组从后向前查
     * 时间复杂度O(n^2)
     * 空间复杂度O(1)
     */
    public void insertSort(int[] array) {
        int temp;
        for (int i = 1; i < array.length; i++) {
            //缓存当前待插入值
            temp = array[i];
            //从后向前
            int j = i - 1;
            for (; j >= 0; j--) {
                //找到待插入位置
                if (temp > array[j]) {
                    array[j + 1] = temp;
                    break;
                }
                //数组元素后移
                array[j + 1] = array[j];
            }
            if(j==-1) {
                array[0] = temp;
            }
        }
    }

    /**
     * 快速排序
     * 一趟排序将数组分为两部分,一部分的数据大于另一部分的数组,在递归进行快速排序
     */
    public void quickSort(int[] array) {
        quickSort(array, 0, array.length - 1);
    }

    public void quickSort(int[] array, int start, int end) {
        //确定一个分割点
        int mid = array[start];
        int left = start;
        int right = end;
        while (left < right) {
            //必须先右后左,若先左,则左永远不会+1
            //从右向左找一个小于mid的值
            while (array[right] > mid && left < right) right--;
            array[left] = array[right];
            //从左向右找一个大于mid的值
            while (array[left] < mid && left < right) left++;
            array[right] = array[left];
        }
        array[left] = mid;
        //递归,分别对两侧进行快速排序
        if (left - 1 > start) quickSort(array, start, left - 1);
        if (right + 1 < end) quickSort(array, right + 1, end);
    }

    /**
     * 堆排序
     * 构建大顶堆,将最后一个元素与堆顶交换,再构建大顶堆,以此类推,直到最后一个元素
     * 堆是完全二叉树,一个数组的下标为i,则他的父节点是(i-1)/2
     */
    public void heapSort(int[] array) {
        int temp;
        for (int i = array.length - 1; i > 0; i--) {
            buildBigHeap(array, 0, i);
            //将栈顶与最后一个元素交换
            temp = array[0];
            array[0] = array[i];
            array[i] = temp;
        }
    }

    public void buildBigHeap(int[] array, int start, int end) {
        int temp;
        for (int i = end; i > start; i--) {
            if (array[i] > array[(i - 1) / 2]) {
                temp = array[i];
                array[i] = array[(i - 1) / 2];
                array[(i - 1) / 2] = temp;
            }
        }
    }

    /**
     * 归并排序(2路归并)
     * 将一个数组对半拆分,直到数据两两一组,之后合并排序,这样将两个有序数组合并为一个有序数组,直到最后一个结果
     */
    public void mergeSort(int[] array) {
        int[] result = new int[array.length];
        split(array, 0, array.length - 1);
    }

    public void split(int[] array, int start, int end) {
        if (start < end) {
            int mid = (end + start) / 2;
            split(array, start, mid);
            split(array, mid + 1, end);
            merge(array, start, mid, end);
        }
    }

    public void merge(int[] array, int start, int mid, int end) {
        int left = start;
        int right = mid + 1;
        int cur = 0;
        int[] result = new int[end - start + 1];
        while (left <= mid && right <= end) {
            if (array[left] < array[right]) {
                result[cur++] = array[left++];
            } else {
                result[cur++] = array[right++];
            }
        }
        while (left <= mid) {
            result[cur++] = array[left++];
        }
        while (right <= end) {
            result[cur++] = array[right++];
        }
        System.arraycopy(result, 0, array, start, end - start + 1);
    }

    /**
     * 基数排序
     * 所有数字按照个十百千,分别进行排序,最后一次排序的结果就是有序的
     * 1.找出最大值
     * 2.所有数字的位数与最大值补齐
     * 3.从个位开始排序
     */
    public void radixSort(int[] array) {
        int max = array[0];
        //找出最大值
        for (int i = 0; i < array.length; i++) {
            if (array[i] > max) {
                max = array[i];
            }
        }
        //判断最大值有多少位
        int maxLength = 1;
        while (max >= 10) {
            maxLength *= 10;
            max = max / 10;
        }
        //每一位单独排序
        for (int i = 1; i <= maxLength; i *= 10) {
            radixSort(array, i);
        }
    }

    public void radixSort(int[] array, int place) {
        //因为一位数只有0-9共10种情况,因此创建一个数组,每个数组存储一个链表
        List<LinkedList> list = new ArrayList();
        for (int i = 0; i < 10; i++) {
            list.add(new LinkedList<Integer>());
        }
        //将节点插入相应位置
        for (int i = 0; i < array.length; i++) {
            list.get((array[i] / place) % 10).add(array[i]);
        }
        //将列表元素放进数组中
        Iterator iterator = list.iterator();
        LinkedList linkedList;
        int cur = 0;
        while (iterator.hasNext() && cur < array.length) {
            linkedList = (LinkedList) iterator.next();
            while (!linkedList.isEmpty()) {
                array[cur++] = (int) linkedList.getFirst();
                linkedList.remove();
            }
        }
    }

    /**
     * 希尔排序
     * 设置步长,相差步长的元素分为一组,进行快速排序
     * 缩小步长为原来的一半,重复上步
     * 当步长为1时,即全部数据有序
     */
    public void shellSort(int[] array) {
        //设置步长为 数组长度的一半,之后不断折半
        for (int step = (array.length+1)/ 2; step > 0; step = (step+1)/2) {
            for (int i = 0; i < step; i++) {
                shellSort(array, i, step);
            }
            if(step==1)
                break;
        }
    }

    public void shellSort(int[] array, int start, int step) {
        int temp;
        //第一个已经有序
        for (int i = start+step; i < array.length - 1; i += step) {
            temp = array[i];
            //从有序表中查找
            int j = i-step;
            for (; j >= start; j -= step) {
                if (temp > array[j]) {
                    array[j+step]=temp;
                    break;
                }
                array[j+step]=array[j];
            }
            if(j==start-step){
                array[start]=temp;
            }
        }
    }


    /**
     * 桶排序
     * 1.确定桶的数量,通过(max-min)/len+1
     * 2.用arraylist存储桶,桶内存储arraylist
     * 3.将数组元素分到桶内
     * 4.对每个桶分别排序
     * 5.遍历所有桶,输出结果
     */
    public void bucketSort(int[] array) {
        //找出最大最小值
        int min=array[0];
        int max=array[0];
        for(int i=1;i<array.length;i++){
            min=min<array[i]?min:array[i];
            max=max>array[i]?max:array[i];
        }
        //确定桶的数量,+1是避免max-min<len
        int bucket=(max-min)/array.length+1;

        //创建桶
        List<ArrayList<Integer>> list=new ArrayList<>(bucket);
        for(int i=0;i<bucket;i++){
            list.add(new ArrayList<Integer>());
        }
        //元素入桶
        for(int i=0;i<array.length;i++){
            list.get((array[i]-min)/array.length).add(array[i]);
        }
        //对桶排序
        for(int i=0;i<list.size();i++){
            Collections.sort(list.get(i));
        }
        //将桶中元素取出,放入数组
        int cur=0;
        Iterator<ArrayList<Integer>> iterator = list.iterator();
        while(iterator.hasNext()){
            Iterator<Integer> iterator1 = iterator.next().iterator();
            while(iterator1.hasNext()){
                array[cur++]=iterator1.next();
            }
        }
    }

    /**
     * 计数排序
     * 将数组内数组映射到数组下标,数组元素大小代表出现的次数
     * 1.求出数组长度,max-min+1
     * 2.偏移量为min
     * 3.将元素对应的数组元素+1
     * 4.按照数组元素大小输出数组元素
     */
    public void countSort(int[] array) {
        int min=array[0];
        int max=array[0];
        for(int i=1;i<array.length;i++){
            min=min<array[i]?min:array[i];
            max=max<array[i]?array[i]:max;
        }
        int[] newArray=new int[max-min+1];
        //将数组元素映射到新数组上
        for(int i=0;i<array.length;i++){
            newArray[array[i]-min]++;
        }
        int cur=0;
        for(int i=0;i<newArray.length;i++){
            while(newArray[i]--!=0){
                array[cur++]=i+min;
            }
        }
    }
}