Duyệt qua dãy, nếu 2 phần tử kề nhau không thứ tự thì hoán đổi. Thực hiện cho đến khi dãy có thứ tự Thuật giải nổi bọt (Bubble sort)[r]
(1)1
(2)1 Phương pháp chèn (Insertion sort)
Nội dung phương pháp:
• Xét dãy a1, …., ai-1 có thứ tự, tìm vị trí thích hợp
của dãy để chèn vào cho ta
được dãy a1, …., có thứ tự
• Thực với i = 2, … , n ta dãy a1, ….,
(3)3
Ví dụ
1
7
1
1
1
1
1
(4)Giải thuật chèn
• Thực với i=2 , …, n: x =
2 j = i-1
3 Khi (j>0) Λ (x<aj)
3 aj+1=aj j = j-1
(5)5
Độ phức tạp
• Số phép gán:
• Số phép so sánh:
(6)Cài đặt
void insertionsort(elem a[], int n, int (*comp)(elem, elem)) {
int i, j, sz=sizeof(elem); elem x;
for (i=1; i<n; i++) {
memcpy(&x, &a[i], sz); j = i-1;
while (j>=0 && comp(x, a[j])<0) {
memcpy(&a[j+1], &a[j], sz); j ;
}
(7)7
2 Phương pháp chọn (Selection sort)
Nội dung phương pháp:
• Chọn phần tử nhỏ dãy ai, …., an ak
• Hoán đổi phần tử với ak
Thực với i = 1, … , n-1 ta dãy a1, ….,
(8)Ví dụ
1
7
1
1
1
1
1
(9)9
Giải thuật chọn
• Với i=1 , …, n-1, thực hiện: k=i
2 x = ak
3 Với j = i+1, …, n, thực hiện:
Nếu x>aj
– k=j
– x=ak
(10)Độ phức tạp
• Số phép gán:
• Số phép so sánh:
(11)11
Cài đặt
void selectionsort(elem a[], int n, int (*comp)(elem, elem)) { int i, j, k, sz=sizeof(elem);
elem x;
for (i=0; i<n-1; i++) {
k = i;
memcpy(&x, &a[k], sz); for (j=i+1; j<n; j++)
if (comp(x, a[j])>0) {
k = j;
memcpy(&x, &a[k], sz); }
memcpy(&a[k], &a[i], sz); memcpy(&a[i], &x, sz); }
(12)Cài đặt
void selectionsort(elem a[], int n, int (*comp)(elem, elem)) { int i, j, k, sz=sizeof(elem);
elem x;
for (i=0; i<n-1; i++) {
k = i;
for (j=i+1; j<n; j++)
if (comp(a[k], a[j])>0) k = j;
memcpy(&x, &a[k], sz); memcpy(&a[k], &a[i], sz); memcpy(&a[i], &x, sz); }
(13)13
3 Phương pháp đổi chổ
Nội dung phương pháp:
Duyệt qua dãy, phần tử kề khơng thứ tự hốn đổi
Thực dãy có thứ tự Thuật giải bọt (Bubble sort)
(14)Thuật giải (C)
for (i=1; i<n; i++)
for (j=n-1; j>=i; j ) if (a[j]<a[j-1])
swap(a[j], a[j-1]);
(15)15
Sap thu tu - phuong phap noi bot
void bubblesort(elem a[], int n, int (*comp)(elem, elem)) {
int i, j, sz=sizeof(elem); elem x;
for (i=1; i<n; i++) for (j=n-1; j>=i; j )
if (comp(a[j], a[j-1])<0) {
memcpy(&x, &a[j], sz);
memcpy(&a[j], &a[j-1], sz); memcpy(&a[j-1], &x, sz); }
(16)Thuật giải BS có sử dụng cờ(C)
i=1; {
OK = 1;
for (j=n-1; j>=i; j ) if (a[j]<a[j-1]) {
swap(a[j], a[j-1]); OK = 0;
(17)17
Thuật giải Sàng (Shaker sort)
Nội dung phương pháp:
Thực lặp trình liên tiếp: Duyệt từ phải qua trái: Nổi bọt
Duyệt từ trái qua phải: Lắng đọng
Mỗi q trình ghi nhận vị trí hóa đổi sau làm điểm xuất phát cho trình
(18)Thuật giải Shaker sort(C)
l = 1;
r = k = n-1; {
for (j=r; j>=l; j ) if (a[j]<a[j-1]) {
swap(a[j], a[j-1]); k = j;
}
l = k+1;
for (j=l; j>=r; j++) if (a[j]<a[j-1]) {
swap(a[j], a[j-1]); k = j;
} r = k-1;
(19)19
(20)1 Giải thuật “vun đống” (Heap sort)
Cải tiến từ phương pháp chọn Định nghĩa:
• Heap: Là cấu trúc nhị phân đầy đủ theo nghĩa: nút bố trí từ mức thấp đến mức cao, từ trái qua phải
(21)21
Giải thuật “vun đống” (Heap sort)
• Heap max (min): Là cấu trúc heap thỏa điều kiện : nút có khóa lớn (nhỏ) Ví dụ:
9
6
7
5
2
(22)Tổ chức heap từ dãy
• Với dãy a1, a2, … an ta tổ chức thành cấu trúc
heap sau:
ai có a2i a2i+1
Vẽ lại
a1 a2 a3 a4 a5 a6 a7
a1
a2 a3
a6 a5
(23)23
Khởi tạo heap max ban đầu
• Ta có với i=n/2+1, … n nút
nên hiển nhiên thỏa mãn tính chất heap max
• Để khởi tạo heap max ban đầu ta tìm cách biến đổi ai (với i=n/2, …, 1) thành heap max ai+1,
…, an thỏa heap max
a1
a2 a3
a6 a5
a4 a7
a10 a9
(24)Sắp thứ tự
• Khi i=1 ta có dãy thỏa mãn tính chất heap max, nghĩa a1 phần tử lớn
• Để thứ tự, phần tử lớn phải nằm cuối nên ta hoán đổi phần tử a1 với an
• Biến đổi a1 thành heap max a2, …, an-1 thỏa heap max
(25)25
Giải thuật biến đổi heap max (q, r)
4
9
1
6
3
5
9
8
1
6
3
5
(26)9
8
1
6
3
5
3
8
1
6
9
5
(27)27
8
6
1
5
9
3
2
6
1
5
9
(28)2
6
1
5
9
3
2
7
6
1
5
9
(29)29
• Tiếp tục thực dãy có thứ tự
3
6
1
5
9
(30)Giải thuật biến đổi heap max (q, r)
1 Khởi tạo – x = aq – i=q – j=2i
– cont=true
2 Khi (j<=r) Λ cont, thực hiện:
2.1 Nếu (j<r) Λ (aj<aj+1) j=j+1
2.2 Nếu x<aj – ai = aj – i=j
– j=2i 2.3 Ngược lại
(31)31
Sắp thứ tự
1 Khởi tạo heap max ban đầu Với i=n/2, …, Thực hiện:
Biến đổi heap max(i, n) Sắp thứ tự
– i=n – Lặp
• Hốn đổi a1 với
• i = i-1
(32)void sift(elem a[ ], int q, int r, int (*comp)(elem, elem)) {
elem x;
int i, j, cont =1, sz = sizeof(elem); i = q;
j = 2*i+1; //lưu ý memcpy(&x, &a[i], sz);
while (j<=r && cont) {
if (j<r && comp(a[j], a[j+1])<0) j++; if (comp(x, a[j]) <0)
{
memcpy(&a[i], &a[j], sz); i = j;
j = 2*i+1; //lưu ý }
else
(33)33 Hàm Heapsort
void heapsort(elem a[ ], int n, int (*comp)(elem, elem)) {
int i, sz = sizeof(elem); elem x;
for (i=n/2-1; i>=0; i ) //lưu ý n/2-1 0
sift(a, i, n-1, comp); i = n-1;
do {
memcpy(&x, &a[0], sz); //lưu ý a[0]
memcpy(&a[0], &a[i], sz); memcpy(&a[i], &x, sz); i ;
sift(a, 0, i, comp); //0
(34)2 Giải thuật Quick sort
• Cải tiến từ phương pháp đổi chổ • Dựa phép phân hoạch:
• Chọn giá trị phân hoạch x thỏa:
Min { } ≤ x ≤ Max { }
– Dị tìm từ trái (l) qua phải phần tử ≥ x
– Dị tìm từ phải (r) qua trái phần tử aj ≤ x
– Nếu i < j hốn đổi với aj
• Tiếp tục thực i>j
Kết dãy bị phân hoạch thành dãy: Dãy từ l đến j mang giá trị ≤ x
Dãy từ i đến r mang giá trị ≥ x
(35)35
void sort(elem a[ ], int l, int r, int (*comp)(elem, elem)) {
static elem x, t;
int i, j, sz = sizeof(elem); i = l;
j = r;
memcpy(&x, &a[(l+r)/2], sz); do {
while (comp(a[i], x)<0) i++; while (comp(a[j], x)>0) j ; if (i<=j)
{
memcpy(&t, &a[i], sz); memcpy(&a[i], &a[j], sz); memcpy(&a[j], &t, sz); i++;
j ; }
} while (i<=j);
(36)void qsort(elem a[ ], int n, int (*comp)(elem, elem)) {
(37)37
Bài tập
• Viết
– Quick sort lời gọi đệ quy – Quick sort không đệ quy
– Chương trình nhập dãy số nguyên, đưa:
• Lẻ đầu dãy thứ tự tăng