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

Slide bài giảng cấu trúc dữ liệu

95 1K 22
Tài liệu đã được kiểm tra trùng lặ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

Thông tin cơ bản

Tiêu đề Cấu Trúc Dữ Liệu
Người hướng dẫn Lương Trần Hy Hiến, Giảng viên
Trường học Đại Học Sư Phạm Tp. Hồ Chí Minh
Chuyên ngành Tin Học
Thể loại bài giảng
Thành phố Hồ Chí Minh
Định dạng
Số trang 95
Dung lượng 2,82 MB

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

Nội dung

Slide bài giảng cấu trúc dữ liệu

Trang 1

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

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

Trang 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

• Tìm tuần tự

• Tìm nhị phân

Tìm kiếm

Trang 3

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

Trang 5

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 6

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]

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

}

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)

Trang 7

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 8

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 21: mid = (left+right)/2; // lấy mốc so sánh

Bước 22: Nếu a[mid] = x: //Tìm thấy

Dừng, vị trí xuất hiện: mid Bước 23: Nếu a[mid] > x: //tìm x trong dãy con a left a mid -1

Trang 10

while (left <= right)

Trang 11

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:

22

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)

Trang 12

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

Trang 13

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ế

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

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

Trang 14

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ử

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 16

Selection sort – Ví duï

Trang 18

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]);

}

}

Trang 19

• 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

38

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

Trang 20

Insertion Sort – Ý tưởng

• Nhận xét: mọi dãy a1 , a2 , , an luô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 , ,ai trở nên có thứ tự

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

• Bước 5: i = i+1;

Nếu i ≤≤≤≤ n : Lặp lại Bước 2.

Ngược lại : Dừng

Trang 25

Insertion Sort – Cài đặt

void InsertionSort ( int a[], int N )

{

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

Trang 26

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.

Binary Insertion Sort – Cài đặt

void BInsertionSort ( int a[], int N )

Trang 27

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:

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

Interchange Sort

Trang 28

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];

• j = j+1;

• Bước 4 : i = i+1;

– Nếu i < n: Lặp lại Bước 2.

– Ngược lại: Dừng

Trang 31

Interchange Sort - Cài đặt

Trang 32

Interchange 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

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

Bubble sort

Trang 33

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

66

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

Trang 37

Bubble sort - Cài đặt

void BubbleSort ( int a[], int N)

Trang 38

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

• 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

Trang 39

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

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ị

– j = j-1;

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

Trang 40

– 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

Trang 41

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:

82

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.

Trang 42

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 :

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.

Trang 43

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.

86

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 ia 2i

• a ia 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ệ.

Trang 45

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 46

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

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.

Trang 47

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;

Trang 48

8

Trang 50

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.

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 21: Hoánvị (a 1 , a right );

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

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

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

//Hết lặp

Trang 51

curr

Trang 52

Shift (a, 1, right)

Trang 54

Heap sort – Hiệu chỉnh heap

• Vấn đề: dãy con a left+1 , a left+2 , …, a right là heap,

cần hiệu chỉnh lại để a left , …, a right là heap

• Ý tưởng: do a left+1 , a left+2 , …, a right là heap nên tất cả các phần tử này đều đã thỏa điều kiện liên đới  vấn đề trở thành: kiểm tra quan hệ liên

đới của a left và đổi chổ a left với liên đới thích hợp của nó nếu quan hệ liên đới bị vi phạm; sau khi hiệu chỉnh sự vi phạm điều kiện liên đới có thể lan truyền đến các vị trí mới hiệu chỉnh.

right

Trang 55

Heap sort – Hiệu chỉnh heap

• Nhận xét: Quá trình hiệu chỉnh có nhiều

bước đổi chỗ trung gian không cần thiết

• Trong ví dụ: đổi chỗ (2, 15), sau đó đổi chổ

tiếp (2, 5): vị trí cuối cùng của 2 là 8, 2 ở vị trí 4 chỉ là tạm thời, không cần thiết

Có thể thực hiện việc dời chỗ hàng loạt,

sau đó đưa giá trị cần hiệu chỉnh vào đúng chỗ

110

Heap sort – Hiệu chỉnh heap

//input: dãy con a left+1 , a left+2 , …, a right là heap

//output: dãy con a left , a left+1 , …, a right là heap

• Bước 1:

• curr = left; x = a curr; //Bắt đầu kiểm tra từ vị trí left

• joint = 2*curr; //Liên đới thứ nhất của curr

• Bước 2: Trong khi (joint ≤ right) //Còn liên đới

để xét

• Bước 21: Nếu (joint < right) && (a joint+1 > a joint )

joint = joint + 1; //joint: vị trí liên đới lớn nhất

• Bước 22: Nếu a joint≤ x //Thỏa điều kiện liên đới

Chuyển đến Bước 3

• Bước 23: a curr = a joint ; curr = joint; joint = 2*curr;

//Hết lặp

• Bước 3: a curr = x;

Ngày đăng: 16/08/2012, 09:59

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

w