1. Trang chủ
  2. » Giáo Dục - Đào Tạo

DATA STRUCTURE and ALGORITHMS lab 03 sorting algorithms

56 19 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 56
Dung lượng 1,09 MB

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

Nội dung

Thuật toán Selection sort sắp xếp mảng bằng cách lần lượt chọn các phần tử nhỏ nhất chưa được sắp xếp trong mảng để đưa các phần tử vào vị trí đúng của nó.. Thuật toán dựa vào bài toán t

Trang 1

TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN TP.HCM

KHOA CÔNG NGHỆ THÔNG TIN



Subject: DATA STRUCTURE and ALGORITHMS

Lab 03: Sorting Algorithms

Class: 20CLC01

ID group: 01

Đỗ Thụy Phương Vy Nguyễn Lê Sơn Dương Thanh Giang Trần Nguyễn Lan Trinh

Trang 2

BẢNG ĐÁNH GIÁ THÀNH VIÊN Môn Cấu trúc dữ liệu & Giải thuật – Lớp 20CLC01

Giảng viên hướng dẫn:

Nguyễn Thanh Phương Nguyễn Ngọc Thảo Bùi Huy Thông Người thực hiện: Tất cả các thành viên trong nhóm

ID nhóm thực hiện: 01

% đóng góp của nhiệm

vụ vào tổng thể bài làm

Đánh giá két quả nhiệm vụ

1 20127098 Đỗ Thụy Phương Vy

Selection Sort* (20), Flash Sort***

(20), Comparision-Experimental run (Table fill) (40), Command 1+2 (30)

Insertion Sort* (20), Shell Sort** (20), Counting Sort*** (20), Comparision- Chart draw and comment (2 cái cuối) (20), Run time-Experimental run (Table fill) (2 cái đầu) (20), Command

4 (15)

3 20127486 Dương Thanh Giang

Bubble Sort* (20), Shaker Sort* (20), Radix Sort*** (20), Comparision- Chart draw and comment (2 cái đầu) (20), Run time-Experimental run (Table fill) (2 cái cuối) (20), Command

3 (15)

4 20127653 Trần Nguyễn Lan Trinh

Merge Sort** (20), Quick Sort** (20), Heap Sort** (20), Run time-Chart draw and comment (40), Command 5

(15)

1 Giới thiệu

Xin chào thầy cô, nhóm chúng em là nhóm 01 đến từ lớp

20CLC01 Hôm nay chúng em mang đến cho thầy cô đồ án

về đo độ phức tạp của thuật toán Mục đích của thuật toán là

để tính toán, chạy thuật toán và đo thời gian chạy của một

thuật toán, sau cùng dựa trên những kết quả có được và đưa ra

Trang 3

những kết luận về các thuật toán đó Nhóm của chúng em

chọn Set 2 (bao gồm 11 thuật toán): Selection Sort, Insertion

Sort, Bubble Sort, Shaker Sort, Shell Sort, Heap Sort, Merge Sort, Quick Sort, Counting Sort, Radix Sort and Flash Sort.

Sau quá trình học hỏi, tìm hiểu và tiếp thu thêm rất nhiều kiến thức mới, chúng em đã cùng nhau hoàn thành trọn vẹn đồ án

mà giảng viên đã giao Chúng em hiểu được những nguyên

lí cơ bản của những thuật toán sắp xếp, học được cách làm sao để đo được một thuật toán và tính toán được đầu vào và đầu ra, hiểu được trường hợp tốt nhất và trường hợp xấu nhất khi đưa một đầu vào vào

2 Cấu hình máy tính đã được sử dụng

 CPU: Intel® Core™ i7-10750H CPU @ 2.60GHz

 SSD: 512GB

 RAM: 16GB DDR4

 GPU: NVIDIA GeForce GTX 1650 Ti 4GB

 CPU: AMD Ryzen 7 3750H with Radeon Vega Mobile Gfx

 SSD: 256GB

 RAM: 8GB DDR4

 GPU: NVIDIA GeForce GTX 1650 4GB

 CPU: Intel® Core ™ i5 – 7200U CPU @ 2.50GHz

Trang 4

Thuật toán Selection

sort sắp xếp mảng bằng cách lần lượt chọn các phần tử nhỏ nhất chưa được sắp xếp trong mảng để đưa các phần tử vào vị trí đúng của nó Thuật toán dựa vào bài toán tìm phần tử nhỏ nhất và đổi chỗ các phần tử với nhau để đưa phân tử vào vị trí đúng của nó

- Bước 1 : Khởi tạo minVal = A[i]minVal = A[i], minInx = i

- Bước 2 : So sánh với các phần tử trong đoạn [i+1, n−1] Nếu

A[j]< minVal thì minVal = a[j], minInx = j

Trang 5

- Bước 3: Hoán vị A[i] và phần tử nhỏ nhất trong đoạn vừa tìm được

- Bước 4: Lặp lại các bước trên đến hết mảng

Mã giả:

For i = 0 to n-2

minVal = A[i]

minInx = i For j = i+1 to n-1

If A[j] < minVal then

minVal = A[j]

minInx = j endif

endfor A[minInx] = A[i]

A[i] = minVal endfor

Đánh giá độ phức tạp:

- Thời gian: O(n2)

- Không gian: O(1)

2 phần: một danh sách con đã được sắp xếp và phần khác l

à các phần tử không có thứ tự Giải thuật sắp xếp chèn sẽ thực hiện việc tìm kiếm liên tiếp qua mảng đó, và các phần

Trang 6

tử không có thứ tự sẽ được di chuyển và được chèn vào vị trí thích hợp trong danh sách con (của cùng mảng đó)

Mô tả: Để sắp xếp một mảng bất kì có kích thước n

theo thứ tự tăng dần thì:

1: Lặp lại từ arr [1] đến arr[n] trên mảng 2: So sánh phần tử hiện tại với phần tử phía trước nó 3: Nếu phần tử chính nhỏ hơn phần tử trước nó, thì tiếp tục l

ấy phần tử chính so sánh với các phần tử trước đó rồi di chuy

ển các phần tử lớn hơn lên một vị trí để tạo chỗ cho phần tử chính đang hoán đổi

Các bước làm:

Bước 1: Tạo vòng lặp từ vị trí thứ hai đến vị trí thứ n(để vị tr

í thứ nhất làm nơi so sánh cho vị trí thứ hai)

Bước 2: Tạo phần mảng với sắp xếp có 1 phần tử (phần tử đ

Bước 4: Tiếp tục lặp lại bước trên với những phần tử tiếp th

eo cho đến khi duyệt qua hết tất cả phần tử của mảng

Ví dụ thuật toán sắp xếp - (theo GeeksforGeeks)

Trang 7

 Mã giả:

Trang 8

Đánh giá độ phức tạp

- Theo thời gian : + Trường hợp tốt nhất: O(n) : khi các phần tử đã được sắp xếp

Trang 9

- Xuất phát từ phần tử cuối danh sách ta tiến hành so sánh với phần tử bên trái của nó Nếu phần tử đang xét có khóa nhỏ hơnphần tử bên trái của nó ta tiến đưa nó về bên trái của dãy bằng cách hoán vị với phần tử bên trái của nó Tiếp tục thực hiện như thế đối với bài toán có n phần tử thì sau n –1 bước ta thu được danh sách tăng dần.

 Mô tả:

- Xét lần lượt 2 phần tử liền kề nhau bắt đầu từ cuối mảng

 Nếu 2 phần tử này là nghịch thế của nhau a[i] > a[i – 1], tiến hành hoán vị đổi chỗ hai phần tử này

 Lặp lại điều trên sẽ đem được phần tử nhỏ nhất lên đầu mảng và loại phần tử này ra khỏi mảng đang xét

 Tiếp tục thực hiện lại các bước trên đối với mảng mới để đưa dần các phần tử nhỏ nhất về đầu mảng

 Thực hiện lại các thao tác cho đến khi mảng đang xétchỉ còn 1 phần tử duy nhất

Các bước:

- Bước 1 : i=0; //Phần tử đầu tiên

- Bước 2: Lần lượt so sánh và đổi chổ (nếu cần) từ phải sang

trái đối với các phần từ từ a[n] đến a[i] với biến gán j=n-i và lặp lại khi j>i

- Bước 3 : i=i+1

- Bước 4 : Nếu i < n, quay lại Bước 2.

Ngược lại, dừng, dãy đã cho đã sắp xếp đúng vị trí

Mã giả:

Trang 10

- Shaker Sort là một cải tiến của Bubble Sort.

- Sau khi đưa phần tử nhỏ nhất về đầu mảng sẽ đưa phần tử lớnnhất về cuối dãy Do đưa các phần tử về đúng vị trí ở cả hai đầu nên Shaker Sort sẽ giúp cải thiện thời gian sắp xếp dãy

số do giảm được độ lớn của mảng đang xét ở lần so sánh kế tiếp

Trang 11

Bước 2a: j = r; // đẩy phần tử nhỏ về đầu

mảng

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

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 các phần tử đã có thứ tự ở đầu

dãy

- Bước 2b: j = l; // đẩy phần tử lớn về cuối mảng

Trong khi (j < r) thực hiện

Nếu a[j] > a[j-1]: a[j] ↔ a[j+1];

k = j; // lưu lại nơi xảy ra

Trang 12

Ý tưởng: Shell Sort là một giải thuật sắp xếp mang lại

hiệu quả cao dựa trên giải thuật sắp xếp chèn (Insertion Sort) Giải thuật này tránh các trường hợp phải tráo đổi

vị trí của hai phần tử xa nhau

trong giải thuật sắp xếp chọn (nếu như phần tử nhỏ hơn

ở vị trí bên phải khá xa so với phần tử lớn hơn

bên trái)

Trang 13

Mô tả:

Shellsort hoạt động bằng cách sắp xếp các phần tử nằm xa nhau, sau đó

dần rút ngắn khoảng cách sắp xếp(gap), đều này giúp di chuyển các phầ

n tử đi một khoảng cách xa có thể giúp các phần tử đi về vị trí chính xác của mình hiệu quả hơn so với việc di chuyển qua từng phần tử liền kề. 

- Một số trình tự tối ưu được sử dụng là:

 Trình tự ban đầu của Shell: N/2, N/4,…,1

 Tăng dần Knuth: 1, 4, 13,…,(3k-1)/2

 Số gia tăng của Sedgewick: 1, 8, 23, 77, 281, 1073, 4193, 16577…4j+1+3·2j+1

 Số gia tăng của Hibbard: 1, 3, 7, 15, 31, 63, 127, 255, 511…

 Số gia tăng của Papernov & Stasevich: 1, 3, 5, 9, 17, 33, 65,

 Pratt: 1, 2, 3, 4, 6, 9, 8, 12, 18, 27, 16, 24, 36, 54, 81 …

- Để diễn giải các bước thực hiện thì chúng ta sẽ có ví dụ để dễ hình  dung. Giả sử chúng ta cần sắp xếp mảng phía dưới theo shell sort:

*Bước 1 : Chúng ta sẽ sử dụng trình tự ban đầu của shell (N/2, N/4,…

1) làm khoảng cách trong thuật toán

-Trong vòng lặp đầu tiên, nếu kích thước mảng là N=8 thì các phần

tử nằm trong khoảng N/2=4 sẽ được so sánh và hoán đổi vị trí nếu chúng không theo thứ tự

- Phần tử thứ 0 được so sánh với phần tử thứ 4

Trang 14

- Nếu phần tử thứ 0 lớn hơn phần tử thứ 4 thì phần tử thứ 4 được lư

u trữ đầu tiên trong biến tạm thời và phần tử thứ 0

(tức là phần tử lớn hơn) được lưu trữ ở vị trí thứ 4 và phần tử được lưu trữ trong tạm thời được lưu trữ ở vị trí thứ 0

(Tức là hoán đổi hai phần tử cho nhau)

- Quá trình này tiếp tục cho tất cả các phần tử còn lại

Sau khi sắp xếp, mảng sẽ như thế này:

*   Bước 2 :

Trong vòng lặp thứ hai, một khoảng N/4=8/4=2 được thực hiện và một l

ần nữa các phần tử nằm trong các khoảng này được sắp xếp

Trang 15

Sau khi sắp xếp, mảng sẽ như thế này:

* Bước 3 : Cuối cùng, khi khoảng là N/8 = 8/8 =

1 thì các phần tử của mảng nằm trong khoảng 1 được sắp xếp Shell Sort

sử dụng giải thuật sắp xếp chèn để sắp xếp mảng

Trang 17

-> Tóm lại với shell sort, chúng ta có nhiều cách sử dụng khi dùng n hiều cách tính khoảng cách với nhau

nhưng tất cả sẽ được thực hiện một cách tổng quát như sau:

Bước 1: Sử dụng vòng lặp với khoảng cách giảm dần giữa các phần tử s

ắp xếp để tách ra các phần tử để sắp xếp

Bước 2 : Sử dụng vòng lặp với mỗi khoảng được chia

trong mảng rồi sắp xếp tất cả phần tử trong khoảng ấy

Bước 3: Tiếp tục với việc giảm khoảng cách dần dần để tách ra các kho

ảng rồi sắp xếp cho đến khi khoảng cách = 1

Bước 4: Khi khoảng cách = 1, dùng Insertion sort để sắp xếp lại

Source code: (theo việc dùng trình tự ban đầu của Shell: N/2, N/4,…,1)

Đánh giá độ phức tạp

- Theo thời gian : do có nhiều cách tính khoảng cách khác nhau

nên thời gian sẽ khác nhau

+ Trường hợp tốt nhất: O(nlognnlog n) – O (nlog2nnlog2 n )

+Trung bình: tùy theo cách chia khoảng cách

+Trường hợp xấu: O(nlog2nnlog2 n) – O(n2n2)

Trang 18

trong trường hợp tệ nhất của các khoảng cách trong Shell sort (theo  Wiki)

- Không gian bộ nhớ sử dụng : O(1),O(n)

 Ứng dụng:

- Việc gọi một ngăn xếp là tốn kém

Thư viện uClibc sử dụng kiểu thuật toán sắp xếp này

- Kỹ thuật đệ quy vượt quá giới hạn cho phép Trình nén bzip2 sử dụng kiểu sắp xếp này

- Sắp xếp chèn không hoạt động tốt khi các phần tử gần bằng nhau nằm

Trang 19

Theo Wikipedia, một Binary

Heap được gọi là hoàn chỉnh khi trong đó các mục được lưu trữ the

o một thứ tự đặc biệt sao cho giá trị trong nút cha lớn hơn( nếu là Max Heap) hoặc nhỏ hơn(nếu là Min Heap)

so với giá trị trong hai nút con của nó

Binary Heap có thể được minh họa bằng ảnh sau:

Nguồn ảnh: Wikipedia

Một Heap được biểu diễn dưới dạng mảng có:

+ Gốc của cây là a[0]

+ Với một nút cha a[i], con trái của a[i] (nếu có) là a[2*i + 1] và con phải của a[i] (nếu có) là a[2*i + 2]

Max Heap: a[cha] >= a[con]

Min Heap: a[cha] <= a[con]

Cách tính số phần tử trong Heap có con được dựa theo công thức: n/2 Các phần tử còn lại không có con

Mô tả:

Trang 20

Để sắp xếp một mảng theo thứ tự, ta cần xây dựng cấu trúc Binary Heap để tìm ra giá trị lớn nhất (nếu mảng cần xếp theo thứ tự tăng dần) hoặc ngược lại tìm giá trị nhỏ nhất (nếu mảng cần xếp theo th

Các bước: (ứng với sắp xếp mảng tăng dần)

+ Bước 1 : Xây dựng cấu trúc Heap cho các phần tử có nút con để t

ìm được phần tử lớn nhất a[i]>= a[2i +1] và a[i]>=a[2i+2]

(nếu có nút con phải) Từ vị trí index: n/2 –

1 trở về 0 là các nút có con nên quá trình sẽ bắt đầu bằng việc xây dựng cấu trúc Binary Heap từ a[n/2 -1] đến a[0]

Biểu diễn dưới dạng mã giả:

Xây dựng cấu trúc Binary Heap ở nút cha i:

void Heapify(int* a, int n, int i)

int max = left;

if (right<n && a[right]>a[max])

Trang 21

+ Bước 2: Hoán đổi vị trí a[0] với a[i] và thực hiện quá trình Heap

ify nhưng không xét a[i], sau đó tiếp tục giảm i:

Hình minh họa một ví dụ của Heap sort:

Trang 24

Nguồn ảnh: Heap Sort Image - Imgur

Độ phức tạp thời gian: O(nlogn)

(trong đó: Heapify O(logn), vòng lặp for kết hợp với Heapify =

Conquer) bằng việc chia mảng nhiều lần để tạo thành các mảng co

n rồi gộp lại theo thứ tự cho đến khi đã thống nhất các mảng con thành 1 mảng

Thuật toán Chia để trị (Divide and Conquer

Strategy):

tính, chia để trị là một mô hình thiết kế thuật toán quan trọng dựa t

rên đệ quy với nhiều phân nhánh Thuật toán chia để trị hoạt động bằng cách chia bài toán thành nhiều bài toán nhỏ hơn thuộc cùng th

ể loại, cứ như vậy lặp lại nhiều lần, cho đến khi bài toán thu được đ

ủ đơn giản để có thể giải quyết trực tiếp

Sau đó lời giải của các bài toán nhỏ được tổng hợp lại thành lời giả

i cho bài toán ban đầu

Thuật toán Merge sort lặp đi lặp lại quá trình chia mảng thành 2 mảng con và tiếp tục chia cho tới khi các mảng con chỉ chứa 1 phần tử Sau đó gộp 2 mảng con nhỏ thành mảng đã sắp xếp và tiếp tục gộp mảng tạo thành với 1 mảng tạo thành khác Việc gộp nửa mảng kết thúc khi ta chỉ còn 1 mảng duy nhất đã sắp xếp Các quá trình chia mảng và gộp mảng được thực hiện bằng Đệ quy

Minh họa thuật toán Merge sort theo hình vẽ: 

Trang 25

Nguồn ảnh: programiz.com

Các bước:

Thuật toán Merge sort chủ yếu dựa trên 2 quá trình là chia mảng rathành các mảng con và gộp các mảng con lại một cách có thứ tự

+ Quá trình 1: Chia mảng thành các mảng con

Lặp đi lặp lại việc chia mảng thành 2 mảng con cho đến khi tới giaiđoạn các mảng con chỉ có 1 phần tử

void mergeSort(int* arr, int left, int right) {

if (left < right) {

Trang 26

int mid = (left + right) / 2;

mergeSort(arr, left, mid);

mergeSort(arr, mid + 1, right);

merge(arr, left, mid, right);

}

}

Theo mã giả trên, mergeSort là hàm chia mảng được truyền vào ban đầu left = 0 và right = n-1 Sau khi việc phân chia kết thúc, quátrình 2 (hàm merge) sẽ tiếp tục

+ Quá trình 2: Kết hợp các mảng con với nhau một cách có thứ tự

cho đến khi có được 1 mảng hoàn chỉnh

Hàm merge vận hành như sau:

1 Tạo ra mảng leftArray và rightArray copy từ mảng ban đầu Truyền vào cho hàm merge các mảngleft, mid và right để đánh dấu index của mảng copy Mảng leftArray sẽ copy từ index left đến index mid của mảng arr Mảng rightArray copy từ index mid +

1 đến right của mảng Arr

void merge(int* arr, int left, int mid, int right) {

int nLeft = mid - left + 1;

int nRight = right - mid;

int* leftArray = new int[nLeft];

int* rightArray = new int[nRight];

for (int i = 0; i < nLeft; i++) {

leftArray[i] = arr[left + i];

} for (int j = 0; j < nRight; j++) {

Trang 27

if (leftArray[i] <= rightArray[j]) {

arr[k] = leftArray[i];

i++;

} else {

arr[k] = rightArray[j];

j++;

} k++;

}

3 Đặt các phần tử còn sót lại sau khi kết thúc quá trình so sánh và đặt:

while (i < nLeft) { arr[k] = leftArray[i];

i++;

k++;

} while (j < nRight) { arr[k] = rightArray[j];

Độ phức tạp thời gian: O(nlogn)

Độ phức tạp không gian: O(n)

8-QuickSort:

Ý tưởng: Quick

sort là một thuật toán sắp xếp chia để trị (Divide and Conquer

Trang 28

algorithm) bằng cách chọn một phần tử trong mảng làm pivot (điểm đánh dấu) và chia mảng ra thành hai mảng con dựa vào pivot đã chọn Quá trình được lặp đi lặp lại với các mảng con

Mô tả: Chọn một phần tử trong mảng làm pivot

(điểm đánh dấu) và chia mảng đã cho thành hai mảng con dựa v

ào pivot đó (mảng các số lớn hơn pivot và mảng các số nhỏ hơn pivot) Có một số cách chọn pivot:

left và right là hai phần tử thuộc rìa bên trái và bên phải của mảng

Bước 2: Nếu left >= right -> Tiến đến bước 7

Trang 29

Bước 3 : Chọn pivot: chọn giá trị phần tử ở giữa mảng làm pivot C

ho hai con chạy i, j xuất phát từ left và right

Bước 4: Cho i tăng dần tới khi a[i]>= pivot Cho

j giảm dần tới khi a[j]<=pivot

Bước 5: Hoán vị a[i], a[j]

Sau đó tiếp tục tăng i lên 1 đơn vị và giảm j xuống 1 đơn vị

Bước 6: Nếu i<= j quay lại bước 4 Nếu i>j,

chia mảng thành hai phần với mảng con 1 có left là 0,

right là j; mảng con 2 có left là i, và right vẫn là right

Quay lại bước 2

Bước 7: Kết thúc thuật toán

Hình minh họa thuật toán Quick sort (Pivot là giá trị ở giữa)

(Nguồn: Chuong Le Hoang – WordPress.com)

Ngày đăng: 24/02/2022, 05:59

TRÍCH ĐOẠN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w