经典排序算法--Java实现

import removeNthFromEnd.ListNode;
import studyproxy.staticproxy.MaskInterface;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class ClassicSort {
    public static void main(String[] arg) {
//        int[] nums = {9, 7, 23, 45, 2, 1, 0, -1};
        int[] nums = {9, 7, 23, 0, 100, 45, 2, 1, 10, 111, 0};
        ClassicSort classicSort = new ClassicSort();
//        classicSort.bubbleSort(nums);
//        classicSort.quickSort(nums);
//        classicSort.simpleInsertSort(nums);
//        classicSort.shellSort(nums);
//        classicSort.simpleSelectSort(nums);
        classicSort.heapSort(nums);
//        classicSort.mergeSort(nums);
//        classicSort.countSort(nums);
//        classicSort.bucketSort(nums);
//        classicSort.radixSort2(nums);
        System.out.println(Arrays.toString(nums));

    }

    /**
     * 冒泡排序
     *
     * @param nums
     */
    public void bubbleSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;

        for (int i = nums.length - 1; i > 0; i--) {
            for (int j = 0; j < i; j++) {
                if (nums[j] > nums[j + 1]) {
                    int temp = nums[j + 1];
                    nums[j + 1] = nums[j];
                    nums[j] = temp;
                }
            }
        }
    }

    /**
     * 快速排序
     *
     * @param nums
     */
    public void quickSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;
        int start = 0;
        int end = nums.length - 1;
        quickSort(nums, start, end);
    }

    private void quickSort(int[] nums, int start, int end) {
        if (start >= end) return;
        int mid = (start + end) / 2;
        int left = start;
        int right = end;
        while (left < right) {

            while (nums[left] < nums[mid]) left++;
            while (nums[right] > nums[mid]) right--;

            if (left < right) {
                //swap
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left++;
                right--;
            } else {
                left++;
            }
        }

        quickSort(nums, start, right);
        quickSort(nums, left, end);
    }

    /**
     * 简单插入排序
     *
     * @param nums
     */
    public void simpleInsertSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;
        for (int i = 1; i <= nums.length - 1; i++) {
            int temp = nums[i];
            int index = i;
            while (index > 0 && temp < nums[index - 1]) {
                nums[index] = nums[index - 1];
                index--;
            }
            nums[index] = temp;
        }
    }

    /**
     * 希尔排序,递减增量排序算法
     *
     * @param nums
     */
    public void shellSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;
        int gap = nums.length / 2;
        while (gap > 0) {
            for (int i = gap; i <= nums.length - 1; i += gap) {
                int temp = nums[i];
                int index = i;
                while (index > 0 && temp < nums[index - gap]) {
                    nums[index] = nums[index - gap];
                    index = index - gap;
                }
                nums[index] = temp;
            }
            gap = gap / 2;
        }
    }

    /**
     * 简单选择排序
     *
     * @param nums
     */
    public void simpleSelectSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;

        for (int i = 0; i < nums.length - 1; i++) {
            int index = i;
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[j] < nums[index]) {
                    index = j;
                }
            }
            int temp = nums[i];
            nums[i] = nums[index];
            nums[index] = temp;
        }
    }

    /**
     * 堆排序
     *
     * @param nums
     */
    public void heapSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;
        //堆化,建立大顶堆
        //找到最后一个非叶子节点
        int k = (nums.length - 1) / 2;
        for (int i = k; i >= 0; i--) {
            headAdjust(nums, i, nums.length);
        }
        //排序,每次取出堆顶的数放到末尾去
        for (int i = nums.length - 1; i >= 0; i--) {
            int temp = nums[i];
            nums[i] = nums[0];
            nums[0] = temp;
            headAdjust(nums, 0, i);
        }
    }

    /**
     * 堆的调整
     * 递归写法
     * @param nums
     * @param index  须要调整的节点下标
     * @param length 堆的容量
     */
    private void headAdjust(int[] nums, int index, int length) {
        int left = 2 * index + 1;
        int maxIndex = left;//定义一个指针,指向左右两个节点中比较大的那个节点,初始时先指向左节点
        if(left < length){//此节点存在左子节点
            int right = left + 1;
            //若是存在右节点,而且右节点的值偏大,指向右节点
            if(right < length && nums[left] < nums[right]){
                maxIndex = right;
            }
            //根节点值比较小,和比本身大的子节点互换
            if (nums[index] < nums[maxIndex]) {
                int temp = nums[index];
                nums[index] = nums[maxIndex];
                nums[maxIndex] = temp;
                //指向刚才调整过的节点,再次调整
                headAdjust(nums, maxIndex, length);
            }
        }
    }
    /**
     * 堆的调整
     * 非递归写法
     * @param nums
     * @param index  须要调整的节点下标
     * @param length 堆的容量
     */
    private void headAdjust2(int[] nums, int index, int length) {
        while (index < length) {
            int left = 2 * index + 1;
            if (left >= length) break;
            int maxIndex = left;
            if (left + 1 < length && nums[left] < nums[left + 1]) {
                maxIndex = left + 1;
            }
            if (nums[index] < nums[maxIndex]) {
                int temp = nums[index];
                nums[index] = nums[maxIndex];
                nums[maxIndex] = temp;
                index = maxIndex;
            } else {
                break;
            }
        }
    }

    /**
     * 归并排序
     *
     * @param nums
     */
    public void mergeSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;
        int[] temp = new int[nums.length];
        mergeSort(nums, 0, nums.length - 1, temp);
    }

    private void mergeSort(int[] nums, int start, int end, int[] temp) {
        if (start < end) {
            int mid = (start + end) / 2;
            mergeSort(nums, start, mid, temp);
            mergeSort(nums, mid + 1, end, temp);
            merge(nums, start, mid, end, temp);
        }
    }

    private void merge(int[] nums1, int start, int mid, int end, int[] temp) {
        int left1 = start;
        int left2 = mid + 1;
        int index = start;
        while (left1 <= mid && left2 <= end) {
            if (nums1[left1] < nums1[left2]) {
                temp[index++] = nums1[left1++];
            } else {
                temp[index++] = nums1[left2++];
            }
        }

        while (left1 <= mid) {
            temp[index++] = nums1[left1++];
        }
        while (left2 <= end) {
            temp[index++] = nums1[left2++];
        }
        for (int i = 0; i < index - start; i++) {
            nums1[start + i] = temp[start + i];
        }
    }

    /**
     * 链表归并排序
     *
     * @param head
     * @return
     */
    public ListNode mergeSoreLinkedList(ListNode head) {
        if (null == head || head.next == null) return head;
        ListNode fast = head;
        ListNode slow = head;
        while (null != slow && null != slow.next
                && null != fast && null != fast.next && null != fast.next.next) {
            fast = fast.next.next;
            slow = slow.next;
        }
        fast = slow;
        slow = slow.next;
        fast.next = null;
        ListNode left = mergeSoreLinkedList(head);
        ListNode right = mergeSoreLinkedList(slow);
        return merge2LinkedList(left, right);
    }

    private ListNode merge2LinkedList(ListNode p, ListNode q) {
        if (null == p) return q;
        if (null == q) return p;
        ListNode res = new ListNode(0);
        ListNode index = res;
        while (null != p && null != q) {
            if (p.val <= q.val) {
                index.next = p;
                p = p.next;
            } else {
                index.next = q;
                q = q.next;
            }
            index = index.next;
        }

        if (p == null) {
            index.next = q;
        } else {
            index.next = p;
        }
        return res.next;
    }

    /**
     * 计数排序,排序数据范围必须是整数范围内
     *
     * @param nums
     */
    public void countSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;
        //找出最大值,最小值
        int minValue = Integer.MAX_VALUE;
        int maxValue = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
            minValue = Math.min(nums[i], minValue);
            maxValue = Math.max(nums[i], maxValue);
        }
        //建立辅助空间
        int[] countArray = new int[maxValue - minValue + 1];
        //统计
        for (int i = 0; i < nums.length; i++) {
            int value = nums[i];
            countArray[value - minValue] += 1;
        }

        //整理
        int p = nums.length - 1;
        for (int i = countArray.length - 1; i >= 0; i--) {
            while (countArray[i] > 0) {
                nums[p] = i + minValue;
                p--;
                countArray[i] -= 1;
            }
        }
    }

    /**
     * 桶排序
     *
     * @param nums
     */
    public void bucketSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;
        int minValue = Integer.MAX_VALUE;
        int maxValue = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
            minValue = Math.min(minValue, nums[i]);
            maxValue = Math.max(maxValue, nums[i]);
        }

        //计算桶的个数
        int bucketNum = (maxValue - minValue) / nums.length + 1;
        ArrayList<ArrayList<Integer>> buckets = new ArrayList<>();
        for (int i = 0; i < bucketNum; i++) {
            buckets.add(new ArrayList<Integer>());
        }

        //遍历数组,将数据分配到不一样的桶里面
        for (int i = 0; i < nums.length; i++) {
            int index = (nums[i] - minValue) / nums.length;
            buckets.get(index).add(nums[i]);
        }

        //对每一个桶内部的数据进行排序
        for (int i = 0; i < bucketNum; i++) {
            Collections.sort(buckets.get(i));
        }

        //整理数据
        int index = 0;
        for (int i = 0; i < bucketNum; i++) {
            for (int j = 0; j < buckets.get(i).size(); j++) {
                nums[index++] = buckets.get(i).get(j);
            }
        }
    }

    /**
     * 基数排序
     *
     * @param nums
     */
    public void radixSort(int[] nums) {
        if (null == nums || 0 == nums.length) return;
        //查找到最大值
        int maxValue = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
            maxValue = Math.max(maxValue, nums[i]);
        }
        //准备10个桶,每一个桶的大小和nums的长度一致
        ArrayList<ArrayList<Integer>> buckets = new ArrayList<>(10);
        //最大值是几位数,就分配和收集几趟
        int temp = 1;
        while (maxValue > 0) {
            for (int i = 0; i < 10; i++) {
                buckets.add(new ArrayList<Integer>());
            }

            //先从个位数开始
            for (int i = 0; i < nums.length; i++) {
                int index = (nums[i] / temp) % 10;
                buckets.get(index).add(nums[i]);
            }

            //按顺序收集出来
            int p = 0;
            for (int i = 0; i < 10; i++) {
                for (int j = 0; j < buckets.get(i).size(); j++) {
                    nums[p++] = buckets.get(i).get(j);
                }
            }
            buckets.clear();

            temp = temp * 10;
            maxValue = maxValue / 10;
        }
    }

    /**
     * 优化,基数排序的第二版,辅助空间减少
     *
     * @param nums
     */
    public void radixSort2(int[] nums) {
        if (null == nums || 0 == nums.length) return;
        //建立辅助空间
        int[] tempArray = new int[nums.length];
        int[] bucket = new int[10];

        //找出最大数
        int maxValue = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
            maxValue = Math.max(maxValue, nums[i]);
        }
        int temp = 1;
        while (maxValue > 0) {
            //初始化辅助空间
            for (int i = 0; i < tempArray.length; i++) {
                tempArray[i] = 0;
            }
            for (int i = 0; i < bucket.length; i++) {
                bucket[i] = 0;
            }
            //遍历数组,桶中开始计数
            for (int i = 0; i < nums.length; i++) {
                int index = (nums[i] / temp) % 10;
                bucket[index]++;
            }

            //把桶中的数字叠加出来,以方便得出数字在tempArray中的下标
            for (int i = 1; i < bucket.length; i++) {
                bucket[i] = bucket[i] + bucket[i - 1];
            }

            //收集整理数据到tempArray中
            for (int i = nums.length - 1; i >= 0; i--) {
                int index = (nums[i] / temp) % 10;//获得数字位于哪一个桶里面
                int p = bucket[index] - 1;//由对应的桶中的数字得出数据位于tempArray中的下标
                tempArray[p] = nums[i];//数据存入tempArray中对应的位置
                bucket[index]--;//桶中的数字减一
            }

            //把数据倒回nums中
            for (int i = 0; i < tempArray.length; i++) {
                nums[i] = tempArray[i];
            }

            temp *= 10;
            maxValue /= 10;
        }

    }
}