THUẬT TOÁN BUBBLE SORT • Ý tưởng của thuật toán • Ví dụ minh họa • Minh họa thuật toán sử dụng ngôn ngữ C++ • Đánh giá thuật toán 1. Ý tưởng của thuật toán bubble sort Thuật toán sắp xếp bubble sort thực hiện sắp xếp dãy số bằng cách lặp lại công việc đổi chỗ 2 số liên tiếp nhau nếu chúng đứng sai thứ tự (số sau bé hơn số trước với trường hợp sắp xếp tăng dần) cho đến khi dãy số được sắp xếp. 2. Ví dụ minh họa Giả sử chúng ta cần sắp xếp dãy số 5 1 4 2 8 này tăng dần. Lần lặp đầu tiên: ( 5 1 4 2 8 ) –> ( 1 5 4 2 8 ), Ở đây, thuật toán sẽ so sánh hai phần tử đầu tiên, và đổi chỗ cho nhau do 5 > 1. ( 1 5 4 2 8 ) –> ( 1 4 5 2 8 ), Đổi chỗ do 5 > 4 ( 1 4 5 2 8 ) –> ( 1 4 2 5 8 ), Đổi chỗ do 5 > 2 ( 1 4 2 5 8 ) –> ( 1 4 2 5 8 ), Ở đây, hai phần tử đang xét đã đúng thứ tự (8 > 5), vậy ta không cần đổi chỗ.
Trang 1BỘ THÔNG TIN VÀ TRUYỀN THÔNG
HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG
-BÀI TIỂU LUẬN HỌC PHẦN: CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT
CÁC THUẬT TOÁN SẮP XẾP ĐƠN GIẢN
Nhóm: 16 Nguyễn Đình Linh- B17DCCN376 Đoàn Đức Toàn- B17DCCN607 Trần Khánh Tùng- B17DCCN667 Bùi Đăng Quang-B17DCCN502
Hà Nội, ngày 05 tháng 05 năm 2019
Mục lục
Trang 2Insertion sort:……… 6 Selection sort:……… 9 Tài liệu tham khảo:………12
Trang 3THUẬT TOÁN BUBBLE SORT
• Ý tưởng của thuật toán
• Ví dụ minh họa
• Minh họa thuật toán sử dụng ngôn ngữ C++
• Đánh giá thuật toán
1 Ý tưởng của thuật toán bubble sort
Thuật toán sắp xếp bubble sort thực hiện sắp xếp dãy số bằng cách lặp lại công việc đổi chỗ 2 số liên tiếp nhau nếu chúng đứng sai thứ tự (số sau bé hơn số trước với trường hợp sắp xếp tăng dần) cho đến khi dãy số được sắp xếp
2 Ví dụ minh họa
Giả sử chúng ta cần sắp xếp dãy số [5 1 4 2 8] này tăng dần
Lần lặp đầu tiên:
( 5 1 4 2 8 ) –> ( 1 5 4 2 8 ), Ở đây, thuật toán sẽ so sánh hai phần tử đầu tiên, và đổi chỗ
cho nhau do 5 > 1
( 1 5 4 2 8 ) –> ( 1 4 5 2 8 ), Đổi chỗ do 5 > 4
( 1 4 5 2 8 ) –> ( 1 4 2 5 8 ), Đổi chỗ do 5 > 2
( 1 4 2 5 8 ) –> ( 1 4 2 5 8 ), Ở đây, hai phần tử đang xét đã đúng thứ tự (8 > 5), vậy ta
không cần đổi chỗ
Lần lặp thứ 2:
( 1 4 2 5 8 ) –> ( 1 4 2 5 8 )
( 1 4 2 5 8 ) –> ( 1 2 4 5 8 ), Đổi chỗ do 4 > 2
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
Bây giờ, dãy số đã được sắp xếp, Nhưng thuật toán của chúng ta không nhận ra điều đó ngay được Thuật toán sẽ cần thêm một lần lặp nữa để kết luận dãy đã sắp xếp khi và khi khi nó đi từ đầu tới cuối mà không có bất kỳ lần đổi chỗ nào được thực hiện
Lần lặp thứ 3:
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
Trang 43 Minh họa thuật toán sử dụng ngôn ngữ C++
+ Vd1:
#include<iostream>
using namespace std;
void input_func(int A[], int &n) {
cout << "nhap so phan tu cua mang
n:";
cin >> n;
for (int i = 0; i<n; i++) {
cout << "phan tu A[" << i << "]" << "=";
cin >> A[i];
}
}
// hàm sắp xếp bubblesort;
void bubblesort(int A[], int &n) {
int i = n;
bool flag = false;
while (i > 0)
{
flag = false; //khởi tạo lại giá trị cờ flag =
false;
for (int j = 0; j < i-1;j++){
if (A[j] > A[j + 1]){
int temp = A[j];
A[j] = A[j + 1];
A[j + 1] = temp;
flag = true;
}
}
if (flag == false){ //nếu không có lần đổi chỗ nào, danh sách đã sắp xếp xong
break;
} Else //nếu có ít nhất một lần đổi chỗ, danh sách chưa sắp xếp xong
{ i = i - 1;
} } } void output_func(int A[], int &n) { for (int i = 0; i < n; i++)
{ cout << A[i] << " ";
}
}
int main() { int A[100], n;
input_func(A, n);
cout << "mang ban dau la:";
output_func(A, n);
bubblesort(A, n);
cout << "mang khi sap xep la:";
output_func(A, n);
cin.get();
getchar();
return 0;
}
Nhập : 64 90 25 34 22 12 11
Xuất : 11 12 22 25 34 64 90
+ Vd2:
#include<iostream>
using namespace std;
int main() {
Trang 5int a[50],n,i,j,temp;
cout<<"so luong: ";
cin>>n;
cout<<"nhap tung so: ";
for(i=0;i<n;++i)
cin>>a[i];
for(i=1;i<n;++i) {
for(j=0;j<(n-i);++j)
if(a[j]>a[j+1]) {
temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;
} }
cout<<"ket qua bubble sort:"; for(i=0;i<n;++i)
cout<<" "<<a[i];
return 0;
}
+ Kết quả :
+ nhập : 5
8 5 6 7 2
+ xuất : 2 5 6 7 8
4 Đánh giá thuật toán sắp xếp bubble sort:
• Số phép so sánh không phụ thuộc vào tình trạng ban đầu của dãy Có thể ước lượng số phép so sánh bằng: (n-1) + (n-2) + + 1 = n(n – 1)/2.
• Số phép hoán vị (3 phép gán) phụ thuộc tình trạng ban đầu Trong trường hợp tốt nhất, tức dãy đã được sắp xếp hoàn toàn thì không cần phải hoán vị, nên số phép hoán vị là: 0.
• Trường hợp xấu nhất, tức dãy có thứ tự ngược với yêu cầu Mỗi lần so sánh ta lại phải hoán vị nên số phép hoán vị là: n(n - 1)/2.
Độ phức tạp thuật toán :
• Trường hợp tốt: O(n)
• Trung bình: O(n^2)
• Trường hợp xấu: O(n^2)
• Không gian bộ nhớ sử dụng: O(1)
Trang 6THUẬT TOÁN INSERTION SORT
• Ý tưởng của thuật toán
• Ví dụ minh họa
• Minh họa thuật toán sử dụng ngôn ngữ C++
• Đánh giá thuật toán
1 Ý tưởng của thuật toán Insertion Sort
Thuật toán insertion sort thực hiện sắp xếp dãy số theo cách duyệt từng phần tử và chèn từng phần tử đó vào đúng vị trí trong mảng con(dãy số
từ đầu đến phần tử phía trước nó) đã sắp xếp sao cho dãy số trong mảng sắp đã xếp đó vẫn đảm bảo tính chất của một dãy số tăng dần.
Khởi tạo mảng với dãy con đã sắp xếp có k = 1 phần tử(phần tử đầu tiên, phần tử có chỉ số 0)
Duyệt từng phần tử từ phần tử thứ 2, tại mỗi lần duyệt phần tử ở chỉ số i thì đặt phần tử đó vào một vị trí nào đó trong đoạn từ [0…i] sao cho dãy số từ [0…i] vẫn đảm bảo tính chất dãy số tăng dần Sau mỗi lần duyệt, số phần tử đã được sắp xếp k trong mảng tăng thêm 1 phần tử
Lặp cho tới khi duyệt hết tất cả các phần tử của mảng
1 Ví dụ minh họa
Trang 7Hàng đầu tiên mô phỏng trạng thái ban đầu của mảng(dãy số chưa sắp xếp) Từ hàng thứ 2 trở đi, ta tìm chèn số đang xét vào vị trí thích hợp để đảm bảo dãy số vẫn tăng dần Và khi lặp hết tất cả các số trong mảng, ta có trạng thái
đã sắp xếp ở hàng cuối cùng
2 Minh họa thuật toán sử dụng ngôn ngữ C++
• VD:
void InsertionSort(int a[] , int n)
{
for(int i=1 ; i<n ; i++)
{
Int x = a[ i ];
Int j = i;
While( j > 0 && a[ j – 1] > x )
{
a[ j ] = a[ j -1 ] ;
j ;
}
a[ j ] = x;
}
}
3 Đánh giá thuật toán
• Trong trường hợp tốt nhất thuật toán sữ dụng n-1 phép so sánh và 0 lần hoán vị.
Trang 8• Trung bình thuật toán sử dụng n2/4 phép so sánh và n2/4 lần hoán vị.
• Trong trường hợp xấu nhất thuật toán sử dụng n2/2 phép so sánh và n2/2 lần hoán vị.
• Thuật toán thích hợp đối với mảng đã được sắp xếp một phần hoặc mảng có kích thước nhỏ.
Độ phức tạp thuật toán :
• Trường hợp tốt: O(n)
• Trung bình: O(n^2)
• Trường hợp xấu: O(n^2)
Không gian bộ nhớ sử dụng: O(1)
Trang 9THUẬT TOÁN SELECTION SORT
• Ý tưởng của thuật toán
• Ví dụ minh họa
• Minh họa thuật toán sử dụng ngôn ngữ C++
• Đánh giá thuật toán
1 Ý tưởng của thuật toán selection sort
Thuật toán thực hiện sắp xếp dãy các đối tượng bằng cách lặp kiểu chọn Thuật toán thực hiện sắp xếp dãy các đối tượng bằng cách lặp lại việc tìm kiếm phần tử có giá trị nhỏ nhất
từ thành phần chưa được sắp xếp trong mảng và đặt nó vào vị trí đầu tiên của dãy Trên dãy các đối tượng ban đầu, thuật toán luôn duy trì hai dãy con:
Dãy con đã được sắp xếp: là các phần tử bên trái của dãy
Dãy con chưa được sắp xếp là các phần tử bên phải của dãy Quá trình lặp sẽ kết thúc khi dãy con chưa được sắp xếp chỉ còn lại đúng một phần tử
Các bước thực hiện của thuật toán selection sort
Bước 1: Thiết lập MIN về vị trí 0
Bước 2: Tìm kiếm phần tử nhỏ nhất trong danh sách
Bước 3: Tráo đổi với giá trị tại vị trí MIN
Bước 4: Tăng MIN để trỏ tới phần tử tiếp theo
Bước 5: Lặp lại cho tới khi toàn bộ danh sách đã được sắp xếp
2 Ví dụ minh họa
Giả sử chúng ta cần sắp xếp dãy số [5 1 4 2 8] này tăng dần
Từ vị trí đầu tiên trong danh sách đã được sắp xếp, toàn bộ danh sách được duyệt một cách liên tục Vị trí đầu tiên có giá trị 5, chúng ta tìm toàn bộ danh sách và thấy rằng 1
là giá trị nhỏ nhất
Lần lặp đầu tiên:
( 5 1 4 2 8 ) –> ( 1 5 4 2 8 ), Do đó, chúng ta thay thế 5 với 1 Sau một vòng lặp, giá trị 1
thay thế cho giá trị 5 tại vị trí đầu tiên trong danh sách đã được sắp xếp Chúng ta tráo đổi hai giá trị này
Lần lặp thứ 2:
( 1 5 4 2 8 ) –> ( 1 2 4 5 8 ), Tại vị trí thứ hai, giá trị 5, chúng ta tiếp tục quét phần còn lại
của danh sách theo thứ tự từng phần tử Chúng ta thấy rằng 2 là giá trị nhỏ nhất thứ hai trong danh sách và nó nên xuất hiện ở vị trí thứ hai Chúng ta tráo đổi hai giá trị này Sau hai vòng lặp, hai giá trị nhỏ nhất đã được đặt tại phần đầu của danh sách đã được sắp xếp
Tiến trình tương tự sẽ được áp dụng cho phần còn lại của danh sách Phía dưới minh họa cho các tiến trình này
Lần lặp thứ 3:
( 1 2 4 5 8) –> ( 1 2 4 5 8), Ở đây, hai phần tử đang xét đã đúng thứ tự, vậy ta không cần đổi chỗ
Trang 10Lần lặp thứ 4:
( 1 4 2 5 8 ) –> ( 1 4 2 5 8 ), Ở đây, hai phần tử đang xét đã đúng thứ tự, vậy ta không cần đổi chỗ
3 Minh họa thuật toán sử dụng ngôn ngữ C++
+ Vd1:
#include<iostream>
using namespace std;
void swap(int &xp, int &yp)
{
int temp = xp;
xp = yp;
yp = temp;
}
// Hàm selection sort
void selectionSort(int arr[], int &n)
{
int i, j, min_idx;
// Di chuyen ranh gioi cua mang dã
sap xep và chua sap xep
for (i = 0; i < n-1; i++)
{
// Tìm phan tu nho nhat trong mang
chua sap xep
min_idx = i;
for (j = i+1; j < n; j++)
if (arr[j] < arr[min_idx])
min_idx = j;
// Ðoi cho phan tu nho nhat voi phan
tu dau tiên
swap(arr[min_idx], arr[i]);
}
}
/* Hàm xuat mang */
void printArray(int arr[], int &size)
{ int i;
for (i=0; i < size; i++) printf("%d ", arr[i]);
printf("\n");
}
/* Hàm nhap mang */
void inputArray(int arr[], int &size) {
cout << "nhap so phan tu cua mang n:";
cin >> size;
for (int i = 0; i<size; i++) {
cout << "phan tu A[" << i
<< "]" << "=";
cin >> arr[i];
} }
int main() {
int arr[100];
int n;
inputArray(arr,n);
selectionSort(arr, n);
printf("Sorted array: \n");
printArray(arr, n);
return 0;
}
+ Kiểm tra kết quả:
Trang 11Nhập : 64 90 25 34 22 12 11
Xuất : 11 12 22 25 34 64 90
Trang 124 Đánh giá thuật toán sắp xếp selection sort :
Để chọn được phần tử nhỏ nhất, ta cần duyệt qua n phần tử (tốn n-1 phép so sánh) và sau đó hoán vị nó với phần tử đầu tiên của dãy hiện hành Để tìm phần tử nhỏ nhất tiếp theo, ta cần duyệt qua n-1 phần tử (tốn n-2 phép so sánh) Cứ như vậy, ta thấy ngay thuật toán sẽ tốn (n-1) + (n-2) + … + 1 = n(n-1)/2 = O(n2) phép so sánh.
Mỗi lần duyệt, ta luôn phải hoán vị 1 lần (1 hoán vị tương đương với 3 phép gán), nghĩa là thuật toán sẽ tốn 3(n-1) + 3(n-2) + … + 3 = 3n(n-1)/2 = O(n2) phép gán.
Tổng kết lại, ta luôn có độ phức tạp của thuật toán Selection Sort là O(n2) trong mọi trường hợp.
Độ phức tạp thuật toán:
• Trường hợp tốt: O(n^2)
• Trung bình: O(n^2)
• Trường hợp xấu: O(n^2)
• Không gian bộ nhớ sử dụng: O(1)
Tài liệu tham khảo
Trang 13• https://en.wikipedia.org/wiki/Selection_algorithm