SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT Một danh sách có thứ tự danh sách được sắp là một danh sách mà các phần tử của nó được sắp xếp theo một thứ tự nào đó dựa trên một trường khoá.. SẮ
Trang 21 Nguyeãn Thò Hoàng Nhi
MSSV:K30-101-066
2 Traàn Minh Phöông
MSSV:K30-101-074
LỚP:3/B
Trang 3SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT
Một danh sách có thứ tự (danh sách được sắp) là một danh sách mà các phần tử của nó được sắp xếp theo một thứ tự nào đó dựa trên một trường khoá
Ví dụ :
Danh sách các phần tử số có thứ tự tăng là danh sách mà với mọi cặp phần tử X, Y ta luôn có X < = Y nếu X xuất hiện trước Y trong danh sách
Chú ý : danh sách có 1 hoặc không có phần tử nào được xem là một danh sách được sắp
Trang 4SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT
Các cách tiếp cận:
Trang 5SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT
Khi kích thước của trường Info lớn, việc hoán vị giá trị của hai phân tử sẽ chiếm chi phí đáng kể
Không tận dụng được các ưu điểm của xâu!
Trang 6THUẬT TOÁN CHỌN TRỰC TIẾP TRÊN XÂU
Trang 7THAO TÁC TRÊN VÙNG INFO
void ListSelectionSort (LIST &l)
q = ppNext;
min = p;
while ( q != NULL ) {
Trang 8THAO TÁC TRÊN VÙNG NEXT
Phương án 2:
Do các nhược điểm của các phương pháp sắp xếp theo phương án
1, khi dữ liệu lưu tại mỗi phần tử trên xâu có kích thước lớn ta thường dùng một cách tiếp cận khác :
+ Thay vì hoán đổi giá trị, ta sẽ tìm cách thay đổi trình tự móc nối của các phần tử sao cho tạo lập nên được thứ tự mong muốn chỉ thao tác trên các móc nối (pNext)
+ Kích thước của trường pNext:
– Không phụ thuộc vào bản chất dữ liệu lưu trong xâu – Bằng kích thước 1 con trỏ (2 hoặc 4 byte trong môi trường 16 bit, 4 hoặc 8 byte trong môi trường 32 bit…)
+ Thao tác trên các móc nối thường phức tạp hơn thao tác trực tiếp trên dữ liệu
Cần cân nhắc khi chọn cách tiếp cận: Nếu d liệu không quá lớn ữ liệu không quá lớn thì nên chọn phương án 1 hoặc một thuật toán hiệu quả nào đó
Trang 9THAO TÁC TRÊN VÙNG NEXT
Một trong những cách thay đổi móc nối đơn giản nhất là tạo một danh sách mới là danh sách có thứ tự gồm các phần tử trích từ danh sách cũ
Giả sử danh sách mới sẽ được quản lý bằng con trỏ đầu xâu Result, ta có thuật toán chọn trực tiếp c a phương án 2 như sau: ủa phương án 2 như sau:
– B1: Khởi tạo danh sách mới Result là rỗng;
– B2: Tìm trong danh sách cũ l phần tử nhỏ nhất – min;
– B3: Tách min khỏi danh sách cũ;
– B4: Chèn min vào cuối danh sách Result;
– B5: Lặp lại bước 2 khi chưa hết danh sách cũ;
Trang 10THAO TÁC TRÊN VÙNG NEXT
Trang 11THAO TÁC TRÊN VÙNG NEXT
Trang 12THAO TÁC TRÊN VÙNG NEXT
pTail2
Trang 13THAO TÁC TRÊN VÙNG NEXT
13
Trang 14THAO TÁC TRÊN VÙNG NEXT
16 pHead 1
Trang 15THAO TÁC TRÊN VÙNG NEXT
Trang 16THAO TÁC TRÊN VÙNG NEXT
NODE * FindMinprev (LIST &l1) // Tìm phần tử đứng trước min trong danh sách {
NODE *min ; // chỉ đến phần tử có giá trị nhỏ nhất trong xâu
Trang 17THAO TÁC TRÊN VÙNG NEXT
void ListSelectionSort2 (LIST &l1)
{
NODE *min, *minprev;
init ( lRes ); // khởi tạo danh sách mới
while(l1.pHead != NULL)
{
minprev = FindMinprev (l1);
min = PickAfter (l1, minprev);// Lấy phần tử min
AddTail (lRes, min);// Chèn min vào cuối danh sách l2 }
l1 = lRes;
}
Trang 18THUẬT TOÁN QUICK SORT
Trang 19THUẬT TOÁN QUICK SORT
Bước 1: Nếu DS có ít hơn 2 phần tử thì dừng.
Bước 2:
Bước 2: Chọn X là phần tử đầu danh sách làm phần
tử cầm canh Loại X ra khỏi danh sách
tử cầm canh Loại X ra khỏi danh sách.
Bước 3:
Bước 3: Tách DS ra làm DS1 (gồm phần tử X) và
DS2 (gồm các phần tử >X).
Bước 4:
Bước 4: Nếu DS1!=NULL thì Quick sort (DS1).
Bước 5:
Bước 5: Nếu DS2!=NULL thì Quick sort (DS2) .
Bước 6: Nối DS1 – X – DS2 ta có DS đã được sắp xếp.
Trang 211 5
3
Trang 22X
2
9 4
Trang 23X
2
9 4
Trang 24X
2
9 4
Trang 25X
2
9 4
Trang 26X
2
9 4
Trang 27X
2
9 4
Trang 30Nối Ds1 – X – Ds2 và đưa kết quả vào pHead
pHead
9 5
4
3 2
1
Trang 31• Quick sort trên DS đơn đơn giản hơn phiên bản của nó trên mảng một chiều.
• Khi dùng quick sort sắp xếp một DS đơn, chỉ có một chọn lựa phần tử cầm canh duy nhất hợp lý là phần tử đầu DS Chọn bất kỳ phần tử nào
khác cũng làm tăng chi phí một cách không cần thiết do cấu trúc tự nhiên của DS đó.
Nhận xét:
Trang 32void Init (List &l) // Khởi tạo DS rỗng
p = l.pHead;
l.pHead = l.pHead->pNext;
p->pNext = NULL;
if(l.pHead == NULL) l.pTail = NULL;
} return p;
}
Trang 33void Noi_2_ds (List &ds, List &ds1)
Trang 34void Quicksort_ds (List &ds)
Trang 35THUẬT TOÁN MERGE SORT
Trang 36THUẬT TOÁN MERGE SORT
Bước 1: Nếu DS có ít hơn 2 phần tử thì dừng.
Bước 5: Trộn DS1 và DS2 đã được sắp xếp lại thì
ta có DS đã được sắp xếp.
Trang 37Sắp xếp dãy số sau theo thứ tự tăng dần: 3 5 4 1 9 2
VÍ DỤ
pHead
pTail
2 9
1 4
5 3
Trang 381 4
5 3
5
Trang 399 1
Trang 409 5
3 1
pHead
Ds1
Trang 41Trộn Ds1 và Ds2 lại ta có Ds đã được sắp xếp theo Merge sort
9 5
4 3
2 1
Trang 42• Merge sort trên DS đơn đơn giản hơn phiên bản trên mảng một chiều
• Khi dùng Merge sort sắp xếp một DS đơn,
không cần dùng thêm vùng nhớ phụ như khi cài đặt trên mảng một chiều
• Thủ tục Merge trên DS đơn không phức tạp như trên mảng vì chỉ phải trộn hai DS đã có thứ tự, trong khi trên mảng phải trộn hai mảng bất kỳ.
Nhận xét:
Trang 43void MergeSort_ds (List & ds)
}
SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT
Trang 44//Phân phối DS vào DS1 Và DS2
void Distribute_ds (List &ds,List &ds1, List &ds2) {
Trang 45void Merge_ds (List& ds, List& ds1, List &ds2)
Trang 47SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT
Thuật toán Radix Sort
k = 0; // k cho biết chữ số dùng để phân loại hiện hành, k = 0: hàng đơn vị,
k = 1: hàng chục; …
B2.1 : Khởi tạo các danh sách (lô) rỗng B0, B1,…, B9;
B2.2 : Trong khi l khác rỗng thực hiện :
p = pickHead ( LIST & l ); // trích phần tử đầu danh sách
Đặt phần tử p vào cuối lô B[i ] với i là chữ số thứ k của
Trang 48SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT
Trang 50Phân loại theo
hàng đơn vị
Trang 51pTail 4 pTail 5 pTail 6 pTail 7 pTail 8 pTail 9
Trang 52pTail 4 pTail 5 pTail 6 pTail 7 pTail 8 pTail 9
Trang 53pTail 4 pTail 5 pTail 6 pTail 7 pTail 8 pTail 9
Trang 54pTail 4 pTail 5 pTail 6 pTail 7 pTail 8 pTail 9
Trang 55pTail 4 pTail 5 pTail 6 pTail 7 pTail 8
Trang 57pTail 1
41
Trang 62Phân loại theo
hàng chục
Trang 64pTail 4 pTail 5
pTail 7 pTail 8
Trang 65pTail 4 pTail 5
pTail 7 pTail 8
Trang 66SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT
void ListRadixSort ( LIST &l, int m )
p = pickHead ( l ); // trích phần tử đầu danh sách
i = GetDigit ( pInfo, k ) ; // chữ số thứ k của pInfo
AddTail ( B[i], p ); // Đặt phần tử p vào cuối lô B[i] }
Trang 67SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT
for ( j = 0; j < 10; j++ )
AppendList ( l, B[ j ] );// Nối B[ j ] vào cuối l
}
}
Trang 68SẮP XẾP THỨ TỰ TRÊN DANH SÁCH LIÊN KẾT
Trong đó các hàm AppendList và GetDigit được viết như sau :
void AppendList ( LIST &l, LIST l1 )