【共通ソートアルゴリズム】

上に書く

アルゴリズムの 1 つだけを使用したい場合は、

対応する並べ替えアルゴリズムだけが必要な場合は、並べ替えクラスごとに次の 3 つの場所を削除できます。

  • SortTest を拡張します
  • メインメソッド
  • @オーバーライド

たとえば、バブルソートの場合、下図で選択したボックスを削除して単独で使用します。
ここに画像の説明を挿入

クラス図

すべての並べ替えアルゴリズムは SortTest を継承します。SortTest は主にアルゴリズムの並べ替えの効果 (正しい率はどれくらいか) をテストするために使用されます。
ここに画像の説明を挿入

ツールクラス NumberArrayUtil

ツールクラスを準備する产生无序的数组

  • createNumberArray(int count): 長さ count の配列を生成します。
  • createNumberArrays(): 一定量の順序付けされていない配列を生成します
public class NumberArrayUtil {
    
    
    private static final Random RANDOM = new Random();
    /**
     * 数组的长度包含0 ~ MAX_VAL
     */
    private static final int MAX_VAL = 10;

    /**
     * 除了长度为0 ~ MAX_VAL长度的数组之外,再产生多少个数组
     */
    private static final int RANDOM_ARRAY_COUNT = 20;
    /**
     * 除了长度为0 ~ MAX_VAL长度的数组之外,再产生的数组最大长度
     */
    private static final int RANDOM_ARRAY_MAX_LENGTH = 100;

    /**
     * 产生指定长度的数组
     * @param count
     * @return
     */
    public static int[] createNumberArray(int count){
    
    
        int[] res = new int[count];
        for (int i = 0; i < res.length; i++) {
    
    
            res[i] =  RANDOM.nextInt();
        }

        return res;
    }

    /**
     * 产生一定量的随机长度的数组
     * @return
     */
    public static List<int[]> createNumberArrays(){
    
    
        List<int[]> res = new ArrayList<>();

        for (int i = 0; i < MAX_VAL; i++) {
    
    
            res.add(createNumberArray(i));
        }

        for (int i = 0; i < RANDOM_ARRAY_COUNT; i++) {
    
    
            res.add(createNumberArray(RANDOM.nextInt(RANDOM_ARRAY_MAX_LENGTH)));
        }

        return res;
    }

    /**
     * 判断两个数组的值是否相同
     * @param arr1
     * @param arr2
     * @return
     */
    public static boolean isSameArray(int[] arr1, int[] arr2){
    
    
        if (arr1.length != arr2.length){
    
    
            return false;
        }

        for (int i = 0; i < arr1.length; i++) {
    
    
            if (arr1[i] != arr2[i]){
    
    
                return false;
            }
        }

        return true;
    }
}

並べ替えをテストするための親クラス SortTest

作成したアルゴリズムがソートを完了できるかどうかをすばやくテストするための抽象クラスを準備します。

  • test(): 実装した並べ替えの結果をテストするためのサブクラス呼び出し
  • sort メソッドは抽象メソッドであるため、サブクラスを書き換えてから、テスト メソッドを呼び出してテストを完了する必要があります。
  • スワップは2つのインデックスの値を交換する方法で、ソートでよく使用されます
public abstract class SortTest {
    
    
    /**
     * 排序方法
     *
     * @param nums
     * @return
     */
    public abstract int[] sort(int[] nums);

    /**
     * 用于检验排序结果
     */
    public void test() {
    
    
        List<int[]> numberArrays = NumberArrayUtil.createNumberArrays();
        int[] sort;
        int errorCount = 0;
        for (int[] numberArray : numberArrays) {
    
    
            int[] copy = Arrays.copyOf(numberArray, numberArray.length);
            sort = sort(Arrays.copyOf(numberArray, numberArray.length));
            Arrays.sort(copy);
            if (!NumberArrayUtil.isSameArray(sort, copy)) {
    
    
                System.out.println(Arrays.toString(numberArray) + "排序出错,排序后的结果:\n" + Arrays.toString(sort));
                System.out.println();
                errorCount++;
            }
        }
        
        System.out.println("测试完成!共计:" + numberArrays.size() + "个,出错个数:" + errorCount);
    }

    /**
     * 交换
     *
     * @param nums
     * @param i
     * @param j
     */
    public void swap(int[] nums, int i, int j) {
    
    
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

バブルソート

public class BubbleSort extends SortTest{
    
    
    public static void main(String[] args) {
    
    
        new BubbleSort().test();
    }

    /**
     * 排序方法
     *
     * @param nums
     * @return
     */
    @Override
    public int[] sort(int[] nums) {
    
    
        //排序次数
        boolean isSwap;
        for (int i = 0; i < nums.length - 1; i++) {
    
    
            //选出第i大的
            isSwap = false;
            for (int j = 0; j < nums.length - 1 - i; j++) {
    
    
                if (nums[j] > nums[j + 1]){
    
    
                    swap(nums, j, j + 1);
                    isSwap = true;
                }
            }
            if (!isSwap){
    
    
                break;
            }
        }

        return nums;
    }
}

ヒープソート

public class HeapSort extends SortTest {
    
    
    public static void main(String[] args) {
    
    
        new HeapSort().test();
    }
    /**
     * 排序方法
     *
     * @param nums
     * @return
     */
    @Override
    public int[] sort(int[] nums) {
    
    
        //初始化一个大顶堆
        buildMaxHeap(nums);

        //堆的大小,每次减少一个
        for (int i = nums.length - 1; i > 0; i--) {
    
    
            //和最后面交换
            swap(nums, 0, i);
            //构建堆,长度-1,最后一个放最大的
            heapify(nums, 0, i);
        }

        return nums;
    }

    private void buildMaxHeap(int[] nums) {
    
    
        //从倒数第二层最后一个往前,依次构建堆
        int len = nums.length;
        for (int i = len / 2 - 1; i >= 0; i--) {
    
    
            heapify(nums, i, len);
        }
    }

    /**
     * 构建堆
     *
     * @param nums
     * @param index 起始索引
     * @param len   有效长度
     */
    private void heapify(int[] nums, int index, int len) {
    
    
        if (index >= nums.length){
    
    
            return;
        }

        int left = 2 * index + 1;
        int right = 2 * index + 2;

        //当前节点和其两个子节点,最大值处对应的索引
        int maxIndx = index;

        //是否子节点比当前节点大
        if (left < len && nums[left] > nums[maxIndx]) {
    
    
            maxIndx = left;
        }
        if (right < len && nums[right] > nums[maxIndx]) {
    
    
            maxIndx = right;
        }

        //和子节点交换,并对子节进行重新构建堆
        if (maxIndx != index) {
    
    
            swap(nums, index, maxIndx);
            heapify(nums, maxIndx, len);
        }
    }
}

挿入ソート

public class InsertSort extends SortTest{
    
    
    /**
     * 排序方法
     *
     * @param nums
     * @return
     */
    @Override
    public int[] sort(int[] nums) {
    
    
        //遍历
        for (int i = 1; i < nums.length; i++) {
    
    
            int tmp = nums[i];
            //如果比当前值大,都应该往后移动
            int j = i - 1;
            while (j >= 0 && nums[j] > tmp){
    
    
                nums[j + 1] = nums[j];
                j--;
            }
            nums[j + 1] = tmp;
        }

        return nums;
    }

    public static void main(String[] args) {
    
    
        new InsertSort().test();
    }
}


マージソート

public class MergeSort extends SortTest {
    
    
    public static void main(String[] args) {
    
    
        new MergeSort().test();
    }

    /**
     * 排序方法
     *
     * @param nums
     * @return
     */
    @Override
    public int[] sort(int[] nums) {
    
    
        sort(nums, 0, nums.length - 1);
        return nums;
    }

    private void sort(int[] nums, int left, int right) {
    
    
        //结束:
        if (right <= left) {
    
    
            return;
        }

        int mid = left + (right - left) / 2;
        //分成两个部分,分别排序
        sort(nums, left, mid);
        sort(nums, mid + 1, right);

        //归并
        int[] marge = marge(Arrays.copyOfRange(nums, left, mid + 1), Arrays.copyOfRange(nums, mid + 1, right + 1));
        System.arraycopy(marge, 0, nums, left, marge.length);
    }

    private int[] marge(int[] nums1, int[] nums2) {
    
    
        int[] res = new int[nums1.length + nums2.length];
        //已经添加的个数
        int index = 0;
        //两个指针
        int i = 0, j = 0;

        while (i < nums1.length && j < nums2.length) {
    
    
            //谁小,谁加入;//i或j增加
            if (nums1[i] > nums2[j]) {
    
    
                res[index++] = nums2[j++];
            } else {
    
    
                res[index++] = nums1[i++];
            }
        }
        //如果添加完了就结束
        if (index == res.length) {
    
    
            return res;
        }
        //没添加完,把某个数组剩余的部分拷贝进去
        if (i < nums1.length) {
    
    
            for (; i < nums1.length; i++) {
    
    
                res[index++] = nums1[i];
            }
        } else {
    
    
            for (; j < nums2.length; j++) {
    
    
                res[index++] = nums2[j];
            }
        }

        return res;
    }
}

クイックソート

public class QuickSort extends SortTest{
    
    
    public static void main(String[] args) {
    
    
        new QuickSort().test();
    }

    /**
     * 排序方法
     *
     * @param nums
     * @return
     */
    @Override
    public int[] sort(int[] nums) {
    
    
        sort(nums, 0, nums.length - 1);
        return nums;
    }

    private void sort(int[] nums, int left, int right) {
    
    
        //结束:
        if (left >= right){
    
    
            return;
        }

        //排序
        //基准
        int val = nums[left];
        int i = left, j = right;
        while (i < j){
    
    
            //右边先移动
            while (j > i && nums[j] >= val){
    
    
                j--;
            }
            //换到左边
            nums[i] = nums[j];
            //左边移动
            while (i < j && nums[i] <= val){
    
    
                i++;
            }
            //换到右边
            nums[j] = nums[i];
        }
        nums[i] = val;

        //排左边
        sort(nums, left, i - 1);
        //排右边
        sort(nums, i + 1, right);
    }
}

選択範囲の並べ替え

public class SelectionSort extends SortTest{
    
    

    /**
     * 排序方法
     *
     * @param nums
     * @return
     */
    @Override
    public int[] sort(int[] nums) {
    
    
        //要选n-1次
        for (int i = 0; i < nums.length - 1; i++) {
    
    
            //每次找最小的放前面
            int min = nums[i];
            int index = i;
            for (int j = i + 1; j < nums.length; j++) {
    
    
                if (min > nums[j]){
    
    
                    min = nums[j];
                    index = j;
                }
            }
            //交换
            swap(nums, i, index);
        }

        return nums;
    }

    public static void main(String[] args) {
    
    
        new SelectionSort().test();
    }
}

ヒルソート

public class ShellSort extends SortTest {
    
    
    public static void main(String[] args) {
    
    
        new ShellSort().test();
    }

    /**
     * 排序方法
     *
     * @param nums
     * @return
     */
    @Override
    public int[] sort(int[] nums) {
    
    
        //步长
        int step = nums.length;

        for (int i = step; i > 0; i /= 2) {
    
    
            //以步长为i进行快速排序
            for (int j = 0; j < step; j++) {
    
    
                //对第j组进行排序,步长是i
                sort(nums, j, i);
            }
        }

        return nums;
    }

    /**
     * 希尔排序,对第startIndex组进行排序
     *
     * @param nums
     * @param startIndex 起始索引
     * @param step       步长
     */
    private void sort(int[] nums, int startIndex, int step) {
    
    
        for (int i = startIndex + step; i < nums.length; i += step) {
    
    
            int tmp = nums[i];
            //一直向前找,找到一个比当前值小的值
            int j = i - step;
            while (j >= 0 && nums[j] > tmp) {
    
    
                nums[j + step] = nums[j];
                j -= step;
            }

            //插入在其后面
            nums[j + step] = tmp;
        }
    }
}

おすすめ

転載: blog.csdn.net/m0_55155505/article/details/127095703