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

Cấu trúc dữ liệu và giải thuật chương 2 2 giải thuật sắp xếp

110 1,4K 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 110
Dung lượng 8,27 MB

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

Nội dung

Ý tưởng chính của giải thuật là 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 Lặp lại xử lý trên với các phần tử tiếp theo

Trang 1

Chương 2.2 Giải thuật sắp xếp

Trang 2

* Nắm vững, minh họa và tính toán được các

phép gán (hoán vị) các giải thuật sắp xếp cơ bản trên mảng một chiều

* Cài đặt được các giải thuật bằng ngôn ngữ

C/C++

Trang 3

* 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ử.

* Khái niệm nghịch thế

Giả sử xét mảng có thứ tự tăng dần, nếu có i<j và

ai>aj thì ta gọi đó là nghịch thế

Mục tiêu của sắp xếp là khử các nghịch thế (bằng cách hoán vị)

a 1 a 2 a 3 a 4 … … a N-2 a N-1 a N

Trang 4

*Đổi chổ trực tiếp – Interchange Sort

*Chọn trực tiếp – Selection Sort

*Chèn trực tiếp – Insertion Sort

*Quick Sort

*Nổi bọt – Buble Sort

*Một số giải thuật khác đọc thêm trong tài liệu

Trang 5

Ý tưởng chính của giải thuật là 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

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

Trang 6

1 2 3 4 5 6 7 8

6

Giả sử cần sắp xếp dãy số sau tăng dần

Trang 7

1 2 3 4 5 6 7 8

7

Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

Trang 8

1 2 3 4 5 6 7 8

8

Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

Trang 9

1 2 3 4 5 6 7 8

9

Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

Trang 10

1 2 3 4 5 6 7 8

10

Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

Trang 11

1 2 3 4 5 6 7 8

11

Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

Trang 12

1 2 3 4 5 6 7 8

12

Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

Trang 13

1 2 3 4 5 6 7 8

13

Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

Trang 15

1 2 3 4 5 6 7 8

15

Bước 2: Xét phần tử thứ hai (tại vị trí 2)

Trang 16

1 2 3 4 5 6 7 8

16

Bước 2: Xét phần tử thứ hai (tại vị trí 2)

Trang 17

1 2 3 4 5 6 7 8

17

Bước 2: Xét phần tử thứ hai (tại vị trí 2)

Trang 18

1 2 3 4 5 6 7 8

18

Bước 2: Xét phần tử thứ hai (tại vị trí 2)

Trang 19

1 2 3 4 5 6 7 8

19

Bước 2: Xét phần tử thứ hai (tại vị trí 2)

Trang 20

1 2 3 4 5 6 7 8

20

Bước 2: Xét phần tử thứ hai (tại vị trí 2)

Trang 22

1 2 3 4 5 6 7 8

22

Bước 3: Xét phần tử thứ ba (tại vị trí 3)

Trang 23

1 2 3 4 5 6 7 8

23

Bước 3: Xét phần tử thứ ba (tại vị trí 3)

Trang 24

1 2 3 4 5 6 7 8

24

Bước 3: Xét phần tử thứ ba (tại vị trí 3)

Trang 25

1 2 3 4 5 6 7 8

25

Bước 3: Xét phần tử thứ ba (tại vị trí 3)

Trang 26

1 2 3 4 5 6 7 8

26

Bước 3: Xét phần tử thứ ba (tại vị trí 3)

Trang 36

1 2 3 4 5 6 7 8

36

Kết thúc bước 5

Bước 5: Xét phần tử thứ năm (tại vị trí 5)

Trang 42

1 2 3 4 5 6 7 8

42

Hoàn tất sắp xếp

Trang 43

Giải thuật

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

*Bước 2 : j = i+1;//tìm các 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]: Hoán vị 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 44

if(a[j ]< a[i]) {

slhv++;

Hoanvi(a[i],a[j]); }

} }

void Hoanvi(int &a, int &b)

Trang 45

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, nhưng

số lượng phép hoán vị thực hiện tùy thuộc vào kết qủa so sánh, có thể ước lượng trong từng trường hợp như sau :

Trang 46

* Ý tưởng:

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; lúc này dãy hiện hành chỉ còn N-1 phần

tử cần sắp xếp, 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ử

Dãy ban đầu có N phần tử, vậy tóm tắt ý tưởng

giải thuật là thực hiện N-1 lượt việc đưa phần

tử nhỏ nhất trong dãy hiện hành về vị trí đúng

ở đầu dãy

Trang 47

Làm sao để xác định được vị trí phần tử có giá trị nhỏ nhất trong một dãy gồm

N phần tử?

?

Trang 48

1 2 3 4 5 6 7 8

48

Giả sử cần tìm vị trí phần tử nhỏ nhất trong dãy

số sau ?

Trang 49

1 2 3 4 5 6 7 8

49

Bước 1: Giả sử vị trí phần tử nhỏ nhất là 1 (vtmin), phần tử này có giá trị 10

vtmin

Trang 50

1 2 3 4 5 6 7 8 50

Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmin vtmin

5 nhỏ hơn 10 nên cập nhật

vị trí min

Trang 51

1 2 3 4 5 6 7 8 51

Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại

7 lớn hơn 5 nên không cập nhật vị trí

min

Trang 52

1 2 3 4 5 6 7 8 52

Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại

3 nhỏ hơn 5 nên cập nhật

vị trí min

Trang 53

1 2 3 4 5 6 7 8 53

Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại

9 lớn hơn 3 nên không cập nhật vị trí

min

Trang 54

1 2 3 4 5 6 7 8 54

Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại

1 nhỏ hơn 3 nên cập nhật

vị trí min

Trang 55

1 2 3 4 5 6 7 8 55

Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại

15 lớn hơn 1 nên không cập nhật vị trí

min

Trang 56

1 2 3 4 5 6 7 8 56

Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại

2 lớn hơn 1 nên không cập nhật vị trí

min

Trang 57

Hãy cài đặt hàm tìm và trả về vị trí phần tử nhỏ nhất bằng ngôn ngữ C, đầu vào là

mảng số nguyên a, kích thước n?

?

Trang 58

Giả sử cần tìm vị trí phần tử nhỏ nhất bắt đầu từ vị trí k cho trước (ví dụ đoạn

từ 3 đến 8) thì giải quyết như thế nào?

Hãy viết hàm cài đặt bằng ngôn ngữ C?

?

Trang 59

1 2 3 4 5 6 7 8

59

Giả sử cần sắp xếp dãy số sau tăng dần

Trang 67

Kết thúc giải thuật - hoàn tất sắp xếp

67

Trang 68

* Giải thuật

Bước 1 : i = 1;

Bước 2 : Tìm phần tử a[vtmin] nhỏ nhất trong dãy hiện hành từ a[i] đến a[N]

Bước 3 : Hoán vị a[vtmin] và a[i]

Bước 4 :

i = i+1

Nếu i < N thì lặp lại Bước 2

Trang 70

* Ðánh giá giải thuật

Ðối với giải thuật chọn trực tiếp, có thể thấy rằng ở lượt thứ i, bao giờ cũng 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 này không phụ thuộc vào tình trạng của dãy số ban đầu, do vậy trong mọi trường hợp có thể kết luận :

Trang 71

71

Trang 72

1 2 3 4 5 6 7 8

72

Giả sử cần sắp xếp dãy số sau tăng dần

Trang 73

1 2 3 4 5 6 7 8

73

Xem như phần tử thứ 1 đã có thứ tự

Tìm vị trí thích hợp để chèn cho phần tử thứ 2

Trang 74

1 2 3 4 5 6 7 8

74

Hai phần tử đầu tiên đã có thứ tự

Tìm vị trí thích hợp để chèn cho phần tử thứ 3

Trang 75

1 2 3 4 5 6 7 8

75

Ba phần tử đầu tiên đã có thứ tự

Tìm vị trí thích hợp để chèn cho phần tử thứ 4

Trang 76

1 2 3 4 5 6 7 8

76

Bốn phần tử đầu tiên đã có thứ tự

Tìm vị trí thích hợp để chèn cho phần tử thứ 5

Trang 77

1 2 3 4 5 6 7 8

77

Năm phần tử đầu tiên đã có thứ tự

Tìm vị trí thích hợp để chèn cho phần tử thứ 6

Trang 78

1 2 3 4 5 6 7 8

78

Sáu phần tử đầu tiên đã có thứ tự

Tìm vị trí thích hợp để chèn cho phần tử thứ 7

Trang 79

1 2 3 4 5 6 7 8

79

Bảy phần tử đầu tiên đã có thứ tự

Tìm vị trí thích hợp để chèn cho phần tử thứ 8

Trang 80

1 2 3 4 5 6 7 8

80

Kết thúc giải thuật

Trang 81

Dựa vào đâu để xác định được vị trí chèn thích hợp?

?

Trang 83

void InsertionSort(int a[], int N )

{

int pos;

int x; //lưu giá 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

{

x = a[i]; pos = i-1;

// tìm vị trí chèn x while((pos >= 0)&&(a[pos] > x)) { // kết hợp dời chỗ các phần tử

a[pos+1] = a[pos];

pos ;

} a[pos+1] = x;// chèn x vào dãy }

}

Trang 84

*Đánh giá giải thuật

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

vị trí thích hợp pos, và mỗi lần xác định vị trí đang xét không thích hợp, sẽ dời chỗ phần tử a[pos] tương ứng Giải thuật thực hiện tất cả N-1 vòng lặp while, 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ượng trong từng trường hợp như sau:

Trang 85

phần tử kế cận để đưa phần tử nhỏ hơn trong cặp phần tử đó về vị trí đúng đầu dãy hiện hành , sau đó sẽ không xét đến nó

ở bước tiếp theo, do vậy ở lần xử lý thứ i

sẽ 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 86

1 2 3 4 5 6 7

8

86

7 3 9 2 15 1

10 5 i

j

Trang 87

1 2 3 4 5 6 7

8

87

7 3 9 2 15

1 10 5 i

j

Trang 88

1 2 3 4 5 6 7

8

88

7 3 9 2

15

1

10 5 i

j

Trang 89

1 2 3 4 5 6 7

8

89

7 3

9 2

15

1

10 5 i

j

Trang 90

1 2 3 4 5 6 7

8

90

7 3

9 2

15

1

10

5 i

j

Trang 91

1 2 3 4 5 6 7

8

91

7 3

9 2

15

1

10

5 i

j

Trang 92

1 2 3 4 5 6 7

8

92

7 3

9 2

Trang 93

1 2 3 4 5 6 7

8

93

7 3

9 2

15

1

10 5

i

Trang 94

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

j = j-1;

Bước 3:

i = i+1;

Nếu i >N-1: Hết dãy Dừng Ngược lại: Lặp lại Bước 2

Trang 95

if( a[j]< a[j-1] )

Hoanvi(a[j],a[j-1]); }

}

Trang 96

Đánh giá giải thuật

Trang 97

*“Chèn trực tiếp” và “Chọn trực tiếp” đều có chi phí cho trường hợp xấu nhất là O(n 2 ) do đó, không thích hợp cho việc sắp xếp các mảng lớn

*Dễ cài đặt, dễ kiểm lỗi

*“Chèn trực tiếp” tốt hơn “Chọn trực tiếp”, nhất

là khi mảng đã có thứ tự sẵn

 Cần có những giải thuật hiệu quả hơn cho việc sắp xếp các mảng lớn

Trang 99

L=1 R=3

L=4 R=8

Trang 100

L=5 R=8

Trang 106

Kết thúc

Trang 107

*Nếu (L<j) Phân hoạch dãy aL … aj

*Nếu (i<R) Phân hoạch dãy ai … aR

Trang 108

Bước 2b: Trong khi (a[j]>x)

j Bước 2c: Nếu (i<j) Hoán vị a[i] và a[j]

Bước 3:

Nếu i<j: Lặp lại bước 2 Ngược lại: Dừng phân hoạch

Trang 109

Cài đặt

void QuickSort(int a[], int left, int right)

{int i, j, x; x=a[(left+right)/2];i=left, j=right; do{ while(a[i]<x) i++;

while(a[j]>x) j ;

if(i<=j) {

HoanVi(a[i], a[j]); i++; j ;

} } while(i<j);

if(left<j) QuickSort(a, left, j);

if(i<right) QuickSort(a, i, right);

}

Trang 110

Đánh giá giải thuật

*Chi phí trung bình O(n*log 2 n)

*Chi phí cho trường hợp xấu nhất O(n 2 )

*Chi phí tùy thuộc vào cách chọn phần tử “trục”:

*Nếu chọn được phần tử có giá trị trung bình,

ta sẽ chia thành 2 dãy bằng nhau;

*Nếu chọn nhằm phần tử nhỏ nhất (hay lớn nhất)  O(n2)

Ngày đăng: 04/12/2015, 01:04

TỪ KHÓA LIÊN QUAN

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