Mỗi lượt cố định thêm một vị trí
Với `[6, 5, 4, 2]`, lượt đầu tìm số nhỏ nhất toàn dãy là 2 rồi đổi với 6: `[2, 5, 4, 6]`. Lượt sau chỉ xét đoạn từ chỉ số 1, chọn 4 rồi đổi với 5: `[2, 4, 5, 6]`. Lượt cuối xét `[5, 6]`, 5 đã ở đầu đoạn nên không cần đổi. Sau lượt chỉ số `i`, phần `a[0]` đến `a[i]` đã đứng đúng vị trí cuối cùng của dãy tăng. Không cần chọn riêng phần tử cuối vì sau các lượt trước nó tự ở đúng chỗ.
Lưu chỉ số nhỏ nhất, không chỉ lưu giá trị
```python
def sap_chon_tang(a):
n = len(a)
for i in range(n - 1):
i_nho_nhat = i
for j in range(i + 1, n):
if a[j] < a[i_nho_nhat]:
i_nho_nhat = j
if i_nho_nhat != i:
a[i], a[i_nho_nhat] = a[i_nho_nhat], a[i]
return a
print(sap_chon_tang([6, 5, 4, 2]))
```
Kết quả là `[2, 4, 5, 6]`. Biến `i_nho_nhat` là **chỉ số** của số nhỏ nhất tìm được trong đoạn còn lại, nhờ đó biết đổi ô nào với `a[i]`. Nếu đã ở đúng `i`, nhánh `if` bỏ phép đổi với chính nó. Hàm vẫn duyệt để xác định điều đó; với dãy rỗng hoặc một phần tử, vòng ngoài không chạy. Khi các giá trị trùng nhau, mã vẫn sắp theo giá trị nhưng không hứa giữ thứ tự ban đầu của các bản ghi có cùng giá trị.
Bài luyện
Sắp xếp chọn tăng dãy `[6,5,4,2]`: sau lượt đầu, dãy là gì?
Số nhỏ nhất 2 đổi với số đầu 6.
Đây chỉ là đổi hai số đầu.
Đây là kết quả sau lượt tiếp theo.
Số nhỏ nhất chưa về đầu.
Lời giải
Trong toàn dãy, 2 nhỏ nhất ở chỉ số 3. Đổi a[0] và a[3] được [2,5,4,6].
Bài luyện
Sau lượt với `i=1` của sắp xếp chọn tăng, phần nào đã đứng đúng vị trí cuối cùng?
a[0] đã đúng từ lượt trước.
Hai vị trí đầu đã lần lượt nhận hai số nhỏ nhất.
Phần tử cuối chưa chắc đúng khi còn đoạn giữa.
Có thể vẫn còn phần chưa sắp.
Lời giải
Lượt i=0 cố định số nhỏ nhất ở a[0]; lượt i=1 cố định số nhỏ nhất tiếp theo ở a[1].
Bài luyện
Biến `i_nho_nhat` trong chương trình lưu gì?
Biến lưu vị trí, không phải chính giá trị.
Cần chỉ số để đổi a[i] với đúng ô.
Nó có thể thay đổi khi tìm thấy số nhỏ hơn.
Độ dài lưu ở n.
Lời giải
Ở mỗi lượt i, chương trình đặt i_nho_nhat=i rồi quét j>i; nếu gặp số nhỏ hơn, lưu chỉ số j để đổi vị trí.
Đang học