ソートアルゴリズム(1)-バブリング、挿入、選択

ここに画像の説明を挿入

簡単にするために、すべての例はデフォルトで正の順序であり、正の順序と逆の順序の問題はここでは考慮されていません!

準備ができました

始める前に、ここで次の準備をしました。

  • パワードコンピューター
  • JDK8またはJDK11
  • JUnit5
  • 考え
  • lombok(必須ではありません。これを使用してログを印刷することに慣れています)

抽象インターフェース:

public interface Sort<E> {
    
    
    E[] sort();
}

テストケース:

@Slf4j
class SortTest {
    
    
    Integer[] integers;

    Sort<Integer> sort;

    @BeforeEach
    void setUp() {
    
    
        integers = new Integer[]{
    
    3, 7, 2, 1, 4, 8, 9, 8, 5, 6, 0};
        log.info("排序前: {}", Arrays.toString(integers));
    }

    @AfterEach
    void tearDown() {
    
    
        assertSort(sort.sort());
    }

    @Test
    void bubbleSortTest() {
    
    
        sort = new BubbleSort(integers);
    }

    @Test
    void insertSortTest() {
    
    
        sort = new InsertSort(integers);
    }

    @Test
    void selectSortTest() {
    
    
        sort = new SelectSort(integers);
    }

    private void assertSort(Integer[] sort) {
    
    
        log.info("排序后: {}", Arrays.toString(sort));
        assertAll(
                () -> assertEquals(integers.length, sort.length),
                () -> assertEquals(0, sort[0]),
                () -> assertEquals(9, sort[sort.length - 1]),
                () -> assertEquals(1, sort[1]),
                () -> assertEquals(2, sort[2]),
                () -> assertEquals(3, sort[3]),
                () -> assertEquals(4, sort[4]),
                () -> assertEquals(5, sort[5]),
                () -> assertEquals(6, sort[6]),
                () -> assertEquals(7, sort[7]),
                () -> assertEquals(8, sort[8]),
                () -> assertEquals(8, sort[9])
        );
    }
}

バブルソート

バブルソートについては、すべての説明が薄いです、この魔法のビデオを見てください、あなたは完全に理解するでしょう

https://www.bilibili.com/video/BV1xW411Y7VL

public class BubbleSort implements Sort<Integer> {
    
    

    private final Integer[] elements;

    public BubbleSort(Integer[] elements) {
    
    
        this.elements = elements;
    }

    @Override
    public Integer[] sort() {
    
    
        int length = elements.length;
        for (int i = 0; i < length - 1; i++) {
    
    
            for (int j = 0; j < length - i - 1; j++) {
    
    
                // 当前大于下一位,则互换位置,继续向后比较
                if (elements[j] > elements[j + 1]) {
    
    
                    Integer temp = elements[j];
                    elements[j] = elements[j + 1];
                    elements[j + 1] = temp;
                }
                // 当前小于或等于下一位,从下一位开始往后比较
            }
        }
        return elements;
    }
}

挿入ソート

  1. 挿入ソートは、配列をソートされた領域とソートされていない領域の2つの領域に分割します。
  2. 並べ替えが開始されると、配列の最初の要素はデフォルトで並べ替えられた領域にあります
  3. 並べ替えの各ラウンドで、並べ替えられていない領域の最初の要素が並べ替えられた領域の要素と順番に比較されます。並べ替えられていない要素が現在並べ替えられている要素よりも小さい場合、これが挿入ポイントになります。
    • 挿入点の後の要素が後方にシフトします
    • ソートされていない要素をここに挿入します
  4. それ以外の場合、このソートされていない要素はソートされた領域の最後に挿入されます。つまり、配列は移動されず、ソートされていない領域の次のビットで新しい比較ラウンドが実行されます。
public class InsertSort implements Sort<Integer> {
    
    

    private Integer[] elements;

    public InsertSort(Integer[] elements) {
    
    
        this.elements = elements;
    }

    @Override
    public Integer[] sort() {
    
    
        int sortedLength = 1;
        int unSortedLength = elements.length - 1;

        for (int i = 0; i < unSortedLength; i++) {
    
    
            // 未排序区的第一个元素
            Integer unSort = elements[sortedLength];
            // 与已排序元素比较
            for (int j = 0; j < sortedLength; j++) {
    
    
                // 1. 已排序区:如果unSort比所有的都大,则排在最后一位,直接完成本轮比对即可
                // 2. 已排序区:unSort小于此位数,则排在此位前
                if (unSort < elements[j]) {
    
    
                    rightMoveOnePlace(sortedLength, j, elements);
                    elements[j] = unSort;
                    break;
                }
                // 3. 已排序区:unSort大于此位数,则进行下一位数对比
            }
            sortedLength++;
        }

        return elements;
    }

    /**
     * 将数组从指定位置开始,向右移动1位
     *
     * @param endMoveElementIndex   结束移动的元素数量
     * @param startMoveElementIndex 开始移动的元素位置
     * @param elements                  待操作的数组
     */
    private void rightMoveOnePlace(int endMoveElementIndex, int startMoveElementIndex, Integer[] elements) {
    
    
        for (int k = 0; k < endMoveElementIndex - startMoveElementIndex; k++) {
    
    
            elements[endMoveElementIndex - k] = elements[endMoveElementIndex - k - 1];
        }
    }
}

ソートを選択

  1. 選択ソートもソート領域と非ソート領域に分けられます
  2. 並べ替えを開始すると、並べ替えられていない領域に要素がありません
  3. ソートされていない領域の最初の要素から始めて、後続のすべての要素と順番に比較し、ソートされた領域の最後に最小の要素を配置します
public class SelectSort implements Sort<Integer> {
    
    

    private Integer[] elements;

    public SelectSort(Integer[] elements) {
    
    
        this.elements = elements;
    }

    @Override
    public Integer[] sort() {
    
    
        for (int unSortIndex = 0; unSortIndex < elements.length - 1; unSortIndex++) {
    
    
            int min = elements[unSortIndex];
            int minIndex = unSortIndex;
            for (int j = unSortIndex + 1; j < elements.length; j++) {
    
    
                if (elements[j] < min) {
    
    
                    min = elements[j];
                    minIndex = j;
                }
            }
            // 如果相等,则说明未排序区首位元素已经是最小值,不需要交换位置
            if (minIndex != unSortIndex) {
    
    
                elements[minIndex] = elements[unSortIndex];
                elements[unSortIndex] = min;
            }
        }
        return elements;
    }
}

やっと

これらのソートアルゴリズムの時間計算量はO(n 2)O(n ^ 2)です。O n2

並べ替えプロセスで新しい配列スペースは適用されません。これらはすべて元の配列に基づいて並べ替えられるため、これらはすべてin-situ並べ替えアルゴリズムであり、スペースの複雑さはO(n)O(n)です。O n

次に、マージと高速ソートを見てみましょう

あなたが自分自身に役立つと感じたら、いいねをしてください、これは私の最大の励ましになります~~~

おすすめ

転載: blog.csdn.net/weixin_38403680/article/details/113998077