Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (156.76 KB, 37 trang )
<span class='text_page_counter'>(1)</span><div class='page_container' data-page=1>
1
Nội dung phương pháp:
• Xét dãy a<sub>1</sub>, …., ai-1 có thứ tự, tìm vị trí thích hợp
của ai trong dãy trên để chèn vào sao cho ta
được dãy a1, …., ai có thứ tự.
• Thực hiện với i = 2, ….., n ta được dãy a1, ….,
3
1 2 3 4 5 6 7 8
7 1 6 9 3 5 4 8
1 7 6
1 6 7 9
1 6 7 9 3
1 3 6 7 9 5
1 3 5 6 7 9
• <sub>Thực hiện với i=2 , …, n:</sub>
1. x = ai
2. j = i-1
3. Khi (j>0) Λ (x<aj)
3. 1 a<sub>j+1</sub>=a<sub>j</sub>
3. 2 j = j-1
5
• Số phép gán:
• Số phép so sánh:
<i><b>void insertionsort(elem a[], int n, int (*comp)(elem, elem))</b></i>
<i><b>{</b></i>
<i><b>int i, j, sz=sizeof(elem);</b></i>
<i><b>elem x;</b></i>
<i><b>for (i=1; i<n; i++)</b></i>
<i><b>memcpy(&x, &a[i], sz);</b></i>
<i><b>j = i-1;</b></i>
<i><b>while (j>=0 && comp(x, a[j])<0)</b></i>
<i><b>{</b></i>
<i><b>memcpy(&a[j+1], &a[j], sz);</b></i>
<i><b>j--;</b></i>
<i><b>}</b></i>
7
Nội dung phương pháp:
• Chọn phần tử nhỏ nhất trong dãy a<sub>i</sub>, …., an là ak
• Hốn đổi phần tử ai với ak.
Thực hiện với i = 1, ….., n-1 ta được dãy a1, ….,
1 2 3 4 5 6 7 8
7 1 6 9 3 5 4 8
1 7 6 9 3 5 4 8
1 3 6 9 7 5 4 8
1 3 4 9 7 5 6 8
1 3 4 5 7 9 6 8
1 3 4 5 6 9 7 8
9
• <sub>Với i=1 , …, n-1, thực hiện:</sub>
1. k=i
2. x = a<sub>k</sub>
3. Với j = i+1, …, n, thực hiện:
Nếu x>aj
– k=j
– x=ak
• Số phép gán:
• Số phép so sánh:
11
<i><b>void selectionsort(elem a[], int n, int (*comp)(elem, elem))</b></i>
<i><b>{ int i, j, k, sz=sizeof(elem);</b></i>
<i><b>elem x;</b></i>
<i><b>for (i=0; i<n-1; i++)</b></i>
<i><b>{</b></i>
<i><b>k = i;</b></i>
<i><b>memcpy(&x, &a[k], sz);</b></i>
<i><b>for (j=i+1; j<n; j++)</b></i>
<i><b>if (comp(x, a[j])>0)</b></i>
<i><b>{</b></i>
<i><b>k = j;</b></i>
<i><b>memcpy(&x, &a[k], sz);</b></i>
<i><b>}</b></i>
<i><b>memcpy(&a[k], &a[i], sz);</b></i>
<i><b>void selectionsort(elem a[], int n, int (*comp)(elem, elem))</b></i>
<i><b>{ int i, j, k, sz=sizeof(elem);</b></i>
<i><b>elem x;</b></i>
<i><b>for (i=0; i<n-1; i++)</b></i>
<i><b>{</b></i>
<i><b>k = i;</b></i>
<i><b>for (j=i+1; j<n; j++)</b></i>
<i><b>if (comp(a[k], a[j])>0)</b></i>
<i><b>k = j;</b></i>
<i><b>memcpy(&x, &a[k], sz);</b></i>
<i><b>memcpy(&a[k], &a[i], sz);</b></i>
<i><b>memcpy(&a[i], &x, sz);</b></i>
<i><b>}</b></i>
13
Nội dung phương pháp:
Duyệt qua dãy, nếu 2 phần tử kề nhau không
thứ tự thì hốn đổi
Thực hiện cho đến khi dãy có thứ tự
Thuật giải nổi bọt (Bubble sort)
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
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);
}
i=1;
do {
OK = 1;
for (j=n-1; j>=i; j--)
if (a[j]<a[j-1])
{
swap(a[j], a[j-1]);
OK = 0;
17
Nội dung phương pháp:
Thực hiện lặp 2 quá 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 cùng
làm điểm xuất phát cho quá trình tiếp theo
l = 1;
r = k = n-1;
do {
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
<i>Cải tiến từ phương pháp chọn</i>
Định nghĩa:
• Heap: Là cấu trúc cây nhị phân đầy đủ theo
nghĩa: các nút được bố trí tuần tự từ mức thấp
đến mức cao, từ trái qua phải
21
• Heap max (min): Là cấu trúc heap thỏa điều
kiện : mọi nút đều có khóa lớn (nhỏ) hơn 2 con
Ví dụ:
9
6
8
7 0 3
5
2
1
• Với dãy a1, a2, ….. an ta tổ chức thành cấu trúc
heap như sau:
ai có 2 con là a2i và a2i+1
Vẽ lại
a<sub>1</sub> a<sub>2</sub> a<sub>3</sub> a<sub>4</sub> a<sub>5</sub> a<sub>6</sub> a<sub>7</sub>
a<sub>1</sub>
a<sub>2</sub> a3
a<sub>6</sub>
a<sub>5</sub>
23
• Ta có ai với i=n/2+1, … n là các nút lá trên cây
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 <i><b>biến </b></i>
<i><b>đổi a</b><b>i</b></i> (với i=n/2, …, 1) thành heap max khi ai+1,
…, <i><b>a</b><b><sub>n</sub></b></i> thỏa heap max
a<sub>1</sub>
a<sub>2</sub> a3
a<sub>6</sub>
a<sub>5</sub>
a<sub>4</sub> a<sub>7</sub>
a<sub>10</sub>
a<sub>9</sub>
• Khi i=1 ta có dãy thỏa mãn tính chất heap max,
nghĩa là a1 là phần tử lớn nhất
• Để sắp thứ tự, phần tử lớn nhất phải nằm cuối
nên ta hoán đổi phần tử a1 với an
<i><b>• Biến đổi</b></i> a<i><b><sub>1</sub></b></i> thành heap max khi a<sub>2</sub>, …, <i><b>a</b><b><sub>n-1</sub></b></i> thỏa
heap max
25
4
9 7
1
8
6 0
3
2
5
9
8 7
1
4
6 0
3
2
5
9
8 7
1
4
6 0
3
2
5
3
8 7
1
4
6 0
9
2
5
27
8
6 7
1
4
5 0
9
2
3
2
6 7
1
4
5 0
9
8
2
6 7
1
4
5 0
9
8
3
2
7
6 2
1
4
5 0
9
8
29
• Tiếp tục thực hiện cho đến khi dãy có thứ tự
3
6 2
1
4
5 0
9
8
1. Khởi tạo
– x = a<sub>q</sub>
– i=q
– j=2i
– cont=true
2. Khi (j<=r) Λ cont, thực hiện:
2.1 Nếu (j<r) Λ (aj<aj+1) thì j=j+1
2.2 Nếu x<a<sub>j</sub> thì
– a<sub>i</sub> = a<sub>j</sub>
– i=j
– j=2i
31
1. Khởi tạo heap max ban đầu
Với i=n/2, …, 1. Thực hiện:
Biến đổi heap max(i, n)
2. Sắp thứ tự
– i=n
– Lặp
• Hốn đổi a1 với ai
• i = i-1
<i><b>void sift(elem a[ ], int q, int r, int (*comp)(elem, elem))</b></i>
<i><b>{</b></i>
<i><b>elem x;</b></i>
<i><b>int i, j, cont =1, sz = sizeof(elem);</b></i>
<i><b>i = q;</b></i>
<i><b>j = 2*i+1;</b></i> <i><b>//lưu ý</b></i>
<i><b>memcpy(&x, &a[i], sz);</b></i>
<i><b>while (j<=r && cont)</b></i>
<i><b>{</b></i>
<i><b>if (j<r && comp(a[j], a[j+1])<0) j++;</b></i>
<i><b>if (comp(x, a[j]) <0)</b></i>
<i><b>{</b></i>
<i><b>memcpy(&a[i], &a[j], sz);</b></i>
<i><b>i = j;</b></i>
<i><b>j = 2*i+1;</b></i> <i><b>//lưu ý</b></i>
<i><b>}</b></i>
<i><b>else</b></i>
33
<i><b>void heapsort(elem a[ ], int n, int (*comp)(elem, elem))</b></i>
<i><b>{</b></i>
<i><b>int i, sz = sizeof(elem);</b></i>
<i><b>elem x;</b></i>
<i><b>for (i=n/2-1; i>=0; i--)</b></i> <i><b>//lưu ý n/2-1 và 0</b></i>
<i><b>sift(a, i, n-1, comp);</b></i>
<i><b>i = n-1;</b></i>
<i><b>do {</b></i>
<i><b>memcpy(&x, &a[0], sz);</b></i> <i><b>//lưu ý a[0]</b></i>
<i><b>memcpy(&a[0], &a[i], sz);</b></i>
<i><b>memcpy(&a[i], &x, sz);</b></i>
<i><b>i--;</b></i>
<i><b>sift(a, 0, i, comp);</b></i> <i><b>//0</b></i>
• Cải tiến từ phương pháp đổi chổ
• Dựa trên phép phân hoạch:
• Chọn giá trị phân hoạch x thỏa:
Min { ai } ≤ x ≤ Max { ai }
– Dị tìm từ trái (l) qua phải phần tử ai ≥ x
– Dị tìm từ phải (r) qua trái phần tử aj ≤ x
– Nếu i < j thì hốn đổi ai với aj
• Tiếp tục thực hiện cho đến khi i>j
Kết quả dãy sẽ bị phân hoạch thành 2 dãy:
<i>Dãy từ l đến j mang giá trị ≤ x</i>
<i>Dãy từ i đến r mang giá trị ≥ x</i>
35
<i><b>void sort(elem a[ ], int l, int r, int (*comp)(elem, elem))</b></i>
<i><b>{</b></i>
<i><b>static elem x, t;</b></i>
<i><b>int i, j, sz = sizeof(elem);</b></i>
<i><b>i = l;</b></i>
<i><b>j = r;</b></i>
<i><b>memcpy(&x, &a[(l+r)/2], sz);</b></i>
<i><b>do {</b></i>
<i><b>while (comp(a[i], x)<0) i++;</b></i>
<i><b>while (comp(a[j], x)>0) j--;</b></i>
<i><b>if (i<=j)</b></i>
<i><b>{</b></i>
<i><b>memcpy(&t, &a[i], sz);</b></i>
<i><b>memcpy(&a[i], &a[j], sz);</b></i>
<i><b>memcpy(&a[j], &t, sz);</b></i>
<i><b>i++;</b></i>
<i><b>j--;</b></i>
<i><b>}</b></i>
<i><b>} while (i<=j);</b></i>
<i><b>void qsort(elem a[ ], int n, int (*comp)(elem, elem))</b></i>
<i><b>{</b></i>
37
• Viết
– Quick sort 1 lời gọi đệ quy
– Quick sort không đệ quy
– Chương trình nhập 1 dãy số ngun, đưa:
• Lẻ về đầu dãy và sắp thứ tự tăng