1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài giảng cấu trúc dữ liệu chương 2 tìm kiếm và sắp xếp

47 320 0

Đ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

Thông tin cơ bản

Định dạng
Số trang 47
Dung lượng 650,66 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

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

Trang 1

Đại Học Sư Phạm Tp Hồ Chí Minh

Chương 2: Tìm kiếm & Sắp xếp

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.

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ố a1, a2, ,aN

int a[N];

•Khoá cần tìm là x

Trang 2

TTTTììììm kie m kie m kiếááám tua m tua m tuầàààn t n t n tựựựự

{

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

}

Trang 3

Tìm kiếm tuần tự

• Cải tiến cài đặt: dùng phương pháp “ đặt lính

– Đặ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

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

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

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

Trang 4

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ệ

ai -1 ≤≤≤≤ ai ≤≤≤≤ ai+1

Nếu x > ai thì x chỉ có thể xuất hiện trong

đoạn [ai+1 ,aN] của dãy

Nếu x < ai thì x chỉ có thể xuất hiện trong

đoạn [a1 ,ai-1] của dãy

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

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

Trang 5

int left =0, right = N-1, midle;

while (left <= right)

• Đá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(log2 n)

Trang 6

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

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

Đị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

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ế

a0 ≤≤≤≤ a1 ≤≤≤≤ … ≤≤≤≤ an

Trang 7

Phức tạp hơn Hiệu quả cao

Lớp thuật toán khác

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

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

• 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í.

Trang 8

Selection sort – Ví duï

Selection sort – Ví duï

Trang 9

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

• 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

Trang 10

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(ni)(n

1 n 1 i

Insertion Sort – Ý tưởng

• Nhận xét: mọi dãy a1 , a2 , , anluôn có i-1 phần tử đầu tiên a1 , a2 , ,ai-1đã có thứ tự (2 ≤ i)



Ý tưởng chính: tìm cách chèn phần tử ai vào vị trí thích hợp của đoạn đã được sắp để có dãy mới a1 ,

a2 , ,aitrở nên có thứ tự

– Vị trí này chính là pos thỏa apos-1≤ a i < apos(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

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

Trang 13

Insertion Sort – Cài đặt

void InsertionSort ( int a[], int N )

{

int pos, i;

int x;//lưu trữ a[i] tránh bị ghi đè khi dời chỗ các phần tử.

for ( int i=1 ; i<N ; i++) //đoạn a[0] đã sắp

Insertion Sort – Nhận xét

• Khi tìm vị trí thích hợp để chèn a[i] vào đoạn

a[0] đến a[i-1], do đoạn đã được sắp  có thể

sử dụng giải thuật tìm nhị phân để thực hiện việc tìm vị trí pos  giải thuật sắp xếp chèn 

nhị phân Binary Insertion Sort

– Lưu ý: Chèn nhị phân chỉ làm giảm số lần so sánh,

không làm giảm số lần dời chỗ.

• Ngoài ra, có thể cải tiến giải thuật chèn trực

tiếp với phần tử cầm canh để giảm điều kiện kiểm tra khi xác định vị trí pos.

51

Binary Insertion Sort – Cài đặt

void BInsertionSort ( int a[], int N )

Insertion Sort – Đánh giá giải thuật

• Các phép so sánh xảy ra trong mỗi vòng lặp tìm vị trí

thích hợp pos Mỗi lần xác định vị trí pos đang xét không thích hợp  dời chỗ phần tử a[pos-1] đến vị trí

pos

• Giải thuật thực hiện tất cả N-1 vòng lặp tìm pos, do số

lượng phép so sánh và dời chỗ này phụ thuộc vào tình trạng của dãy số ban đầu, nên chỉ có thể ước lược trong từng trường hợp như sau:

Trang 14

Phương pháp đổi chỗ trực tiếp

Interchange Sort

54

Interchange Sort – Ý tưởng

• Nhận xét: Để sắp xếp một dãy số, ta có

thể xét các nghịch thế có trong dãy và làm triệt tiêu dần chúng đi



 Ý tưởng chính:

– Xuất phát từ đầu dãy, tìm tất cả nghịch thế

chứa phần tử này, triệt tiêu chúng bằng cách đổi chỗ phần tử này với phần tử tương ứng trong cặp nghịch thế

– Lặp lại xử lý trên với các phần tử tiếp theo

trong dãy

Interchange Sort – Thuật toán

//input: dãy (a, N)

//output: dãy (a, N) đã được sắp xếp

• Bước 1 : i = 1; // bắt đầu từ đầu dãy

• Bước 2 : j = i+1; //tìm các cặp phần tử

a[j] < a[i], j>i

• Bước 3 : Trong khi j ≤ N thực hiện

• Nếu a[j]<a[i]: a[i] ↔a[j];

Trang 16

Interchange Sort - Cài đặt

• Số lượng các phép so sánh xảy ra không phụ

thuộc vào tình trạng của dãy số ban đầu

• Số lượng phép hoán vị thực hiện tùy thuộc

vào kết quả so sánh

Phương pháp nổi bọt

Bubble sort

Bubble sort – Ý tưởng

• Ý tưởng chính:

– Xuất phát từ cuối (đầu) dãy, đổi chỗ các

cặp phần tử kế cận để đưa phần tử nhỏ (lớn) hơn trong cặp phần tử đó về vị trí đúng đầu (cuối) dãy hiện hành, sau đó sẽ không xét đến nó ở bước tiếp theo,

– Ở lần xử lý thứ i có vị trí đầu dãy là i – Lặp lại xử lý trên cho đến khi không còn

cặp phần tử nào để xét

Trang 17

Bubble 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 : j = Vị trí cuối;//Duyệt từ cuối dãy ngược

về vị trí i

– Trong khi (j > i) thực hiện:

• Nếu a[j]<a[j-1]: a[j]↔a[j-1];//xét cặp phần tử kế cận

• j = Vị trí trước(j);

• Bước 3 : i = Vị trí kế(i); // lần xử lý kế tiếp

– Nếu i = Vị trí cuối: Dừng // Hết dãy.

– Ngược lại : Lặp lại Bước 2.

Trang 19

Bubble sort - Cài đặt

void BubbleSort ( int a[], int N)

Bubble sort - Đánh giá giải thuật

• Số lượng các phép so sánh xảy ra không phụ

thuộc vào tình trạng của dãy số ban đầu

• Số lượng phép hoán vị thực hiện tùy thuộc

vào kết quả so sánh

75

• Khuyết điểm:

– Không nhận diện được tình trạng dãy đã có

thứ tự hay có thứ tự từng phần

– Các phần tử nhỏ được đưa về vị trí đúng rất

nhanh, trong khi các phần tử lớn lại được

đưa về vị trí đúng rất chậm.

Bubble sort - Đánh giá giải thuật

76

Bubble sort – Cải tiến

• Giải thuật ShakerSort:

– Dựa trên nguyên tắc đổi chỗ trực tiếp – Tìm cách khắc phục các nhược điểm của

BubleSort

• Trong mỗi lần sắp xếp, duyệt mảng theo 2 lượt

từ 2 phía khác nhau :

– Lượt đi: đẩy phần tử nhỏ về đầu mảng – Lượt về: đẩy phần tử lớn về cuối mảng

• Ghi nhận lại những đoạn đã sắp xếp nhằm tiết

kiệm các phép so sánh thừa.

Trang 20

Giải thuật ShakerSort

//input: dãy (a, N)

//output: dãy (a, N) đã được sắp xếp

• Bước 1 :

– l = 1; r = n; //từ l đến r là đoạn cần được sắp xếp

– k = n; // ghi nhận lại vị trí k xảy ra hoán vị sau cùng

// để làm cơ sở thu hẹp đoạn l đến r

• Bước 2 :

– Bước 2a : j = r ; // đẩy phần tử nhỏ về đầu mảng

• Trong khi (j > l) :

– Nếu a[j]<a[j-1]: a[j] ↔ a[j-1];

» k = j; //lưu lại nơi xảy ra hoán vị

– Nếu a[j]>a[j+1]: a[j] ↔ a[j+1];

» k = j;//lưu lại nơi xảy ra hoán vị

– j = j+1;

• r = k; //loại bớt các phần tử đã có thứ tự ở cuối dãy

• Bước 3 : Nếu l < r: Lặp lại Bước 2

Sắp xếp cây - Heap sort

• Khi tìm phần tử nhỏ nhất ở bước i, phương

pháp sắp xếp chọn trực tiếp không tận dụng

được các thông tin đã có được do các phép so

sánh ở bước i-1

• Giải thuật Heap Sort khắc phục nhược điểm

này bằng cách chọn ra được một cấu trúc dữ

liệu cho phép tích lũy các thông tin về sự so

sánh giá trị các phần tử trong quá trình sắp

xếp

Sắp xếp cây - Heap sort

• Xét dãy số : 5 2 6 4 8 1

• Giả sử các phần tử của dãy được bố trí

theo quan hệ so sánh và tạo thành sơ

đồ dạng cây:

Trang 21

Sắp xếp cây - Heap sort

• Phần tử ở mức i chính là phần tử lớn trong cặp

phần tử tương ứng ở mức i+1

⇒ phần tử ở mức 0 (nút gốc của cây) luôn là phần tử

lớn nhất của dãy

• Nếu loại bỏ phần tử gốc ra khỏi cây (nghĩa là đưa

phần tử lớn nhất về đúng vị trí), thì việc cập nhật

cây chỉ xảy ra trên những nhánh liên quan đến

phần tử mới loại bỏ, còn các nhánh khác được bảo

toàn, nghĩa là bước kế tiếp có thể sử dụng lại các

kết quả so sánh ở bước hiện tại.

82

Sắp xếp cây - Heap sort

• Loại bỏ 8 ra khỏi cây và thế vào các chỗ

trống giá trị -∞ để tiện việc cập nhật lại cây :

83

Sắp xếp cây - Heap sort

• Toàn bộ nhánh trái của cây cũ được bảo

toàn

⇒ Bước kế tiếp để chọn được phần tử lớn

nhất hiện hành là 6, chỉ cần làm thêm

một phép so sánh 1 với 6.

84

Sắp xếp cây - Heap sort

• Tiến hành nhiều lần việc loại bỏ phần tử gốc của

cây cho đến khi tất cả các phần tử của cây đều là

-∞

∞, khi đó xếp các phần tử theo thứ tự loại bỏ trên

cây sẽ 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.

Trang 22

Sắp xếp cây - Heap sort

• Định nghĩa heap:

– Heap là một dãy các phần tử a left , a left+1 , ,

a right thoả các quan hệ:

• a i ≥≥≥≥ a 2i

• a i ≥≥≥≥ a 2i+1

với ∀i ∈∈ [left, right]

– Khi đó (a i , a 2i ), (a i ,a 2i+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ệ.

Sắp xếp cây - Heap sort

• Một số tính chất của Heap:

– Tính chất 1: Nếu a left , a left+1 , …, a right là một heap thì khi cắt bỏ một số phần tử ở hai đầu của heap, dãy con còn lại vẫn là một heap.

– Tính chất 2: Nếu a 1 , a 2 , …, a n là một heap thì phần tử a 1 (đầu heap) luôn là phần tử lớn nhất trong heap.

– Tính chất 3: Mọi dãy con a left , a left+1 , ,

a right thỏa: 2left > right đều là heap.

Trang 23

Sắp xếp cây - Heap sort

• Sắp xếp dãy tăng dần qua 2 giai đoạn:

– Giai đoạn 1: Dựa vào tính chất 3 của heap

để hiệu chỉnh dãy ban đầu thành heap

– 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

91

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

hiệu chỉnh vị trí các phần tử theo mối

quan hệ liên đới ta sẽ nhận được heap

mong muốn.

92

Heap sort – Giai đoạn 1

//input: dãy (a, N) //output: dãy (a, N) là một heap

• Bước 1: left = N/2; //Thêm các phần tử

aleft, , a1 vào heap

• Bước 2: Trong khi left > 0

//Lưu ý: đoạn a left+1 , …, a N đã là heap

• Bước 21: Hiệu chỉnh đoạn a left , …, a N thành heap

• Bước 22: left = left - 1;

//Hết lặp

Trang 24

curr

Trang 25

Heap sort – Giai đoạn 2

• Vấn đề: Sắp xếp heap a 1 , …, a N thành dãy tăng dần

//Đặt: right = N dãy a 1 , …, a right là heap.

• Ý tưởng:

– Theo tính chất 2: a 1 sẽ là phần tử lớn nhất, vì vậy vị trí đúng của a 1 phải là right - cuối dãy.

Đổi chổ (a 1 , a right )  được thêm một phần tử ở đúng vị trí

Theo tính chất 3: dãy con a 2 , …, a right-1 vẫn là heap

 Giảm right, thêm a 1 vào dãy và hiệu chỉnh lại

 dãy a 1 , …, a right là heap.

99

Heap sort – Giai đoạn 2

//input: dãy (a, N) là heap

//output: dãy (a, N) sắp tăng dần

• Bước 1: right = N; //Bắt đầu thực hiện từ cuối

dãy

• Bước 2: Trong khi right > 1

//Đưa phần tử lớn nhất (a 1 )về vị trí right

• Bước 2.1: Hoánvị (a 1 , a right );

//Loại bỏ phần tử lớn nhất ra khỏi heap

• Bước 2.2: right := right -1;

• Bước 2.3: Hiệu chỉnh đoạn a 1 , a 2 , …, a right thành heap

Ngày đăng: 20/10/2014, 06:52

TỪ KHÓA LIÊN QUAN

TRÍCH ĐOẠN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm