排序算法之冒泡-快速-计数-桶-基数-堆Java版

冒泡排序

package org.gallant.algorithm;

import static org.gallant.algorithm.SortUtil.println;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author 会灰翔的灰机
 * @date 2020/1/19
 */
public class BubbleSort {

    public static void bubbleSort(int[] data) {
        int size = data.length;
        while (size > 1) {
            for (int i = 0; i < size - 1; i++) {
                int left = data[i];
                int right = data[i + 1];
                if (left > right) {
                    data[i] = right;
                    data[i + 1] = left;
                }
            }
            size--;
        }
    }

    public static void main(String[] args) {
        int[] array = SortUtil.randomArray(9);
        println(array);
        bubbleSort(array);
        println(array);
    }

}

快速排序

package org.gallant.algorithm;

import static org.gallant.algorithm.SortUtil.println;

/**
 * @author 会灰翔的灰机
 * @date 2020/1/19
 */
public class QuickSort {

    public static void quickSort(int[] data, int start, int end) {
        int pivotIndex = partitioning(data, start, end);
        if (pivotIndex > -1) {
            quickSort(data, start, pivotIndex);
            quickSort(data, pivotIndex, end);
        }
    }

    public static int partitioning(int[] data, int start, int end) {
        int pivot = data[start];
        int i = end, j = start + 1;
        while (i >= j) {
            int right = data[i];
            int left = data[j];
            // 相等的值放在右边子序列中
            boolean rightLesserPivot = right < pivot;
            boolean leftGreaterPivot = left >= pivot;
            // 哨兵i大于基准值,继续移动
            if (!rightLesserPivot) {
                i--;
            } else {
                // 哨兵j小于基准值,并且哨兵i已经发现大于基准值的值时,移动哨兵j
                if (!leftGreaterPivot) {
                    j++;
                }
            }
            if (leftGreaterPivot && rightLesserPivot) {
                // 哨兵i与哨兵j相遇前找到了比基准值大,比基准值小的数值,交换他们的位置
                swap(data, left, j, right, i);
                i--;
                j++;
            }
            // 哨兵i与哨兵j相遇
            if (i == j) {
                boolean isLesserPivot = data[i] < pivot;
                if (isLesserPivot) {
                    swap(data, pivot, start, data[i], i);
                }
                println(data);
                return i;
            }
        }
        return -1;
    }

    public static void swap(int[] data, int leftValue, int leftIndex, int rigthValue, int rightIndex){
        data[rightIndex] = leftValue;
        data[leftIndex] = rigthValue;
    }

    public static void main(String[] args) {
        int[] array = SortUtil.randomArray(15);
        println(array);
        quickSort(array, 0, array.length - 1);
        println(array);
    }

}

计数排序

package org.gallant.algorithm;

import static org.gallant.algorithm.SortUtil.print;
import static org.gallant.algorithm.SortUtil.println;

/**
 * @author 会灰翔的灰机
 * @date 2020/1/20
 */
public class CountingSort {

    public static void countingSort(int[] data) {
        int max = Integer.MIN_VALUE,min = Integer.MAX_VALUE;
        // 1. 查找最大值、最小值
        for (int i = 0; i < data.length; i++) {
            int currentValue = data[i];
            if (currentValue > max) {
                max = currentValue;
            }
            if (currentValue < min) {
                min = currentValue;
            }
        }
        // 2. 将数据根据最小值映射放入对应的桶内(index下标处)
        println("max:"+max+",min:"+min);
        int[] count = new int[max - min + 1];
        for (int i = 0; i < data.length; i++) {
            int currentValue = data[i];
            print(currentValue+",");
            count[currentValue - min] += 1;
        }
        println("");
        println(count);
        // 3. 根据计数桶还原数据到原数据中。计数桶中的数据由于映射的算法可知是有序的
        int currentDataIndex = 0;
        for (int i = 0; i < count.length; i++) {
            int cnt = count[i];
            if (cnt > 0) {
                for (int j = 0; j < cnt; j++) {
                    data[currentDataIndex] = min + i;
                    currentDataIndex++;
                }
            }
        }
    }

    public static void main(String[] args) {
        int[] array = SortUtil.randomArray(11);
        println(array);
        countingSort(array);
        println(array);
    }

}

桶排序

package org.gallant.algorithm;

import static org.gallant.algorithm.SortUtil.println;

import java.util.Arrays;
import java.util.Objects;

/**
 * @author 会灰翔的灰机
 * @date 2020/1/20
 */
public class BucketSort {

    public static void bucketSort(int[] array) {
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        // 1. 查找 数字长度 最大值、最小值
        for (int currentValue : array) {
            int len = getIntegerLength(currentValue);
            if (len > max) {
                max = len;
            }
            if (len < min) {
                min = len;
            }
        }
        // 2. 将数据根据数字长度以及最小长度,放入对应的桶中
        println("max:"+max+",min:"+min);
        Integer[][] count = new Integer[max - min + 1][array.length];
        for (int i = 0; i < array.length; i++) {
            int currentValue = array[i];
            Integer[] bucket = count[getIntegerLength(currentValue) - min];
            for (int j = 0; j < bucket.length; j++) {
                if (bucket[j] == null) {
                    bucket[j] = currentValue;
                    break;
                }
            }
        }
        println(count);
        // 3. 根据映射函数可知,桶的下标大的桶中的所有数据大于下标小的桶中的数据
        // 所以将每个桶排序后直接拼接结果便可以得到全局有序的集合
        int currentDataIndex = 0;
        for (int i = 0; i < count.length; i++) {
            Integer[] bucketObj = count[i];
            if (bucketObj.length > 0) {
                int[] bucket = Arrays.stream(bucketObj).filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
                Sorts.insertSort(bucket);
                for (int j = 0; j < bucket.length; j++) {
                    array[currentDataIndex] = bucket[j];
                    currentDataIndex++;
                }
            }
        }
    }

    public static int getIntegerLength(int value) {
        return Integer.toString(value).length();
    }

    public static void main(String[] args) {
        int[] array = SortUtil.randomArray2(10);
        println(array);
        bucketSort(array);
        println(array);
    }

}

基数排序

package org.gallant.algorithm;

import static org.gallant.algorithm.SortUtil.println;

import java.util.Arrays;
import java.util.Objects;

/**
 * @author 会灰翔的灰机
 * @date 2020/1/20
 */
public class RadixSort {

    public static void radixSort(int[] array) {
        int maxLen = 0;
        for (int i = 0; i < array.length; i++) {
            int currentValue = array[i];
            int len = Integer.toString(currentValue).length();
            if (len > maxLen) {
                maxLen = len;
            }
        }
        // 1. 从个位数至最高位,按每个位的数字进行分桶,逐个执行桶排序
        for (int i = 0; i < maxLen; i++) {
            Integer[][] buckets = new Integer[10][array.length];
            double divisor = Math.pow(10, i);
            for (int j = 0; j < array.length; j++) {
                int currentValue = array[j];
                int index = (int) ((currentValue / divisor) % 10);
                Integer[] bucket = buckets[index];
                for (int k = 0; k < bucket.length; k++) {
                    if (bucket[k] == null) {
                        bucket[k] = currentValue;
                        break;
                    }
                }
            }
            // 2. 根据映射函数可知,桶的下标大的桶中的所有数据大于下标小的桶中的数据
            // 所以将每个桶排序后直接拼接结果便可以得到全局有序的集合
            int currentDataIndex = 0;
            for (int l = 0; l < buckets.length; l++) {
                Integer[] bucketObj = buckets[l];
                if (bucketObj.length > 0) {
                    int[] bucket = Arrays.stream(bucketObj).filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
                    Sorts.insertSort(bucket);
                    for (int m = 0; m < bucket.length; m++) {
                        array[currentDataIndex] = bucket[m];
                        currentDataIndex++;
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        int[] array = SortUtil.randomArray2(9);
        println(array);
        radixSort(array);
        println(array);
    }

}

堆排序

package org.gallant.algorithm;

import static org.gallant.algorithm.SortUtil.println;

/**
 * 参考:https://www.geeksforgeeks.org/heap-sort/
 * @author 会灰翔的灰机
 * @date 2020/1/21
 */
public class HeapSort {

    /**
     * 初始数组被看作一个完全二叉树
     * Input data: 4, 10, 3, 5, 1
     *          4(0)
     *         /   \
     *      10(1)   3(2)
     *     /   \
     *  5(3)    1(4)
     *
     * The numbers in bracket represent the indices in the array
     * representation of data.
     *
     * Applying heapify procedure to index 1:
     *          4(0)
     *         /   \
     *     10(1)    3(2)
     *     /   \
     * 5(3)    1(4)
     *
     * Applying heapify procedure to index 0:
     *         10(0)
     *         /  \
     *      5(1)  3(2)
     *     /   \
     *  4(3)    1(4)
     * The heapify procedure calls itself recursively to build heap
     *  in top down manner.
     */
    public static void heapSort(int[] array) {
        int heapSize = array.length;
        // 1. 构建最大堆。最大堆的每个非叶子节点都是左右子树的最大节点。即:构建之后0索引处为整棵树的最大值
        for (int i = heapSize / 2 - 1; i >= 0; i--) {
            heapify(array, heapSize, i);
        }
        for (int i = array.length - 1; i >= 0 ; i--) {
            // 2. 将最大值交换至最后,剩余[0, n - 2]恢复非最大堆状态。n - 1索引处为当前最大堆中的最大值
            swap(array, i, 0);
            // 3. 重复步骤1,2,直至整个堆有序
            heapify(array, i, 0);
        }
    }

    public static void heapify(int[] array, int heapSize, int largestNodeIndex) {
        // 初始化根节点
        int largest = largestNodeIndex;
        // 根节点左子节点索引
        int leftChild = 2 * largestNodeIndex + 1;
        // 根节点右子节点索引
        int rightChild = 2 * largestNodeIndex + 2;
        // 如果左子树大于根节点,更新根节点索引
        if (leftChild < heapSize && array[leftChild] > array[largest]) {
            largest = leftChild;
        }
        // 如果右子树大于根节点,更新根节点索引
        if (rightChild < heapSize && array[rightChild] > array[largest]) {
            largest = rightChild;
        }
        // 根节点索引发生变更,更新根节点
        if (largest != largestNodeIndex) {
            swap(array, largest, largestNodeIndex);
            // 左子树或右子树发生变更,递归更新发生变更的子树
            heapify(array, heapSize, largest);
        }
    }

    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 = SortUtil.randomArray(9);
        println(array);
        heapSort(array);
        println(array);
    }

}

发布了81 篇原创文章 · 获赞 85 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u010597819/article/details/104082806