Hàm thực hiện việc phân phối luân phiên các đường chạy có chiều dài L trên dãy M có N phần tử về thành các dãy Temp1 và Temp2 có tương ứng N1 và N2 phần tử.
Trang 1B15: K2++
B16: IF (J2 > N2) //Đã chép hết các phần tử trong Temp2 Thực hiện B30
B17: Lặp lại B11 //Chép phần run còn lại trong Temp1 về M B18: IF (K1 > L) //Đã chép hết phần run còn lại trong Temp1 về M Lặp lại B4
B19: M[I] = Temp1[J1]
B20: I++
B21: J1++
B22: K1++
B23: IF (J1 > N1) //Đã chép hết các phần tử trong Temp1 Thực hiện B25
B24: Lặp lại B18 //Chép các phần tử còn lại trong Temp2 về M B25: IF (J2>N2)
Thực hiện Bkt B26: M[I] = Temp2[J2]
B27: I++
B28: J2++
B29: Lặp lại B25 //Chép các phần tử còn lại trong Temp1 về M B30: IF (J1>N1)
Thực hiện Bkt B31: M[I] = Temp1[J1]
B32: I++
B33: J1++
B34: Lặp lại B30 Bkt: Kết thúc
- Thuật toán sắp xếp trộn thẳng:
B1: L = 1 //Chiều dài ban đầu của các run B2: IF (L ≥ N) //Dãy chỉ còn 01 run Thực hiện Bkt
B3: Phân_Phối(M, N, Temp1, N1, Temp2, N2, L) B4: Trộn(Temp1, N1, Temp2, N2, M, N, L) B5: L = 2*L
B6: Lặp lại B2 Bkt: Kết thúc
- Cài đặt thuật toán:
Hàm StraightMergeSort có prototype như sau:
void StraightMergeSort(T M[], int N);
Hàm thực hiện việc sắp xếp N phần tử có kiểu dữ liệu T trên mảng M theo thứ tự tăng dựa trên thuật toán sắp trộn trực tiếp Hàm sử dụng các hàm Distribute, Merge có prototype và ý nghĩa như sau:
void Distribute(T M[], int N, T Temp1[], int &N1, T Temp2[], int &N2, int L);
Trang 2Hàm thực hiện việc phân phối luân phiên các đường chạy có chiều dài L trên dãy M có N phần tử về thành các dãy Temp1 và Temp2 có tương ứng N1 và N2 phần tử
void Merge(T Temp1[], int N1, T Temp2[], int N2, T M[], int &N, int L);
Hàm thực hiện việc trộn từng cặp tương ứng các đường chạy với độ dài L trên Temp1, Temp2 về dãy M thành các đường chạy có chiều dài 2*L
Nội dung của các hàm như sau:
void Distribute(T M[], int N, T Temp1[], int &N1, T Temp2[], int &N2, int L) { int I = 0, J1 = 0, J2 = 0;
while (I < N) { for(int K = 0; K<L && I<N; K++, I++, J1++) Temp1[J1] = M[I];
for(K = 0; K<L && I<N; K++, I++, J2++) Temp2[J2] = M[I];
} N1 = J1;
N2 = J2;
return;
} //========================================================
void Merge(T Temp1[], int N1, T Temp2[], int N2, T M[], int &N, int L) { int I = 0, J1 = 0, J2 = 0, K1 = 0, K2 = 0;
while (J1 < N1 && J2 < N2) { while (Temp1[J1] <= Temp2[J2] && J1 < N1 && J2 < N2) { M[I] = Temp1[J1];
I++;
J1++;
if (J1 == N1) { for (; J2 < N2; J2++, I++) M[I] = Temp2[J2];
return;
} K1++;
if (K1 == L) { for (; K2 < L && J2 < N2; K2++, I++, J2++) M[I] = Temp2[J2];
K1 = K2 = 0;
break;
} } while (Temp2[J2] < Temp1[J1] && J1 < N1 && J2 < N2) { M[I] = Temp2[J2];
I++;
J2++;
if (J2 == N2) { for (; J1 < N1; J1++, I++) M[I] = Temp1[J1];
w
Trang 3return;
} K2++;
if (K2 == L) { for (; K1 < L && J1 < N1; K1++, I++, J1++) M[I] = Temp1[J1];
K1 = K2 = 0;
break;
} } } while (J1 < N1) { M[I] = Temp1[J1];
I++;
J1++;
} while (J2 < N2) { M[I] = Temp2[J2];
I++;
J2++;
}
N = N1 + N2;
return;
} //========================================================
void StraightMergeSort(T M[], int N) { int L = 1, N1 = 0, N2 = 0;
T * Temp1 = new T[N];
T * Temp2 = new T[N];
if (Temp1 == NULL || Temp2 == NULL) return;
while (L < N) { Distribute(M, N, Temp1, N1, Temp2, N2, L);
Merge(Temp1, N1, Temp2, N2, M, N, L);
L = 2*L;
} delete Temp1;
delete Temp2;
return;
}
- Ví dụ minh họa thuật toán:
Giả sử ta cần sắp xếp mảng M có 10 phần tử sau (N = 10):
Ta thực hiện các lần phân phối và trộn các phần tử của M như sau:
Lần 1: L = 1
Trang 4Phân phối M thành Temp1, Temp2:
Temp1:N1=5
Temp2:N2=5
Trộn Temp1, Temp2 thành M:
Temp1:N1=5
Temp2:N2=5
Lần 2: L = 2 Phân phối M thành Temp1, Temp2:
Temp1: N1=6
Temp2: N2=4
Trộn Temp1, Temp2 thành M:
Temp1: N1=6
Temp2: N2=4
Lần 3: L = 4
w
Trang 5Phân phối M thành Temp1, Temp2:
Trộn Temp1, Temp2 thành M:
Lần 4: L = 8 Phân phối M thành Temp1, Temp2:
Trộn Temp1, Temp2 thành M:
L = 16 > 10: Kết thúc thuật toán
- Phân tích thuật toán:
+ Trong thuật giải này chúng ta luôn thực hiện log2(N) lần phân phối và trộn các run