Five sorting algorithm code templates

Depending on the memory occupied by data during sorting, sorting can be divided into

  • Internal sorting: The entire sorting process is performed in memory
  • External sorting: requires external storage

According to the method of gradually expanding the length of the recorded ordered sequence, the internal sorting can be divided into five major categories

  • Insertion class: Insert one or several records from an unordered subsequence into an ordered sequence
  • Selection class: Select the record with the smallest or largest keyword from the unordered subsequence of records and add it to the ordered subsequence
  • Exchange class: exchange records in an unordered subsequence to obtain the record with the smallest or largest keyword, and add it to the ordered subsequence.
  • Merge class: by merging two or more record ordered subsequences
  • Allocation class: The only sorting algorithm that does not require comparison between keywords. It mainly uses two basic operations of allocation and collection to implement the entire sorting process.

Code: gitee warehouse address: gitee warehouse entrance

1. Insertion class sorting

package com.algorithm.order.insert;

import java.util.Arrays;

/**
 * 插入类排序。
 *
 * 思想: 在一个已经排好序的有序序列区内,对待排序列的无序序列区中记录逐个进行处理,每一步将一个待排序的记录与同组那些已经排好序的
 *      记录进行比较,然后有序插入到该有序序列区中,直到所有待排记录全部插入为止。
 *
 *      直接插入排序
 *      折半插入排序
 *      希尔排序(缩小增量排序)
 *
 *
 */
public class InsertOrder {
    
    

    /** 直接插入排序。 */
     public static void directInsert(int[] nums) {
    
    
         System.out.println("direct insert: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        int tmp = 0;
        for (int i = 1; i < nums.length; i++) {
    
    
            if (nums[i] < nums[i-1]) {
    
    
                tmp = nums[i];
                int j = i - 1;
                for (; j >= 0 && tmp < nums[j]; j--) {
    
    
                    nums[j+1] = nums[j];
                }
                nums[j+1] = tmp;
            }
        }
    }

    /** 折半插入排序。 */
    public static void reduceByHalfInsert(int[] nums) {
    
    
        System.out.println("reduce by half insert: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        int tmp = 0;
        for (int i = 1; i < nums.length; i++) {
    
    
            if (nums[i] < nums[i-1]) {
    
    
                tmp = nums[i];
                int low = 0, high = i - 1;
                while (low <= high) {
    
    
                    int mid = low + (high - low)/2;
                    if (nums[mid] > tmp) {
    
    
                        high = mid - 1;
                    } else {
    
    
                        low = mid + 1;
                    }
                }
                for (int j = i - 1; j >= low; j--) {
    
    
                    nums[j+1] = nums[j];
                }
                nums[low] = tmp;
            }
        }
    }

    /** 希尔排序。 */
    public static void shellInsert(int[] nums) {
    
    
        System.out.println("shell insert: " + Arrays.toString(nums));
        for (int dt = nums.length/2; dt > 0; dt /= 2) {
    
    
            for (int i = dt; i < nums.length; i++) {
    
    
                int j = i;
                while (j - dt >= 0 && nums[j] < nums[j - dt]) {
    
    
                    int tmp = nums[j];
                    nums[j] = nums[j - dt];
                    nums[j - dt] = tmp;
                    j -= dt;
                }
            }
        }
    }

    /** 测试。 */
    public static void main(String[] args) {
    
    
        int[] nums = {
    
    3, 9, 1, 0, 4, 6, 7, 5, 8, 2};
        int[] result = {
    
    };

        // 直接插入排序
        result = nums.clone();
        directInsert(result);
        System.out.println(Arrays.toString(result));

        // 折半插入排序
        result = Arrays.copyOf(nums, nums.length);
        reduceByHalfInsert(result);
        System.out.println(Arrays.toString(result));

        // 希尔排序
        result = Arrays.copyOf(nums, nums.length);
        shellInsert(result);
        System.out.println(Arrays.toString(result));
    }
}

2. Select category sorting

package com.algorithm.order.select;

import java.util.Arrays;

/**
 * 选择类排序
 *
 * 思想:在第 i 趟的记录序列中选取关键字第 i 小的记录作为有序序列的第 i 个记录。
 * 关键:从剩余的待排序列中找出最小或最大的记录。
 *
 *      简单选择排序
 *      树形选择排序
 *      堆排序
 */
public class SelectOrder {
    
    

    /** 简单选择排序。 */
    public static void simpleSelect(int nums[]) {
    
    
        System.out.println("simple select sort: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        for (int i = 0; i < nums.length - 1; i++) {
    
    
            int k = i;
            for (int j = i + 1; j < nums.length; j++) {
    
    
                if (nums[j] < nums[k]) {
    
    
                    k = j;
                }
            }
            if (k != i) {
    
    
                int tmp = nums[i];
                nums[i] = nums[k];
                nums[k] = tmp;
            }
        }
    }

    /**
     * 树形选择排序。
     *      思路:
     *      1. 将数组的元素两两相比较,得到 n/2 个较小的元素 ;
     *      2. 重复步骤1,直至取到最小的元素
     *      3. 将剩余 n-1 个元素继续 1,2 步骤比较
     */
    public static void treeSelect(int[] nums) {
    
    
        System.out.println("tree select: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        int len = nums.length, treeSize = 2 * len - 1; // 完全二叉树节点数
        int[] tree = new int[treeSize];
        int j = treeSize;
        // 将数组放到 tree 中
        for (int i = len - 1; i >= 0; i --) {
    
    
            tree[j-1] = nums[i];
            j--;
        }
        // 根据叶子节点两两比较,小的填充非叶子节点
        for (int i = treeSize - 1; i > 0; i -= 2) {
    
    
            tree[(i-1)/2] = tree[i] > tree[i-1] ? tree[i-1] : tree[i];
        }

        // 重复寻找最小值,将最小值按顺序放回原来的数组
        int ii = 0;
        while (ii < len) {
    
    
            int min = tree[0];
            int minIndex = 0;
            // 确定最小值在 tree 中的位置
            for (int i = treeSize - 1; i > 0; i--) {
    
    
                if (min == tree[i]) {
    
    
                    minIndex = i;
                    // 将最小值设置为最大(设置为 Integer.MAX_VALUE)
                    tree[i] = Integer.MAX_VALUE;
                    break;
                }
            }

            // 将最小值按顺序重新放回原来的数组
            nums[ii++] = min;
            // 找到其兄弟节点
            while (minIndex > 0) {
    
    
                if (minIndex % 2 == 0) {
    
    
                    tree[(minIndex-1)/2] = tree[minIndex] > tree[minIndex-1] ? tree[minIndex-1] : tree[minIndex];
                    minIndex = (minIndex-1)/2;
                } else {
    
    
                    tree[minIndex/2] = tree[minIndex] > tree[minIndex+1] ? tree[minIndex+1] : tree[minIndex];
                    minIndex = minIndex/2;
                }
            }
        }
    }

    /** 堆排序。 */
    public static void heapSort(int[] nums) {
    
    
        System.out.println("heap sort: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        for (int i = nums.length/2 - 1; i >= 0; i--) {
    
    
            heapAdjust(nums, i, nums.length);
        }
        for (int i = nums.length - 1; i > 0; i--) {
    
    
            int tmp = nums[0];
            nums[0] = nums[i];
            nums[i] = tmp;
            heapAdjust(nums, 0, i);
        }
    }

    public static void heapAdjust(int[] nums, int index, int len) {
    
    
        int tmp = nums[index];
        for (int j = 2*index + 1; j < len; j = 2*j + 1) {
    
    
            if (j + 1 < len && nums[j] < nums[j+1]) {
    
    
                j++;
            }
            if (tmp >= nums[j]) {
    
    
                break;
            }
            nums[index] = nums[j];
            index = j;
        }
        nums[index] = tmp;
    }

    /** 测试。 */
    public static void main(String[] args) {
    
    
        int[] nums = {
    
    3, 9, 1, 0, 4, 6, 7, 5, 2, 8};
        int[] result = {
    
    };

        // 简单选择排序
        result = nums.clone();
        simpleSelect(result);
        System.out.println(Arrays.toString(result));

        //  树形选择排序
        result = nums.clone();
        treeSelect(result);
        System.out.println(Arrays.toString(result));

        //  堆排序
        result = nums.clone();
        heapSort(result);
        System.out.println(Arrays.toString(result));
    }
}

3. Exchange sorting

package com.algorithm.order.swap;

import java.util.Arrays;

/**
 * 交换类排序
 *
 * 思想:对代排序记录对关键字两两比较,只要发现两个记录为逆序就进行交换,直到没有逆序对记录为止。
 *
 *      冒泡排序
 *      快速排序
 */
public class SwapOrder {
    
    

    /** 冒泡排序。 */
    public static void bubbleSort(int nums[]) {
    
    
        System.out.println("bubble sort: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        boolean flag = true;
        for (int i = 0; i < nums.length - 1 && flag; i++) {
    
    
            flag = false;
            for (int j = 0; j < nums.length - i - 1; j++) {
    
    
                if (nums[j+1] < nums[j]) {
    
    
                    int tmp = nums[j];
                    nums[j] = nums[j+1];
                    nums[j+1] = tmp;
                    flag = true;
                }
            }
        }
    }

    /** 快速排序。 */
    public static void quickSort(int[] nums) {
    
    
        System.out.println("quick sort: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        int low = 0, high = nums.length - 1;
        if (low < high) {
    
    
            int pos = quickSortOne(nums, low, high);
            quickSortOne(nums, 0, pos - 1);
            quickSortOne(nums, pos + 1, high);
        }
    }

    private static int quickSortOne(int[] nums, int low, int high) {
    
    
        int key = nums[low];
        while (low < high) {
    
    
            while (low < high && nums[high] >= key) {
    
    
                high --;
            }
            nums[low] = nums[high];
            while (low < high && nums[low] < key) {
    
    
                low ++;
            }
            nums[high] = nums[low];
        }
        nums[low] = key;
        return low;
    }

    /** 测试。 */
    public static void main(String[] args) {
    
    
        int[] nums = {
    
    3, 9, 1, 0, 4, 6, 7, 5, 8, 2};
        int[] result = {
    
    };

        // 冒泡排序
        result = nums.clone();
        bubbleSort(result);
        System.out.println(Arrays.toString(result));

        //  快速排序
        result = nums.clone();
        quickSort(result);
        System.out.println(Arrays.toString(result));
    }
}

4. Merge class sorting

package com.algorithm.order.merge;

import java.util.Arrays;

/**
 * 归并类排序。
 *
 * 思想:首先将原始无序序列划分为两个子序列,然后分别对每个子序列递归地进行排序,然后再将有序子序列合并。
 *      二路归并排序
 *      自然归并排序
 */
public class MergeSort {
    
    

    /** 二路归并排序。 */
    public static void twoWayMerge(int[] nums) {
    
    
        System.out.println("two way merge sort: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        twoWayMergeDivide(nums, 0, nums.length - 1);
    }

    private static void twoWayMergeDivide(int[] nums, int low, int high) {
    
    
        if (low < high) {
    
    
            int middle = (low + high) / 2;
            twoWayMergeDivide(nums, low, middle);
            twoWayMergeDivide(nums, middle + 1, high);
            twoWayMergeConquer(nums, low, middle, high);
        }
    }

    private static void twoWayMergeConquer(int[] nums, int low, int middle, int high) {
    
    
        int i = low;  // 左半部有序序列的起始位置
        int j = middle + 1;  // 右半部有序序列的起始位置
        int index = low;
        int[] tmp = Arrays.copyOf(nums, nums.length);
        while (i <= middle && j <= high) {
    
    
            nums[index++] = tmp[i] <= tmp[j] ? tmp[i++] : tmp[j++];
        }
        while (i <= middle) {
    
    
            nums[index++] = tmp[i++];
        }
        while (j <= high) {
    
    
            nums[index++] = tmp[j++];
        }
    }

    /** 自然归并排序。 */
    public static void nativeMerge(int[] nums) {
    
    
        System.out.println("two way merge sort: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        int i = 0, sum = 0, low = 0, mid = 0, high = 0;
        int len = nums.length;
        while (true) {
    
    
            i = 0;
            sum = 1;
            while (i < len - 1) {
    
    
                low = i;
                while (i < len - 1 && nums[i] < nums[i+1]) {
    
    
                    i++;
                }
                mid = i++;
                while (i < len - 1 && nums[i] < nums[i+1]) {
    
    
                    i++;
                }
                high = i++;
                if (i <= len) {
    
    
                    merge(nums, low, mid, high);
                    sum ++;
                }
            }
            if (sum == 1) {
    
    
                break;
            }
        }
    }

    private static void merge(int[] nums, int low, int mid, int high) {
    
    
        int i = low, j = mid+1, p = low, q = 0;
        int[] tmp = Arrays.copyOf(nums, nums.length);
        while (i <= mid && j <= high) {
    
    
            nums[p++] = tmp[i] <= tmp[j] ? tmp[i++] : tmp[j++];
        }
        int tmpHighIndex = 0;
        if (i > mid) {
    
    
            q = j;
            tmpHighIndex = high;
        } else {
    
    
            q = i;
            tmpHighIndex = mid;
        }
        for (; q <= tmpHighIndex; q++) {
    
    
            nums[p++] = tmp[q];
        }
    }

    /** 测试。 */
    public static void main(String[] args) {
    
    
        int[] nums = {
    
    3, 9, 1, 0, 4, 6, 7, 5, 2, 8};
        int[] result = {
    
    };

        // 二路归并排序
        result = nums.clone();
        twoWayMerge(result);
        System.out.println(Arrays.toString(result));

        //  自然归并排序
        result = nums.clone();
        nativeMerge(result);
        System.out.println(Arrays.toString(result));
    }
}

5. Allocation class sorting

package com.algorithm.order.distribution;

import java.util.*;

/**
 * 分配类排序。
 *
 * 思想:利用分配和收集来完成排序,不需要进行关键字比较。
 *
 *      桶排序
 *      基数排序
 */
public class DistributeSort {
    
    

    /** 桶排序。 */
    public static void bucketSort(int[] nums) {
    
    
        System.out.println("two way merge sort: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        ArrayList<LinkedList<Integer>> buckets = new ArrayList<>();
        int max = nums[0];
        for (int i = 0; i < nums.length; i++) {
    
    
            max = Math.max(nums[i], max);
        }
        for (int i = 0; i <= max; i++) {
    
    
            buckets.add(new LinkedList<>());
        }
        for (int i = 0; i < nums.length; i++) {
    
    
            int item = nums[i];
            insertBucket(buckets.get(item), item);
        }
        for (int i = 0, j = 0; i <= max; i++) {
    
    
            List<Integer> list = buckets.get(i);
            if (list != null) {
    
    
                ListIterator<Integer> iterator = list.listIterator();
                while (iterator.hasNext()) {
    
    
                    nums[j++] = iterator.next();
                }
            }
        }
    }

    private static void insertBucket(List<Integer> bucket, int num) {
    
    
        ListIterator<Integer> iterator = bucket.listIterator();
        boolean flag = false;
        while (iterator.hasNext()) {
    
    
            if (num <= iterator.next()) {
    
    
                iterator.previous();
                iterator.add(num);
                flag = true;
                break;
            }
        }
        if (!flag) {
    
    
            bucket.add(num);
        }
    }

    /** 链式基数排序。 */
    public static void radixSort(int[] nums) {
    
    
        System.out.println("radix sort: " + Arrays.toString(nums));
        if (nums == null || nums.length <= 1) {
    
    
            return;
        }
        ArrayList<LinkedList<Integer>> buckets = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
    
    
            buckets.add(new LinkedList<>());
        }
        int maxLen = 0;
        for (int i = 0; i < nums.length; i++) {
    
    
            maxLen = Math.max(String.valueOf(nums[i]).length(), maxLen);
        }
        for (int i = 0; i < maxLen; i++ ) {
    
    
            // 分配
            for (int j = 0; j < nums.length; j++) {
    
    
                int num = (nums[j] % (int) Math.pow(10, i+1)) / (int) Math.pow(10, i);
                insertBucket(buckets.get(num), nums[j]);
            }
            // 收集
            for (int k = 0, j = 0; k < 10; k++) {
    
    
                List<Integer> list = buckets.get(k);
                if (list != null) {
    
    
                    ListIterator<Integer> iterator = list.listIterator();
                    while (iterator.hasNext()) {
    
    
                        nums[j++] = iterator.next();
                        iterator.remove();
                    }
                }
            }
        }
    }


    /** 测试。 */
    public static void main(String[] args) {
    
    
        int[] nums = {
    
    3, 9, 1, 0, 4, 6, 7, 5, 2, 8};
        int[] result = {
    
    };

        // 桶排序排序
        result = nums.clone();
        bucketSort(result);
        System.out.println(Arrays.toString(result));

        // 链式基数排序
        result = nums.clone();
        radixSort(result);
        System.out.println(Arrays.toString(result));

        nums = new int[] {
    
     345, 92, 1, 0, 2224, 46, 37, 45, 12, 8444};

        // 桶排序排序
        result = nums.clone();
        bucketSort(result);
        System.out.println(Arrays.toString(result));

        // 链式基数排序
        result = nums.clone();
        radixSort(result);
        System.out.println(Arrays.toString(result));
    }
}

Guess you like

Origin blog.csdn.net/weixin_39651041/article/details/119512775