import java.util.Arrays;

public class Sort
{
    public static int[] nums = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51};

    public static void main(String[] args)
    {
        // 冒泡
        int[] mNums = Arrays.copyOf(nums, nums.length);
        for (int i = 0; i < mNums.length - 1; i++) {
            for (int j = 0; j < mNums.length - 1 - i; j++) {
                if (mNums[j + 1] < mNums[j]) {
                    swap(mNums, j, j + 1);
                }
            }
        }
        System.out.println(Arrays.toString(mNums));
        // 快速
        int[] fNums = Arrays.copyOf(nums, nums.length);
        fastSort(fNums, 0, fNums.length - 1);
        System.out.println(Arrays.toString(fNums));
        // 归并
        int[] meNums = Arrays.copyOf(nums, nums.length);
        mergeSort(meNums, 0, meNums.length - 1);
        System.out.println(Arrays.toString(meNums));
        // 插入
        int[] iNums = Arrays.copyOf(nums, nums.length);
        insertSort(iNums);
        System.out.println(Arrays.toString(iNums));
        // 希尔
        int[] sNums = Arrays.copyOf(nums, nums.length);
        shellSort(sNums);
        System.out.println(Arrays.toString(sNums));
        // 堆
        int[] hNums = Arrays.copyOf(nums, nums.length);
        heapSort(hNums);
        System.out.println(Arrays.toString(hNums));
    }

    private static void heapSort(int[] a)
    {
        for (int i = a.length-1; i >= 0; i--) {
            max_heapify(a, i);
            swap(a, 0, i);
        }
    }

    private static void max_heapify(int[] a, int end)
    {
        //49,38,65,97,76,13,27
        if (a.length < 1 || a.length < end) { return; }

        int root = (end-1) / 2 ;
        for (; root >= 0; root--) {
            if (root * 2 >= end) {
                continue;
            }
            int left = root * 2+1;
            int right = (left + 1) > end ? left : left + 1;
            int maxChild = a[left] >= a[right] ? left : right;
            if (a[maxChild] > a[root]) {
                swap(a, root, maxChild);
            }
        }
    }

    private static void shellSort(int[] a)
    {
        int step = a.length / 2;
        // 缩小直到为1
        for (; step > 0; step /= 2) {
            // 以步长分组
            for (int j = 0; (j + step) < a.length; j++) {
                // 组内排序
                for (int k = 0; (k + step) < a.length; k += step) {
                    if (a[k] > a[k + step]) {
                        swap(a, k, k + step);
                    }
                }
            }
        }
    }

    private static void insertSort(int[] a)
    {
        int temp, i, j;
        for (i = 1; i < a.length; i++) {
            temp = a[i];
            for (j = i - 1; j >= 0; j--) {
                if (temp > a[j]) {
                    break;
                }
                else {
                    a[j + 1] = a[j];
                }
            }
            a[j + 1] = temp;
        }
    }

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

    public static void fastSort(int[] a, int start, int end)
    {
        if (start > end) {
            return;
        }
        int base = a[start];
        int i = start;
        int j = end;
        while (i != j) {
            while (a[j] > base && i < j) {
                j--;
            }
            while (a[i] <= base && i < j) {
                i++;
            }

            if (i < j) {
                swap(a, i, j);
            }
        }
        a[start] = a[i];
        a[i] = base;

        fastSort(a, start, i - 1);
        fastSort(a, i + 1, end);
    }

    public static void mergeSort(int[] a, int left, int right)
    {
        if (left < right) {
            int mid = (left + right) / 2;
            mergeSort(a, left, mid);
            mergeSort(a, mid + 1, right);
            merge(a, left, mid, right);
        }
    }

    public static void merge(int a[], int left, int mid, int right)
    {
        int[] temp = new int[right - left + 1];
        int i = left;
        int j = mid + 1;
        int k = 0;
        while (i <= mid && j <= right) {
            if (a[i] < a[j]) {
                temp[k++] = a[i++];
            }
            else {
                temp[k++] = a[j++];
            }
        }
        while (i <= mid) {
            temp[k++] = a[i++];
        }
        while (j <= right) {
            temp[k++] = a[j++];
        }
        for (int x = 0; x < temp.length; x++) {
            a[x + left] = temp[x];
        }
    }
}