常见排序算法

冒泡排序

public class BubbleSort {

    public static void sort(int[] array) {
        int len = array.length;
        for (int i = 0; i < len - 1; i++) {
            for (int j = 0; j < len - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }
    // 改进1
    public static void sort2(int[] array) {
        int len = array.length;

        for (int i = 0; i < len - 1; i++) {
            // 有序标记,每一轮的初始是true
            boolean isSorted = true;
            for (int j = 0; j < len - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    isSorted = false;
                }
            }
            if (isSorted) break;
        }
    }
    // 改进2
    public static void sort3(int[] array) {
        int len = array.length;

        // 记录最后一次交换的位置
        int lastExchangeIndex = 0;

        // 无序数列的边界,每次比较只需要比到这里为止
        int sortBorder = len - 1;

        for (int i = 0; i < len - 1; i++) {
            boolean isSorted = true;
            for (int j = 0; j < sortBorder; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    isSorted = false;
                    // 把无序数列的边界更新为最后一次交换元素的位置
                    lastExchangeIndex = j;
                }
            }
            sortBorder = lastExchangeIndex;
            if (isSorted) break;
        }
    }

    public static void main(String[] args) {
        int[] array = new int[] { 5, 8, 6, 3, 9, 2, 1, 7 };
        sort(array);
        System.out.println(Arrays.toString(array));
    }
}

选择排序

public class SelectSort {

    public static void sort(int[] array) {
        int len = array.length;

        // 总共要经过 N-1 轮比较
        for (int i = 0; i < len - 1; i++) {
            int minIndex = i;

            // 每轮需要比较的次数 N-i
            for (int j = i + 1; j < len; j++) {
                if (array[minIndex] > array[j]) minIndex = j;
            }

            // 将找到的最小值和i位置所在的值进行交换
            if (minIndex != i) {
                int temp = array[i];
                array[i] = array[minIndex];
                array[minIndex] = temp;
            }
        }

    }

    public static void main(String[] args) {
        int[] array = new int[]{3, 4, 2, 1, 5, 6, 7, 8};
        sort(array);
        System.out.println(Arrays.toString(array));
    }

}

插入排序

public class InsertSort {

    public static void sort(int[] array) {
        int len = array.length;
        // 从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
        for (int i = 1; i < len; i++) {
            // 记录要插入的数据
            int temp = array[i];

            // 从已经排序的序列最右边的开始比较,找到比其小的数
            int j = i;
            while (j >= 1 && array[j - 1] > temp) {
                array[j] = array[j - 1];
                j--;
            }
            array[j] = temp;
        }
    }

    public static void main(String[] args) {
        int[] array = new int[]{3, 4, 2, 1, 5, 6, 7, 8};
        sort(array);
        System.out.println(Arrays.toString(array));
    }
}

希尔排序

public class ShellSort {

    public static void sort2(int[] array) {
        int len = array.length;
        for (int step = len / 2; step > 0; step /= 2) {
            for (int i = step; i < len; i++) {
                int temp = array[i];
                int j = i - step;
                while (j >= 0 && array[j] > temp) {
                    array[j + step] = array[j];
                    j -= step;
                }
                array[j + step] = temp;
            }
        }
    }

    public static void sort(int[] array) {
        int len = array.length;
        // 希尔排序的增量
        int step = len;
        while (step > 1) {
            // 使用希尔增量的方式,即每次折半
            step /= 2;
            for (int x = 0; x < step; x++) {
                for (int i = x + step; i < len; i += step) {
                    int temp = array[i];
                    int j = i;
                    while (j >= step && array[j - step] > temp) {
                        array[j] = array[j - step];
                        j -= step;
                    }
                    array[j] = temp;
                }
            }
        }
    }

    public static void main(String[] args) {
        int[] array = {5, 3, 9, 12, 6, 1, 7, 2, 4, 11, 8, 10};
        sort2(array);
        System.out.println(Arrays.toString(array));
    }

}

归并排序

public class MergeSort {

    // 划分
    public static void mergeSort(int[] array, int start, int end) {
        if (start == end) return;
        int mid = (start + end) / 2;
        // 折半成两个小集合,分别进行递归
        mergeSort(array, start, mid);
        mergeSort(array, mid + 1, end);
        merge(array, start, mid, end);
    }

    // 合并
    private static void merge(int[] array, int start, int mid, int end) {
        // 开辟临时空间
        int len = end - start + 1;
        int[] tempArr = new int[len];
        int p1 = start;
        int p2 = mid + 1;
        int p = 0;
        // 比较两个小集合的元素,依次放入大集合
        while (p1 <= mid && p2 <= end) {
            if (array[p1] <= array[p2]){
                tempArr[p++] = array[p1++];
            } else {
                tempArr[p++] = array[p2++];
            }
        }

        // 左侧小集合还有剩余,依次放入大集合尾部
        while (p1 <= mid) {
            tempArr[p++] = array[p1++];
        }
        // 右侧小集合还有剩余,依次放入大集合尾部
        while (p2 <= end) {
            tempArr[p++] = array[p2++];
        }

        // 把大集合的元素复制回原数组
        /*for (int i = 0; i < len; i++) {
            array[start++] = tempArr[i];
        }*/

        System.arraycopy(tempArr, 0, array, start, len);
    }

    public static void main(String[] args) {
        int[] array = {5, 8, 6, 3, 9, 2, 1, 7};
        mergeSort(array, 0, array.length - 1);
        System.out.println(Arrays.toString(array));
    }

}

快速排序

public class QuickSort {

    public static void quickSort(int[] array, int startIndex, int endIndex) {
        // 递归结束条件:startIndex大于等于endIndex的时候
        // 当partition为0时,会出现start > end的情况
        if (startIndex >= endIndex) return;
        // 得到基准元素的位置
        int pivotIndex = partition(array, startIndex, endIndex);
        // 用分治法递归数列的两部分
        quickSort(array, startIndex, pivotIndex - 1);
        quickSort(array, pivotIndex + 1, endIndex);
    }

    // 栈代替递归
    public static void quickSort2(int[] array, int startIndex, int endIndex) {
        Stack<Map<String, Integer>> stack = new Stack<>();
        HashMap<String, Integer> map = new HashMap<>();
        map.put("start", startIndex);
        map.put("end", endIndex);
        stack.push(map);

        while (!stack.empty()) {
            Map<String, Integer> popMap = stack.pop();
            Integer start = popMap.get("start");
            Integer end = popMap.get("end");
            int pivotIndex = partition2(array, start, end);

            if (start < pivotIndex - 1) {
                Map<String, Integer> leftMap = new HashMap<>();
                leftMap.put("start", start);
                leftMap.put("end", pivotIndex - 1);
                stack.push(leftMap);
            }
            if (end > pivotIndex + 1) {
                Map<String, Integer> rightMap = new HashMap<>();
                rightMap.put("start", pivotIndex + 1);
                rightMap.put("end", end);
                stack.push(rightMap);
            }
        }
    }

    // 挖坑法
    private static int partition(int[] array, int startIndex, int endIndex) {
        // 取第一个位置的元素作为基准元素
        int pivot = array[startIndex];
        // 坑的位置,初始等于pivot的位置
        int pIndex = startIndex;
        // 大循环在左右指针重合时结束
        while (startIndex < endIndex) {
            // 从右向左进行比较
            while (array[endIndex] >= pivot && startIndex < endIndex) endIndex--;
            array[pIndex] = array[endIndex];
            pIndex = endIndex;

            // 从左向右进行比较
            while (array[startIndex] < pivot && startIndex < endIndex) startIndex++;
            array[pIndex] = array[startIndex];
            pIndex = startIndex;
        }
        array[pIndex] = pivot;

        return pIndex;
    }

    // 指针交换法
    private static int partition2(int[] array, int startIndex, int endIndex) {
        // 取第一个位置的元素作为基准元素
        int pivot = array[startIndex];
        int pIndex = startIndex;

        // 大循环在左右指针重合时结束
        while (startIndex < endIndex) {
            while (array[endIndex] >= pivot && startIndex < endIndex) endIndex--;
            while (array[startIndex] < pivot && startIndex < endIndex) startIndex++;
            
            if (startIndex < endIndex) {
                int temp = array[startIndex];
                array[startIndex] = array[endIndex];
                array[endIndex] = temp;
            }
        }
        array[pIndex] = array[startIndex];
        array[startIndex] = pivot;

        return startIndex;
    }

    public static void main(String[] args) {
        int[] arr = new int[] {4,4,7,6,5,3,2,8,1};
        quickSort2(arr, 0, arr.length-1);
        System.out.println(Arrays.toString(arr));
    }

}
posted @ 2021-03-02 17:38  oumae  阅读(49)  评论(0编辑  收藏  举报