Đưa giá trị nhỏ về bên trái
Đoạn mã duyệt mọi cặp chỉ số `i < j`. Nếu `a[i] > a[j]`, nó đổi chỗ hai giá trị. Sau khi xét hết các `j > i`, vị trí `i` giữ giá trị nhỏ nhất trong phần dãy đang xét; tiếp tục với `i+1`. Kết quả là dãy **không giảm**, kể cả khi có phần tử bằng nhau.
Mã có thể đổi chỗ nhiều lần trong một lượt `i`, vì vậy không gọi nó là đúng cùng cách cài đặt sắp xếp chọn của bài trước, vốn tìm vị trí nhỏ nhất rồi mới đổi chỗ một lần.
Đầu ra và số lần so sánh
```python
def sap_theo_cap_va_dem(a):
so_sanh = 0
for i in range(len(a) - 1):
for j in range(i + 1, len(a)):
so_sanh += 1
if a[i] > a[j]:
a[i], a[j] = a[j], a[i]
return so_sanh
a = [3, 1, 2]
print(sap_theo_cap_va_dem(a), a)
```
Kết quả là `3 [1, 2, 3]`. Số cặp được xét là `(n−1)+(n−2)+…+1 = n(n−1)/2`, nên bậc thời gian `O(n²)`. Nếu dãy đã tăng sẵn, vẫn xét từng cặp nhưng không đổi chỗ; chi phí đổi chỗ vì thế không cố định cho mọi dữ liệu.
Bài luyện
Với `a = [3, 1, 2]`, sau `sap_theo_cap_va_dem(a)` thì a là gì?
Có các cặp sai thứ tự nên sẽ đổi.
Lượt i=0 đưa 1 về đầu, lượt i=1 đưa 2 về vị trí giữa.
Mã sắp theo chiều tăng.
Cặp 3 và 2 còn được xét.
Lời giải
Với i=0, đổi 3 với 1 để được [1,3,2]; cặp chỉ số 0 và 2 không cần đổi. Với i=1, đổi 3 với 2 được [1,2,3].
Bài luyện
Mã trong bài xét bao nhiêu cặp chỉ số khi dãy có 4 phần tử?
Đó chỉ là số cặp ở lượt i=0.
Không phải tổng.
3+2+1=6 cặp i<j.
Mã không xét cặp theo cả hai chiều.
Lời giải
Các lượt i=0,1,2 xét 3,2,1 cặp; cộng được 6.
Bài luyện
Điểm khác của mã này so với sắp xếp chọn tìm vị trí nhỏ nhất rồi đổi một lần là gì?
Mã có hai vòng lặp.
Mỗi lần gặp a[j] nhỏ hơn a[i], mã đổi ngay.
Dãy bất kì vẫn xử lí được.
Điều kiện a[i] > a[j] là phép so sánh.
Lời giải
Trong cùng lượt i, một giá trị nhỏ hơn mới có thể xuất hiện nhiều lần; mã đổi ngay mỗi lần gặp, còn sắp chọn chuẩn chỉ đổi sau khi tìm xong vị trí nhỏ nhất.
Đang học