Tìm kiếm và Sắp xếp

24 369 0
Tìm kiếm và Sắp xếp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Chương 1 Tìm kiếm Sắp xếp  1.1 Tìm kiếm Tìm kiếm là thao tác cơ bản, thường xuyên quan trọng trong tin học. Ví dụ như tìm kiếm nhân viên trong danh sách nhân viên, tìm kiếm một sinh viên trong danh sách lớp học…Các hệ thống thông tin thường lưu trữ khối lượng dữ liệu lớn, nên thuật toán tìm kiếm tốt sẽ có nhiều lợi ích. Tuy nhiên, thao tác tìm kiếm còn phụ thuộc rất nhiều đến dữ liệu được tổ chức như thế nào; nếu dữ liệu được tổ chức tốt thì việc tìm kiếm sẽ tiến hành nhanh chóng hiệu quả hơn. Giả sử sách được sắp theo chủ đề, thể loại thì dễ tìm kiếm hơn là không được sắp. Hoặc danh sách tên người được sắp theo thứ tự alphabet cũng dễ cho việc tìm kiếm… 1.1.1 Mô tả bài toán tìm kiếm trong tin học Tìm kiếm là quá trình xác định một đối tượng nào đó trong một tập các đối tượng. Kết quả trả về là đối tượng tìm được hoặc một chỉ số (nếu có) xác định vị trí của đối tượng trong tập đó. Việc tìm kiếm dựa theo một trường nào đó của đối tượng, trường này là khóa (key) của việc tìm kiếm. Ví dụ: đối tượng sinh viên có các dữ liệu {MaSV, HoTen, DiaChi,…}. Khi đó tìm kiếm trên danh sách sinh viên thì khóa thường chọn là MaSV hoặc HoTen. Thông thường người ta phân làm hai loại tìm kiếm: tìm kiếm tuyến tính hay còn gọi là tuần tự cho tập dữ liệu bất kỳ; tìm kiếm nhị phân cho tập dữ liệu đã được sắp xếp. Bài toán tìm kiếm được mô tả như sau: • Tập dữ liệu được lưu trữ là dãy a 1 , a 2 , ,a n . Giả sử chọn cấu trúc dữ liệu mảng để lưu trữ dãy số này trong bộ nhớ chính, có khai báo: int a[n]; • Khoá cần tìm là x có kiểu nguyên : int x. Tìm kiếm Tìm kiếm tuyến tính Tìm kiếm nhị phân Tập DL bất kỳ Tập DL được sắp Hình 4.1: Phân loại phương pháp tìm kiếm 1.1.2 Tìm kiếm tuyến tính Ý tưởng chính: duyệt tuần tự từ phần tử đầu tiên, lần lượt so sánh khóa tìm kiếm với khoá tương ứng của các phần tử trong danh sách (trong trường hợp mô tả trên là so sánh x a[i]). Cho đến khi gặp phần tử cần tìm hoặc đến khi duyệt hết danh sách. Các bước tiến hành như sau : Bước 1: i = 1 ; Bước 2: so sánh a[i] với x, có hai khả năng i. a[i] = x: tìm thấy ⇒ dừng ii. a[i] <> x: sang bước 3 Bước 3: i = i +1, kiểm tra chỉ số i kích thước mảng n i. nếu i>n: hết mảng, không tìm thấy ⇒ dừng ii. ngược lại: quay lại bước 2 Hàm tìm kiếm tuyến tính đơn giản minh họa bằng ngôn ngữ C/C++. int Search(int a[], int n, int key) { int i =0; while (i<n) && (key != a[i]) i++; if (i >= n) return -1; // tìm không thấy else return i; // tìm thấy tại vị trí i } 1.1.3 Tìm kiếm nhị phân Phương pháp tìm kiếm nhị phân được áp dụng cho dãy khoá đã có thứ tự: k[1] ≤ k[2] ≤ . ≤ k[n]. Ý tưởng của phương pháp này như sau: Giả sử ta cần tìm trong đoạn a[left .right] với khoá tìm kiếm là x, trước hết ta xét phần tử giữa a[mid], với mid = (left + right)/2. a 3 a 2 a 1 x ? a n a n-1 • Nếu a[mid] < x thì có nghĩa là đoạn a[left] đến a[right] chỉ chứa khóa < x, ta tiến hành tìm kiếm từ a[mid+1] đến a[right]. • Nếu a[mid] > x thì có nghĩa là đoạn a[m] đến a[right] chỉ chứa khoá > x, ta tiến hành tìm kiếm từ a[left] đến a[mid-1]. • Nếu a[mid] = x thì việc tìm kiếm thành công. • Quá trình tìm kiếm thất bại nếu left > right. Các bước tiến hành như sau: Bước 1: left =1, right = n // tìm kiếm trên tất cả phần tử. Bước 2: mid = (left + right)/2 // lấy mốc so sánh So sánh a[mid] với x có 3 khả năng: - a[mid] = x, tìm thấy ⇒ dừng - a[mid]> x, tìm tiếp trong dãy a[left] a[mid-1] right = mid -1; - a[mid] < x, tìm tiếp trong dãy a[mid+1] a[right] left = mid +1; Bước 3: Nếu left ≤ right; còn phần tử ⇒ tìm tiếp ⇒ bước 2 Ngược lại: dừng, đã xét hết phần tử ⇒ không tìm thấy. Ví dụ: cho dãy số gồm 8 phần tử {1, 2, 4, 5, 6, 8, 12, 15} x = 8 1 Left = 1 X = 8 Right = 8 Mid = 4 Đoạn tìm kiếm 2 4 5 6 8 12 15 1 Left = 5 X = 8 Right = 8 Mid = 6 Đoạn tìm kiếm 2 4 5 6 8 12 15 = Hình 4.2: Tìm kiếm nhị phân. Hàm C minh họa cài đặt thuật toán tìm kiếm nhị phân int BinarySearch(int key) { int left = 0, right = n-1, mid; while (left <= right) { mid = (left + right)/ 2; // lấy điểm giữa if (a[mid] == key) // nếu tìm được return mid; if (a[mid] < x) // tìm đoạn bên phải mid left = mid+1; else right = mid-1; // tìm đoạn bên trái mid } return -1; // không tìm được } 1.1.4 Kết luận • Giải thuật tìm kiếm tuyến tính không phụ thuộc vào thứ tự của các phần tử trong mảng, do vậy đây là phương pháp tổng quát nhất để tìm kiếm trên một dãy bất kỳ. • Thuật giải nhị phân dựa vào quan hệ giá trị của các phần tử trong mảng để định hướng trong quá trình tìm kiếm, do vậy chỉ áp dụng được với dãy đã có thứ tự. • Thuật giải nhị phân tìm kiếm nhanh hơn tìm kiếm tuyến tính. • Tuy nhiên khi áp dụng thuật giải nhị phân thì cần phải quan tâm đến chi phí cho việc sắp xếp mảng. Vì khi mảng được sắp thứ tự rồi thì mới tìm kiếm nhị phân. 1.2 Bài toán sắp xếp Sắp xếp là quá trình bố trí lại các phần tử của một tập đối tượng nào đó theo một thứ tự nhất định. Ví dụ như: tăng dần, giảm dần với một dãy số, thứ tự từ điển với các từ .Việc sắp xếp là một bài toán thường thấy trong tin học, do các yêu cầu tìm kiếm thuận lợi, sắp xếp kết quả các bảng biểu . Dữ liệu thường được tổ chức thành mảng các mẫu tin dữ liệu, mỗi mẫu tin thường có một số các trường dữ liệu khác nhau. Không phải toàn bộ các trường đều tham gia quá trình sắp xếp mà chỉ có một trường nào đó (hoặc một vài trường) được quan tâm. Người ta gọi trường này là khoá, việc sắp xếp sẽ được tiến hành dựa vào giá trị khoá này. Ví dụ: sắp xếp một mảng các số nguyên tăng dần, sắp xếp một danh sách học sinh với điểm thi giảm dần . 1.3 Một số phương pháp sắp xếp cơ bản Trong phần này giới thiệu một số phương pháp sắp xếp cơ bản thường được dùng để sắp xếp một danh sách, mảng dữ liệu. 1.3.1 Phương pháp chọn Đây là một trong những thuật toán sắp xếp đơn giản nhất. Ý tưởng cơ bản của phương pháp này được thể hiện như sau: 1. Ở lượt thứ nhất, ta chọn trong dãy khoá k[1 n] ra khoá nhỏ nhất đổi giá trị nó với k[1], khi đó k[1] sẽ trở thành khoá nhỏ nhất. 2. Ở lượt thứ hai, ta chọn trong dãy khoá k[2 n] ra khóa nhỏ nhất đổi giá trị nó cho k[2]. 3. . 4. Ở lượt thứ i, ta chọn trong dãy khóa k[i n] ra khóa nhỏ nhất đổi giá trị nó cho k[i]. 5. Tới lượt k-1, ta chọn giá trị nhỏ nhất trong k[n-1] k[n] ra khoá nhỏ nhất đổi cho giá trị cho k[n-1]. Thuật giải SelectionSort: (mã giả, chỉ số 1 là đầu mảng) begin for i:= 1 to n-1 do begin jmin := i; for j:=i+1 to n do if a[j] < a[jmin] then jmin = j; if ( jmin <> i) Swap(a[i], a[jmin]) end. end. 1.3.2 Phương pháp sắp xếp nổi bọt Trong thuật toán sắp xếp nổi bọt, dãy khóa sẽ được duyệt từ cuối lên đầu dãy, nếu gặp hai khóa kế cận ngược thứ tự thì đổi chỗ cho nhau. Sau lần duyệt như vậy, khóa nhỏ nhất trong dãy khóa sẽ được chuyển về vị trí đầu tiên vấn đề trở thành sắp xếp dãy khoá từ k[n] đến k[2]. Thuật giải bubblesort: (mả giả, chỉ số 1 là đầu mảng) begin for i:=2 to n do for j:= n downto i do if (a[j] < a[j-1]) Swap(a[j],a[j-1]) end. 1.3.3 Phương pháp sắp xếp chèn Xét dãy khóa k[1 n], ta thấy dãy con chỉ gồm mỗi một khoá là k[1] có thể coi là đã sắp xếp rồi. Xét thêm k[2], ta so sánh nó với k[1], nếu thấy k[2] < k[1] thì chèn nó vào trước k[1]. Đối với k[3], ta chỉ xét dãy chỉ gồm hai khoá k[1] k[2] đã sắp xếp tìm cách chèn k[3] vào dãy khóa đó để được thứ tự sắp xếp. Một cách tổng quát, ta sẽ sắp xếp dãy k[1 i] trong điều kiện dãy k[1 i-1] đã sắp xếp rồi bằng cách chèn k[i] vào dãy đó tại vị trí đúng khi sắp xếp. Thuật giải InsertionSort: (mả giả, chỉ số 1 là đầu mảng) begin for i:= 2 to n do begin tmp = a[i]; j = i-1; while (j>0) and (tmp < a[j]) begin a[j+1] = a[j];// đẩy lùi giá trị k[i] về sau -> tạo khoảng trống j := j-1; end k[j+1] = tmp; // chèn vào khoảng trống. end end. 1.3.4 Phương pháp đổi chỗ trực tiếp Ý tưởng chính: xuất phát từ đầu dãy, tìm những phần tử còn lại không thoả thứ tự sắp xếp với phần tử đang xét, hoán vị các phần tử tương ứng để thỏa thứ tự. Lặp lại tương tự với các phần tử tiếp theo của dãy. Các bước tiến hành như sau:  Bước 1 : i = 1; // xuất phát từ đầu dãy  Bước 2 : j = i+1; // tìm các phần tử phía sau i  Bước 3 : o While j ≤ n do  Nếu a[j]< a[i] ⇒ Swap(a[i], a[j]);  j = j+1;  Bước 4 : i = i+1; o Nếu i < n: ⇒ Bước 2 o Ngược lại ⇒ Kết thúc Ví dụ: cho dãy số a: 10 3 7 6 2 5 4 16 [...]... i j 3 a[k] > x, với k = j n Ta có nhận xét khi đó dãy con thứ 2 đã có thứ tự, nếu dãy con 1 dãy con 3 có một phần tử thì chúng cũng đã có thứ tự, khi đó dãy ban đầu đã được sắp Ngược lại, nếu dãy con 1 3 có nhiều hơn một phần tử thì dãy ban đầu có thứ tự khi dãy con 1 3 được sắp Để sắp xếp dãy con 1 3, ta lần lượt tiến hành việc phân hoạch từng dãy con theo cùng phương pháp vừa trình bày... thức phân loại các con số trong dãy thứ tự phân loại con con số này để tạo ra thứ tự cho các phần tử Đây là cách tiếp cận khác so với các phương pháp sắp xếp trước là so sánh các giá trị của các phần tử Thuật giải dựa trên ý tưởng chính là sắp xếp từng con số của một dãy các số Giả sử chúng ta có dãy số như sau: 493 812 715 710 195 437 582 340 385 Đầu tiên sắp xếp các số theo hàng đơn vị: 493 812... để tìm vị trí thích hợp trong dãy con x = a[i]; // a[j] đứng trước a[i] trong cùng dãy con j = i – len; while ((x < a[j]) && (j>= 0)) // sắp xếp dãy con chứa x dùng pp chèn { a[j+len] = a[j]; // dời về sau theo dãy con j = j – len; // qua phần tử trước trong dãy con } a[j+len] = x;// đưa x vào vị trí thích hợp trong dãy con } } } 1.3.6 Phương pháp phân đoạn QuickSort Đây là một phương pháp sắp xếp. .. right, o Cho x = a[k], i = left, j = right  Bước 2: Tìm hoán vị cặp phần tử a[i] a[j] không đúng thứ tự đang sắp o Bước 2-1: Trong khi a[i] < x ⇒ i++; o Bước 2-2: Trong khi a[j] > x ⇒ j ; o Bước 2-3: Nếu i < j o Nếu i < j: ⇒ Bước 2;  ⇒ Swap(a[i], a[j]) // a[i], a[j] sai thứ tự // chưa hết mảng dừng Bước 3: o Nếu i ≥ j: ⇒ Dừng Giải thuật để sắp xếp dãy a[left], a[left+1], , a[right]: được phát... do C.A.R Hoare đề xuất Thuật toán này có tốc độ trung bình nhanh hơn các thuật toán sắp xếp tổng quát khác Do đó Hoare dùng chữ “Quick” để đặt tên cho thuật toán này Ý tưởng chính: Để sắp dãy a[1] a[n], ta thực hiện sắp xếp dãy a từ chỉ số 1 đến chỉ số n QuickSort dựa trên phân hoạch dãy ban đầu thành hai phần dựa vào giá trị x, x là giá trị của một phần tử tùy ý trong dãy ban đầu:  Dãy thứ 1: gồm... Hình 4.3: Minh họa đổi chỗ trực tiếp 1.3.5 Phương pháp ShellSort Trong phương pháp sắp xếp kiểu chèn nếu ta luôn phải chèn một khóa vào vị trí đầu dãy thì dẫn đến hạn chế của thuật toán này Để khắc phục trong trường hợp này thì người ta đưa ra một phương pháp sắp xếp là ShellSort Ý tưởng chính: xét một dãy a[1] a[n], cho một số nguyên h (1 ≤ h ≤ n), ta có thể chia dãy đó... Bước 2: Chia dãy ban đầu thành các dãy con có bước nhảy là h[i] Thực hiện sắp xếp từng dãy con bằng phương pháp chèn trực tiếp  Bước 3: i = i+1 o Nếu i > k: ⇒ Dừng o Ngược lại: ⇒ Bước 2 Ví dụ: cho dãy bên dưới với n = 8, h = {5, 3, 1} 10 3 7 Ta có minh họa như sau: 6 2 5 4 16 Hình 4.4: Minh hoạ ShellSort Cài đặt ShellSort: sắp xếp dãy a[] tăng, với h[] là mảng chứa các độ dài (bước nhảy) đã chọn sẵn:... 3 2 5 2 7 4 4 16 16 5 Những dãy này được coi là những dãy con xếp theo độ dài bước h Tư tưởng chính của thuật toán ShellSort là: với mỗi bước h, áp dụng thuật toán sắp xếp kiểu chèn từng dãy con độc lập để làm mịn dần các phần tử trong dãy chính Tiếp tục làm tương tự đối với bước (h div 2) cho đến khi h = 1 thì ta được dãy phần tử được sắp Xét trong ví dụ trên, nếu chúng ta dùng phương pháp chèn thì... đó nó phải chèn vào vị trí thứ 1, tức là phải chèn trước 4 phần tử trước nó Nhưng nếu chúng ta xem 2 là phần tử của dãy 2 thì ta chỉ cần chèn trước một phần tử là 3 Đây chính là nguyên nhân thuật toán ShellSort thực hiện hiệu quả hơn sắp xếp chèn Khi đó khóa nhỏ nhanh chóng đưa về gần vị trí đúng của nó Các bước thực hiện chính như sau:  Bước 1: chọn k khoảng cách h[1], h[2], , h[k], i = 1  Bước... khi a[i] . Chương 1 Tìm kiếm và Sắp xếp  1.1 Tìm kiếm Tìm kiếm là thao tác cơ bản, thường xuyên và quan trọng trong tin học. Ví dụ như tìm kiếm nhân viên. cần tìm là x có kiểu nguyên : int x. Tìm kiếm Tìm kiếm tuyến tính Tìm kiếm nhị phân Tập DL bất kỳ Tập DL được sắp Hình 4.1: Phân loại phương pháp tìm kiếm

Ngày đăng: 05/10/2013, 17:20

Hình ảnh liên quan

Hình 4.2: Tìm kiếm nhị phân. Hàm C minh họa cài đặt thuật toán tìm kiếm nhị phân - Tìm kiếm và Sắp xếp

Hình 4.2.

Tìm kiếm nhị phân. Hàm C minh họa cài đặt thuật toán tìm kiếm nhị phân Xem tại trang 4 của tài liệu.
Hình 4.3: Minh họa đổi chỗ trực tiếp. - Tìm kiếm và Sắp xếp

Hình 4.3.

Minh họa đổi chỗ trực tiếp Xem tại trang 13 của tài liệu.
Bảng 4.1: Sắp theo hàng đơn vị - Tìm kiếm và Sắp xếp

Bảng 4.1.

Sắp theo hàng đơn vị Xem tại trang 20 của tài liệu.
1.3.7 Phương pháp cơ số RadixSort - Tìm kiếm và Sắp xếp

1.3.7.

Phương pháp cơ số RadixSort Xem tại trang 20 của tài liệu.
Bảng 4.2: Sắp theo hàng chục - Tìm kiếm và Sắp xếp

Bảng 4.2.

Sắp theo hàng chục Xem tại trang 21 của tài liệu.

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan