Tài liệu này dành cho sinh viên, giáo viên khối ngành công nghệ thông tin tham khảo và có những bài học bổ ích hơn, bổ trợ cho việc tìm kiếm tài liệu, giáo án, giáo trình, bài giảng các môn học khối ngành công nghệ thông tin
Đ Đ ạ ạ i H i H ọ ọ c Sư Ph c Sư Ph ạ ạ m Tp. H m Tp. H ồ ồ Ch Ch í í Minh Minh Chương 2: Tìm kiếm & Sắp xếp C C Ấ Ấ U TR U TR Ú Ú C D C D Ữ Ữ LI LI Ệ Ệ U 1 U 1 2 2 Tìm kiếm & Sắp xếp Mục tiêu: • Giới thiệu một số thuật toán tìm kiếm và sắp xếp nội. • Phân tích, đánh giá độ phức tạp của các giải thuật tìm kiếm, sắp xếp. Nội dung: • Nhu cầu tìm kiếm và sắp xếp dữ liệu trong một hệ thống thông tin. • Các giải thuật tìm kiếm nội. • Các giải thuật sắp xếp nội. 3 3 Các giải thuật tìm kiếm nội • Tìm tuần tự • Tìm nhị phân Tìm kiếm 4 4 Các giải thuật tìm kiếm nội Bài toán: Tìm vò trí xuất hiện của phần tử có giá trò x trên danh sách đặc a •Tập dữ liệu được lưu trữ là dãy số a 1 , a 2 , ,a N int a[N]; •Khoá cần tìm là x int x; 5 5 Tìm kiếm tuần tự • Bước 1: i = Vò trí đầu; • Bước 2: Nếu a[i] = x : Tìm thấy. Dừng, vò trí xuất hiện: i • Bước 3 : i = Vò trí kế(i);// xét tiếp phần tử kế trong mảng • Bước 4: Nếu i >Vò trí cuối: //Hết mảng Không tìm thấy. Dừng. Ngược lại: Lặp lại Bước 2. 6 6 Tìm kiếm tuần tự • Ví dụ: Cho dãy số a 1228516415 • Giá trò cần tìm: 8 • i = 1 7 7 Tìm kiếm tuần tự • i = 2 • i = 3 8 8 T TT Tì ìì ìm kie m kiem kie m kiế áá ám tua m tuam tua m tuầ àà àn t n tn t n tự ựự ự int LinearSearch(int a[], int N, int x) { for (int i=0; (i<N)&&(a[i]!=x ); i++); if (i<N) return i; // a[i] là phần tử có khoá x return -1; // tìm hết mảng nhưng không có x } 9 9 Tìm kiếm tuần tự • Cải tiến cài đặt: dùng phương pháp “đặt lính canh” – Đặt thêm một phần tử có giá trò x vào cuối mảng – Bảo đảm luôn tìm thấy x trong mảng – Sau đó dựa vào vò trí tìm thấy để kết luận. 10 10 Tìm kiếm tuần tự int LinearSearch(int a[], int N, int x) { // mảng gồm N phần tử từ a[0] a[N-1] a[N] = x; // thêm lính canh vào cuối dãy for (int i=0; (a[i]!=x); i++); if (i<N) return i; // a[i] là phần tử có khoá x return -1; // tìm hết mảng nhưng không có x } 11 11 Tìm kiếm tuần tự • Đánh giá giải thuật: • Vậy giải thuật tìm tuần tự có độ phức tạp tính toán cấp n: T(n) = O(n) 12 12 Tìm kiếm tuần tự Nhận xét: – Giải thuật tìm tuyến tính không phụ thuộc vào thứ tự của các phần tử trong danh sách, do vậy đây là phương pháp tổng quát nhất để tìm kiếm trên một danh sách bất kỳ. – Một thuật toán có thể được cài đặt theo nhiều cách khác nhau, kỹ thuật cài đặt ảnh hưởng đến tốc độ thực hiện của thuật toán. 13 13 Tìm kiếm nhò phân • Đối với những dãy đã sắp thứ tự (giả sử thứ tự tăng), các phần tử trong dãy có quan hệ a i -1 ≤ ≤≤ ≤ a i ≤ ≤≤ ≤ a i+1 Nếu x > a i thì x chỉ có thể xuất hiện trong đoạn [a i+1 ,a N ] của dãy Nếu x < a i thì x chỉ có thể xuất hiện trong đoạn [a 1 ,a i-1 ] của dãy 14 14 Tìm kiếm nhò phân • Ý tưởng của giải thuật là tại mỗi bước tiến hành so sánh x với phần tử nằm ở vò trí giữa của dãy tìm kiếm hiện hành, dựa vào kết quả so sánh này để quyết đònh giới hạn dãy tìm kiếm ở bước kế tiếp là nửa trên hay nửa dưới của dãy tìm kiếm hiện hành 15 15 Tìm kiếm nhò phân Bước 1: left = VTĐ; right = VTC; Bước 2: Trong khi left ≤ ≤≤ ≤ right lặp: //đoạn tìm kiếm chưa rỗng Bước 2.1: mid = (left+right)/2; // lấy mốc so sánh Bước 2.2: Nếu a[mid] = x: //Tìm thấy. Dừng, vò trí xuất hiện: mid Bước 2.3: Nếu a[mid] > x: //tìm x trong dãy con a left a mid -1 right = mid - 1; Ngược lại //tìm x trong dãy con a mid +1 a right left = mid + 1; //Hết lặp Bước 3: Dừng, không tìm thấy. 16 16 Tìm kiếm nhò phân • Ví dụ: Cho dãy số a gồm 8 phần tử: 1245 6 8 12 15 • Giá trò cần tìm là 8 17 17 Tìm kiếm nhò phân • left = 1, right = 8, mid = 4 18 18 Tìm kiếm nhò phân • left = 5, right = 8, mid = 6 19 19 Tìm kiếm nhò phân int BinarySearch(int a[],int N,int x ) { int left =0, right = N-1, midle; while (left <= right) { midle = (left + right)/2; if (x == a[midle]) return midle;//Tìm thấy x tại mid if (x<a[midle])right = midle -1; else left = midle +1; } return -1; // trong dãy không có x } 20 20 Tìm kiếm nhò phân • Đánh giá giải thuật: • Giải thuật tìm nhò phân có độ phức tạp tính toán cấp logn: T(n) = O(log 2 n) 21 21 Tìm kiếm nhò phân Nhận xét: – Giải thuật tìm nhò phân dựa vào quan hệ giá trò của các phần tử mảng để đònh hướng trong quá trình tìm kiếm, do vậy chỉ áp dụng được cho những dãy đã có thứ tự. – Giải thuật tìm nhò phân tiết kiệm thời gian hơn rất nhiều so với giải thuật tìm tuần tự do T nhò phân (n) = O(log 2 n) < T tuần tự (n) = O(n). 22 22 Tìm kiếm nhò phân Nhận xét: – Khi muốn áp dụng giải thuật tìm nhò phân cần phải xét đến thời gian sắp xếp dãy số để thỏa điều kiện dãy số có thứ tự. Thời gian này không nhỏ, vàkhi dãy sốbiến động cần phải tiến hành sắp xếp lại => khuyết điểm chính cho giải thuật tìm nhò phân. – Cần cân nhắc nhu cầu thực tế để chọn một trong hai giải thuật tìm kiếm trên sao cho có lợi nhất. 23 23 Đònh nghóa bài toán sắp xếp • Sắp xếp là quá trình xử lý một danh sách các phần tử (hoặc các mẫu tin) để đặt chúng theo một thứ tự thỏa mãn một tiêu chuẩn nào đó dựa trên nội dung thông tin lưu giữ tại mỗi phần tử. • Lưu ý : Thứ tự được đề cập ở đây là một thứ tự tổng quát. • Ví dụ: Hãy đònh nghóa một thứ tự để dãy số sau là dãy tăng theo thứ tự này. 1 3 5 7 2220106 24 24 Khái niệm nghòch thế • Khái niệm nghòch thế: – Xét một mảng các số a 0 , a 1 , … a n . – Nếu cói<j vàa i > a j , thì ta gọi đó là một nghòch thế. • Mảng chưa sắp xếp sẽ có nghòch thế. • Mảng đã có thứ tự sẽ không chứa nghòch thế. a 0 ≤ ≤≤ ≤ a 1 ≤ ≤≤ ≤ … ≤ ≤≤ ≤ a n 25 25 Các phương pháp sắp xếp thông dụng • Selection sort • Insertion sort • Interchange sort • Bubble sort • Shaker sort • Binary Insertion sort • Shell sort • Heap sort • Quick sort • Merge sort • Radix sort • … Đ Đ ơn gia ơn gia û û n, n, Chi ph Chi ph í í cao cao Ph Ph ứ ứ c ta c ta ï ï p hơn p hơn Hie Hie ä ä u qua u qua û û cao cao Lơ Lơ ù ù p thua p thua ä ä t toa t toa ù ù n n kha kha ù ù c c 26 26 Selection sort – Ý tưởng • Nhận xét: Mảng có thứ tự thì a i = min(a i , a i+1 , …, a n-1 ) Ý tưởng: mô phỏng một trong những cách sắp xếp tự nhiên nhất trong thực tế: – Chọn phần tử nhỏ nhất trong N phần tử ban đầu, đưa phần tử này về vò trí đúng là đầu dãy hiện hành – Xem dãy hiện hành chỉ còn N-1 phần tử của dãy ban đầu, bắt đầu từ vò trí thứ 2; lặp lại quá trình trên cho dãy hiện hành đến khi dãy hiện hành chỉ còn 1 phần tử. 27 27 Selection sort – Thuật toán //input: dãy (a, N) //output: dãy (a, N) đã được sắp xếp • Bước 1 : i = Vò trí đầu; • Bước 2 : Tìm phần tử a[min] nhỏ nhất trong dãy hiện hành từ a[i] đến a[N] • Bước 3 : Nếu min ≠ ≠≠ ≠ i: Hoán vò a[min] và a[i] • Bước 4 : Nếu i chưa là Vò trí cuối » i = Vò trí kế(i); » Lặp lại Bước 2 Ngược lại: Dừng. //N phần tử đã nằm đúng vò trí. 28 28 Selection sort – Ví dụ 2 8 5 1 6 4 1512 i min 23456781 Find MinPos(1, 8) Swap(a i , a min ) 29 29 Selection sort – Ví duï 2 8 5 12 6 4 151 i min 23456781 Find MinPos(2, 8) Swap(a i , a min ) 30 30 Selection sort – Ví duï 2 8 5 12 6 4 151 i min 23456781 Find MinPos(3, 8) Swap(a i , a min ) 31 31 Selection sort – Ví duï 2 4 5 12 6 8 151 i min 23456781 Find MinPos(4, 8) Swap(a i , a min ) 32 32 Selection sort – Ví duï 2 4 5 12 6 8 151 i min 23456781 Find MinPos(5, 8) Swap(a i , a min ) 33 33 Selection sort – Ví dụ 2 4 5 6 12 8 151 i min 23456781 Find MinPos(6, 8) Swap(a i , a min ) 34 34 Selection sort – Ví dụ 2 4 5 6 8 12 151 i min 23456781 Find MinPos(7, 8) Swap(a i , a min ) 12 15 35 35 Selection sort void SelectionSort(int a[],int N ) { int min; // chỉ số phần tử nhỏ nhất trong dãy hiện hành for (int i=0; i<N-1 ; i++) { min = i; for(int j = i+1; j < N ; j++) if (a[j] < a[min]) min = j; // ghi nhận vò trí phần tử nhỏ nhất if (min != i) Swap(a[min], a[i]); } } 36 36 • Số lần hoán vò (một hoán vò bằng 3 phép gán) phụ thuộc vào tình trạng ban đầu của dãy số Selection sort – Đánh giá giải thuật 37 37 Selection sort – Đánh giá giải thuật • Ởû lượt thứ i, cần (N-i) lần so sánh để xác đònh phần tử nhỏ nhất hiện hành. • Số lượng phép so sánh không phụ thuộc vào tình trạng của dãy số ban đầu. • Trong mọi trường hợp, số lần so sánh là: 2 1)n(n i)(n 1n 1i − =− ∑ − = 38 38 Insertion Sort – Ý tưởng • Nhận xét: mọi dãy a 1 , a 2 , , a n luôn có i-1 phần tử đầu tiên a 1 , a 2 , ,a i-1 đã có thứ tự (2 ≤ i). Ý tưởng chính: tìm cách chèn phần tử a i vào vò trí thích hợp của đoạn đã được sắp để có dãy mới a 1 , a 2 , ,a i trở nên có thứ tự. – Vò trí này chính là pos thỏa a pos-1 ≤ a i <a pos (1≤ ≤≤ ≤pos≤ ≤≤ ≤i). Chi tiết hơn: – Dãy ban đầu a 1 , a 2 , , a n , xem như đã có đoạn gồm một phần tử a 1 đã được sắp. – Thêm a 2 vào đoạn a 1 sẽ có đoạn a 1 a 2 được sắp – Thêm a 3 vào đoạn a 1 a 2 để có đoạn a 1 a 2 a 3 được sắp – Tiếp tục cho đến khi thêm xong a N vào đoạn a 1 a 2 a N-1 sẽ có dãy a 1 a 2 a N được sắp. 39 39 Insertion Sort – Thuật toán //input: dãy (a, N) //output: dãy (a, N) đã được sắp xếp • Bước 1 : i = 2; // giả sử có đoạn a[1] đã được sắp • Bước 2 : x = a[i]; Tìm vò trí pos thích hợp trong đoạn a[1] đến a[i] để chèn x vào • Bước 3 : Dời chỗ các phần tử từ a[pos] đến a[i-1] sang phải 1 vò trí để dành chổ cho x • Bước 4 : a[pos] = x; // có đoạn a[1] a[i] đã được sắp • Bước 5 : i = i+1; Nếu i ≤ ≤≤ ≤ n : Lặp lại Bước 2. Ngược lại : Dừng. 40 40 Insertion Sort – Ví dụ 2 8 5 1 6 4 1512 23456781 [...]... Sort – Ví dụ Bubble Sort – Ví dụ 1 2 3 4 5 6 7 j 8 1 2 3 4 5 6 7 j 8 1 2 12 2 8 5 4 6 15 1 2 4 12 4 8 5 6 15 i i 67 68 Bubble Sort – Ví dụ Bubble Sort – Ví dụ 1 2 3 4 5 6 7 j 8 1 2 3 4 5 6 7 j 8 1 2 4 5 12 8 5 6 15 1 2 4 5 6 12 8 6 15 i i 69 70 Bubble Sort – Ví dụ Bubble Sort – Ví dụ 1 2 3 4 5 6 7 j 8 1 2 3 4 5 6 7 j 8 1 2 4 5 6 12 8 8 15 1 2 4 5 6 8 12 15 i i 71 72 Bubble sort - Đánh giá giải thuật... Bước 2. 2: right := right -1; • Bước 2. 3: Hiệu chỉnh đoạn a1, a2, …, aright thành heap 1 2 3 4 5 6 7 8 15 12 8 5 1 6 4 2 right Swap(a1, aright) //Hết lặp 99 100 Heap sort – Giai đoạn 2 Heap sort – Giai đoạn 2 curr 1 joint 2 joint 3 4 5 6 7 8 1 2 3 4 5 6 7 8 2 12 8 5 1 6 4 15 12 5 8 2 1 6 4 15 right right Shift(a, 1, right) Swap(a1, aright) 101 1 02 Heap sort – Giai đoạn 2 Heap sort – Giai đoạn 2 curr... 5 1 12 4 15 119 120 Shell sort – Ví dụ Shell sort – Ví dụ h = (5, 3, 1); k = 3 len = 3 h = (5, 3, 1); k = 3 len = 3 joint 1 2 3 curr 4 5 6 7 8 joint 1 2 3 joint 4 5 6 curr 7 8 6 2 15 5 1 12 4 8 5 1 12 6 2 15 4 8 121 122 Shell sort – Ví dụ Shell sort – Ví dụ h = (5, 3, 1); k = 3 len = 3 h = (5, 3, 1); k = 3 len = 1 1 2 3 4 5 6 7 8 joint 1 curr joint 2 joint 3 4 5 6 7 8 4 1 12 5 2 15 6 8 4 1 12 5 2 15... Quick sort – Ví dụ Phân hoạch dãy X 6 1 2 j 3 4 i 5 6 7 8 1 2 3 4 i 5 6 7 j 8 4 2 1 5 8 6 12 15 1 2 4 5 8 6 12 15 left right right left Sắp xếp đoạn 3 STOP STOP Not less than X greater than X Not 139 140 Quick sort – Ví dụ Shell sort – Ví dụ 1 2 3 4 j 5 i 6 7 8 1 2 3 4 5 6 7 8 1 2 4 5 6 8 12 15 1 2 4 5 6 8 12 15 left right Sắp xếp đoạn 3 141 Quick sort – Cài đặt 1 42 Quick sort – Đánh giá giải thuật void...Insertion Sort – Ví dụ Insertion Sort – Ví dụ Insert a2 into (1, 2) Insert a3 into (1, 3) 1 pos 2 3 4 5 6 7 8 1 2 pos 3 4 5 6 7 8 12 2 2 8 5 1 6 4 15 2 12 8 8 5 1 6 4 15 i i x x 41 42 Insertion Sort – Ví dụ Insertion Sort – Ví dụ Insert a4 into (1, 4) Insert a5 into (1, 5) 1 2 3 pos 4 5 6 7 8 1 2 3 4 pos 5 6 7 8 2 8 5 12 5 1 6 4 15 2 1 5 8 12 1 6 4 15 i i x x 43 44 Insertion Sort – Ví dụ Insertion... có dãy đã sắp xếp • Để cài đặt thuật toán hiệu quả, cần phải tổ chức một cấu trúc lưu trữ dữ liệu có khả năng thể hiện được quan hệ của các phần tử trong cây với n ô nhớ thay vì 2n-1 như trong ví dụ • Khái niệm heap và phương pháp sắp xếp Heapsort do J.Williams đề xuất đã giải quyết được các khó khăn trên 84 Sắp xếp cây - Heap sort Ví dụ dãy là heap: • Đònh nghóa heap: • ai ≥ a2i • ai ≥ a2i+1 với ∀i... đoạn 2 curr 1 joint 2 joint 3 4 5 joint 6 7 8 1 2 3 4 5 6 7 8 4 5 8 2 1 6 12 15 8 5 6 2 1 4 12 15 right Shift(a, 1, right) right Swap(a1, aright) 103 104 Heap sort – Hiệu chỉnh heap Heap sort – Giai đoạn 2 1 2 3 4 5 6 7 8 4 5 6 2 1 8 12 15 1 2 4 5 6 8 12 15 • Vấn đề: dãy con aleft+1, aleft +2, …, aright là heap, cần hiệu chỉnh lại để aleft, …, aright là heap • Ý tưởng: do aleft+1, aleft +2, …, aright là... phương pháp sắp xếp chèn trực tiếp Ý tưởng của phương pháp sắp xếp này là xem xét dãy ban đầu như những dãy con gồm các phần tử ở cách nhau len vò trí; tiến hành sắp xếp trên từng dãy con; giảm dần bước len đến khi len = 1 sắp xếp xong: • Dãy ban đầu : a1, a2, , aN được xem như sự xen kẽ của các dãy con sau : – – – – Dãy con thứ nhất : a1 alen+1 a2len+1 Dãy con thứ hai : a2 alen +2 a2len +2 Dãy con... right] 1 2 3 4 5 6 7 8 15 – Heap là một dãy các phần tử aleft, aleft+1, , aright thoả các quan hệ: 12 8 5 1 4 6 2 – Khi đó (ai , a2i), (ai ,a2i+1) được gọi là các cặp phần tử liên đới – Heap được đònh nghóa như trên được dùng trong trường hợp sắp xếp tăng dần, khi sắp xếp giảm dần phải đổi chiều các quan hệ 85 Sắp xếp cây – Heap sort Sắp xếp cây - Heap sort • Một số tính chất của Heap: a1 a2 a4 Các... Giai đoạn 2: Dựa vào các tính chất 1 và 2 của heap để sắp xếp heap có được sau giai đoạn 1 thành dãy tăng dần 2 89 90 Heap sort – Giai đoạn 1 Heap sort – Giai đoạn 1 • Vấn đề: Đổi chổ một số phần tử trên dãy a1, …, aN để dãy trở thành heap • Ý tưởng: theo tính chất 3, dãy con an /2+ 1 , an /2+ 2 an đương nhiên là heap Lần lượt thêm vào phía trước dãy các phần tử an /2, an /2- 1, …, a1; mỗi bước thêm vào cần . duï 2 4 12 8 5 6 15 1 23 4567 81 i j 5 70 70 Bubble Sort – Ví duï 2 4 5 12 8 6 15 1 23 4567 81 i j 6 71 71 Bubble Sort – Ví duï 2 4 5 6 12 8 15 1 23 4567 81 i j 8 72 72 Bubble Sort – Ví duï 2 4 5 6 8 12 15 1 23 4567 81 i j 15 12 73 73 Bubble. Bước 2. Ngược lại : Dừng. 40 40 Insertion Sort – Ví dụ 2 8 5 1 6 4 15 12 234567 81 41 41 2 8 5 1 6 4 15 12 i x 23 4567 81 pos 2 Insertion Sort – Ví duï Insert a 2 into (1, 2) 42 42 12 8 5 1 6 4 15 2 i x 23 4567 81 pos Insertion. Lặp lại Bước 2. 66 66 Bubble Sort – Ví dụ 2 8 5 1 6 4 15 12 234567 81 i j 1 67 67 Bubble Sort – Ví dụ 12 2 8 5 4 6 15 1 23 4567 81 i j 2 68 68 Bubble Sort – Ví dụ 2 12 4 8 5 6 15 1 23 4567 81 i j 4 69 69 Bubble