Selection sort (sắp xếp chọn)
Cập nhật lần cuối
Selection sort (sắp xếp chọn) chia mảng thành vùng đã sắp xếp ở bên trái và vùng chưa sắp xếp ở bên phải. Ở mỗi lượt, thuật toán quét vùng chưa sắp xếp để tìm phần tử nhỏ nhất, rồi đổi nó vào vị trí chưa sắp xếp đầu tiên, nhờ đó vùng đã sắp xếp lớn thêm một ô. Nhấn Phát ở trên để xem quá trình quét và đổi chỗ, hoặc chạy từng bước qua từng lần so sánh.
Selection sort luôn thực hiện cùng một số lần so sánh bất kể dữ liệu đầu vào, nhưng chỉ đổi chỗ tối đa n-1 lần, ít hơn nhiều so với bubble sort, điều này có thể quan trọng khi thao tác ghi tốn kém.
Độ phức tạp thời gian và không gian
| Trường hợp | Độ phức tạp | Ghi chú |
|---|---|---|
| Tốt nhất | O(n²) | Vẫn phải so sánh dù đã sắp xếp |
| Trung bình | O(n²) | Thứ tự ngẫu nhiên |
| Xấu nhất | O(n²) | Sắp xếp ngược |
| Không gian | O(1) | Sắp xếp tại chỗ |
| Ổn định | Không | Đổi chỗ có thể đảo thứ tự các phần tử bằng nhau |
Từng bước
| Bước | Điều gì xảy ra |
|---|---|
| 1 | Coi cả mảng là chưa sắp xếp. |
| 2 | Quét vùng chưa sắp xếp để tìm phần tử nhỏ nhất. |
| 3 | Đổi phần tử nhỏ nhất đó vào vị trí chưa sắp xếp đầu tiên. |
| 4 | Dịch ranh giới sang phải một bước (ô đó giờ đã được sắp xếp). |
| 5 | Lặp lại cho đến khi chỉ còn một phần tử chưa sắp xếp. |
Ví dụ minh họa
Sắp xếp [5, 2, 4, 1]:
| Lượt | Mảng | Thao tác |
|---|---|---|
| Bắt đầu | [5, 2, 4, 1] | Cả mảng chưa được sắp xếp. |
| 1 | [1, 2, 4, 5] | Quét [5, 2, 4, 1], nhỏ nhất là 1 ở chỉ số 3; đổi nó với chỉ số 0. |
| 2 | [1, 2, 4, 5] | Quét [2, 4, 5], nhỏ nhất là 2, đã ở chỉ số 1; đổi với chính nó. |
| 3 | [1, 2, 4, 5] | Quét [4, 5], nhỏ nhất là 4, đã ở chỉ số 2; không cần di chuyển. |
| Xong | [1, 2, 4, 5] | Chỉ còn 5, nên nó đã ở đúng chỗ. |
Khi nào nên dùng selection sort
| Nên dùng khi | Tránh dùng khi |
|---|---|
Thao tác ghi tốn kém: thuật toán đổi chỗ tối đa n-1 lần. | Mảng lớn: O(n²) lần so sánh chiếm phần lớn thời gian. |
| Bạn cần một thuật toán sắp xếp tại chỗ đơn giản, dễ cài đặt. | Bạn cần sắp xếp ổn định, giữ nguyên thứ tự các khóa bằng nhau. |
Bộ nhớ hạn hẹp: thuật toán chỉ dùng thêm O(1) bộ nhớ. | Dữ liệu gần như đã sắp xếp: nó không thể kết thúc sớm như insertion sort. |
| Tập dữ liệu rất nhỏ và hiệu năng dễ đoán là điều quan trọng. | Thông lượng quan trọng: các thuật toán O(n log n) như quicksort nhanh hơn nhiều. |
Code Selection Sort
Một cách cài đặt Selection Sort gọn gàng, chạy được ngay bằng Python, JavaScript, Java, C++, C, Pseudocode. Chọn một ngôn ngữ, sao chép code hoặc mở sẵn trong Coddy Playground.
Code Selection Sort bằng Python
1def selection_sort(a):2 n = len(a)3 for i in range(n - 1):4 # Find the smallest element in the unsorted tail5 min_idx = i6 for j in range(i + 1, n):7 if a[j] < a[min_idx]:8 min_idx = j9 a[i], a[min_idx] = a[min_idx], a[i]10 return a11
12
13nums = [64, 25, 12, 22, 11]14print("Before:", nums)15selection_sort(nums)16print("After: ", nums)Code Selection Sort bằng JavaScript
1function selectionSort(a) {2 for (let i = 0; i < a.length - 1; i++) {3 let min = i;4 // Find the smallest element in the unsorted tail5 for (let j = i + 1; j < a.length; j++) {6 if (a[j] < a[min]) min = j;7 }8 if (min !== i) [a[i], a[min]] = [a[min], a[i]];9 }10 return a;11}12
13const data = [5, 2, 9, 1, 7, 3];14console.log("Before:", data);15console.log("Sorted:", selectionSort([...data]));Code Selection Sort bằng Java
1import java.util.Arrays;2
3public class Main {4 static void selectionSort(int[] arr) {5 for (int i = 0; i < arr.length - 1; i++) {6 int minIndex = i;7 // Find the smallest value in the unsorted part8 for (int j = i + 1; j < arr.length; j++) {9 if (arr[j] < arr[minIndex]) minIndex = j;10 }11 int tmp = arr[i];12 arr[i] = arr[minIndex];13 arr[minIndex] = tmp;14 }15 }16
17 public static void main(String[] args) {18 int[] arr = {29, 10, 14, 37, 13, 5};19 System.out.println("Before: " + Arrays.toString(arr));20 selectionSort(arr);21 System.out.println("After: " + Arrays.toString(arr));22 }23}Code Selection Sort bằng C++
1#include <iostream>2#include <utility>3#include <vector>4
5void printVec(const std::vector<int>& a) {6 for (int x : a) std::cout << x << " ";7 std::cout << "\n";8}9
10void selectionSort(std::vector<int>& a) {11 for (size_t i = 0; i + 1 < a.size(); ++i) {12 // Find the smallest element in the unsorted suffix13 size_t minIdx = i;14 for (size_t j = i + 1; j < a.size(); ++j) {15 if (a[j] < a[minIdx]) minIdx = j;16 }17 std::swap(a[i], a[minIdx]);18 }19}20
21int main() {22 std::vector<int> data = {29, 10, 14, 37, 13, 5};23 std::cout << "Before: ";24 printVec(data);25 selectionSort(data);26 std::cout << "After: ";27 printVec(data);28 return 0;29}Code Selection Sort bằng C
1#include <stdio.h>2
3void printArr(const int a[], int n) {4 for (int i = 0; i < n; i++) printf("%d ", a[i]);5 printf("\n");6}7
8void selectionSort(int a[], int n) {9 for (int i = 0; i < n - 1; i++) {10 // Find the smallest element in the unsorted suffix11 int minIdx = i;12 for (int j = i + 1; j < n; j++) {13 if (a[j] < a[minIdx]) minIdx = j;14 }15 int tmp = a[i];16 a[i] = a[minIdx];17 a[minIdx] = tmp;18 }19}20
21int main(void) {22 int data[] = {29, 10, 14, 37, 13, 5};23 int n = sizeof(data) / sizeof(data[0]);24 printf("Before: ");25 printArr(data, n);26 selectionSort(data, n);27 printf("After: ");28 printArr(data, n);29 return 0;30}Code Selection Sort bằng Pseudocode
1DECLARE nums : ARRAY[1:7] OF INTEGER2DECLARE n : INTEGER3n ← 74nums[1] ← 75nums[2] ← 36nums[3] ← 97nums[4] ← 18nums[5] ← 59nums[6] ← 810nums[7] ← 211DECLARE i : INTEGER12DECLARE j : INTEGER13DECLARE minIndex : INTEGER14DECLARE temp : INTEGER15
16// Select the smallest remaining value and swap it into place17FOR i ← 1 TO n - 118 minIndex ← i19 FOR j ← i + 1 TO n20 IF nums[j] < nums[minIndex] THEN21 minIndex ← j22 ENDIF23 NEXT j24 IF minIndex <> i THEN25 temp ← nums[i]26 nums[i] ← nums[minIndex]27 nums[minIndex] ← temp28 ENDIF29NEXT i30
31FOR i ← 1 TO n32 OUTPUT nums[i]33NEXT iCâu hỏi thường gặp về selection sort
Độ phức tạp thời gian của selection sort là bao nhiêu?
O(n²) trong mọi trường hợp, tốt nhất, trung bình và xấu nhất, vì nó luôn quét toàn bộ vùng chưa sắp xếp để tìm mỗi phần tử nhỏ nhất. Thuật toán dùng thêm O(1) bộ nhớ.Selection sort có ổn định không?
Phiên bản tại chỗ tiêu chuẩn không ổn định, vì đổi một phần tử nhỏ nhất ở xa vào vị trí có thể đẩy một phần tử bằng nó vượt qua phần tử khác. Có biến thể ổn định nhưng phải dời phần tử thay vì đổi chỗ.
Khi nào selection sort hữu ích?
n-1 lần, mức thấp nhất có thể với một thuật toán sắp xếp so sánh có di chuyển phần tử.Selection sort khác bubble sort như thế nào?
O(n²), nhưng selection sort đổi chỗ tối đa n-1 lần còn bubble sort có thể đổi chỗ tới O(n²) lần. Bubble sort còn phát hiện được mảng đã sắp xếp và dừng sớm, trong khi selection sort luôn chạy đủ số lượt.Nên dùng selection sort hay insertion sort?
O(n) với dữ liệu gần như đã sắp xếp và trung bình nhanh hơn. Chỉ chọn selection sort khi ưu tiên hàng đầu là giảm số lần ghi, vì nó bảo đảm đổi chỗ tối đa n-1 lần.Tại sao selection sort luôn chạy O(n²) kể cả với mảng đã sắp xếp?
O(n²), khác với insertion sort hay bubble sort vốn có thể dừng sớm.