Thuật toán sử dụng tưtưởng chia để trị nên còn được ví là part sort và thuộc loại sắp xếp phức tạp.. Từ dãyban đầu, người ta sẽ chia dãy thành hai phần nhỏ theo một quy tắc xác định, từ
Trang 1TRƯỜNG ĐẠI HỌC KIẾN TRÚC HÀ NỘIKHOA CÔNG NGHỆ THÔNG TIN
Trang 2Mục lục :
1 Giới thiệu 3
2 Ý tưởng thuật toán 3
3 Các bước thực hiện giải thuật 6
4 Cài đ t gi i thu tặảậ 8
5 Độ phức tạp của thuật toán 9
6 Đánh giá thu t toánậ 9
6.1 u đi mƯể 9
6.2 Nhược đi mể 10
7 Bài t p quick-sortậ 10
Trang 3Sắp xếp nhanh (Quick Sort)1 Giới thiệu
Thuật toán sắp xếp nhanh hay còn gọi là QuickSort Algorithm là một trong 6thuật toán sắp xếp thông dụng nhất của khoa học máy tính Thuật toán sử dụng tưtưởng chia để trị nên còn được ví là part sort và thuộc loại sắp xếp phức tạp Từ dãyban đầu, người ta sẽ chia dãy thành hai phần nhỏ theo một quy tắc xác định, từ đógiúp cải thiện tốc độ của việc săp xếp.
Hình minh họa Quick sort
Thuật toán sắp xếp nhanh được phát triển vào năm 1959 bởi Tony Hoare khi ôngđang là sinh viên thỉnh giảng tại Đại học Tổng hợp Moscow Khi đó, Hoare đangthực hiện một dự án về máy dịch cho Phòng thí nghiệm Vật lý Quốc gia Là mộtphần của quá trình dịch thuật, ông phải sắp xếp các từ của các câu tiếng Nga trướckhi tra cứu chúng trong từ điển Nga-Anh đã được sắp xếp theo thứ tự bảng chữ cáivà được lưu trữ trong băng từ Để hoàn thành nhiệm vụ này, ông đã phát hiện raQuick Sort và sau đó đã xuất bản mã năm 1961.
Quick Sort là thuật toán đáng được quan tâm và thực sự rất quan trọng Hầu hếttrong các thư viện của các ngôn ngữ lập trình hiện nay đều có sẵn thuật toán này.
2 Ý tưởng thuật toán
Quicksort là thuật toán ứng dụng ý tưởng chia nhỏ để trị Đầu tiên nó chia mảng
đầu vào thành hai mảng con một nửa nhỏ hơn, một nửa lớn hơn dựa vào một phầntử trung gian Sau đó, nó sắp xếp đệ quy các mảng con để giải quyết bài toán.
Trang 4Mấu chốt của thuật toán ở việc chia mảng con hay còn gọi là thuật toán phân đoạn.Cách giải quyết có thể tóm tắt như sau:
Chọn một phần tử trong mảng làm phần tử trung gian để chia đôi mảnggọi là pivot Thông thường ta thường chọn phần tử đầu tiên, phần tử ởgiữa mảng hoặc phần tử cuối cùng của mảng để làm pivot.
Phân đoạn: di chuyển phần tử có giá trị nhỏ hơn pivot về một bên, tất cảcác phần tử có giá trị lớn hơn pivot xếp về một bên (các giá trị bằng pivotcó thể đi theo một trong hai cách).
Sau bước phân đoạn di chuyển pivot về đúng vị trí giữa của 2 mảng con
Áp dụng đệ quy các bước phân đoạn trên cho hai mảng con để thực hiệnsắp xếp
Trường hợp dừng của đệ quy là khi các mảng con có kích thước bằng 0 hoặc 1, khiđó nó đã được sắp xếp theo định nghĩa, vì vậy chúng không bao giờ cần phải sắpxếp.
Trang 5Lưu đồ thuật toán sắp xếp nhanh:3 Các bước thực hiện giải thuật
Giả sử ta có một dãy các phần tử như sau:
Left = 0; right = 7; Ở ví dụ này ta lấy một phần tử làm khóa, ở đây mình chọn phầntử khóa là A[(0+7)/2] = A[3] = 30 Cho i chạy từ trái sang phải, bắt đầu từ vị trí 0Cho j chạy từ phải sang trái, bắt đầu từ vị trí 7 Quá trình duyệt từ bên trái với biếnduyệt i sẽ dừng lại ở 56 (i=2), vì đây không phải là phần tử nhỏ hơn khóa Quá trìnhduyệt từ bên phải với biến duyệt j sẽ dừng lại ở 18 (j=7) vì đây là phần tử nhỏ hơnkhóa Tiến hành đổi chỗ 2 phần tử cho nhau.
Quá trình duyệt tiếp tục Khóa ở đây vẫn là 30 Ta tiếp tục tăng biến duyệt i và giảmbiến duyệt j, nhận thấy biến duyệt i chạy đến 30 (i=3), còn biến duyệt j dừng lại ở24 (j=6) Tiến hành đổi chỗ 2 phần tử cho nhau.
Trang 6Quá trình duyệt tiếp tục Khóa ở đây vẫn là 30 Tiếp tục tăng biến duyệt i và giảmbiến duyệt j, nhận thấy biến duyệt i chạy đến 32 (i=5), còn biến duyệt j dừng lại ở30(j=6) Tiến hành đổi chỗ 2 phần tử cho nhau.
Quá trình duyệt tiếp tục Khóa ở đây vẫn là 30 Tiếp tục tăng biến duyệt i và giảmbiến duyệt j, nhận thấy biến duyệt i và j cùng chạy đến 30 Lúc này ta sẽ chia mảngtrên ra làm 2 mảng con A[0 4] và A[5 7], vì ta thấy A[5 7] đã được sắp xếp tăngdần rồi nên ta sẽ xét A[0 4] A[0 4] = [28, 16, 18, 24, 17] Lặp lại những bước trênvới phần tử được chọn là khóa là A[(0+4)/2] = A[2] = 18 left = 0; right = 4; Cho ichạy từ trái sang phải bắt đầu từ vị trí 0 Cho j chạy từ phải sang trái bắt đầu từ vị trí4 Quá trình duyệt từ bên trái với biến duyệt i sẽ dừng lại ở 28(i=0) vì đây khôngphải là phần tử nhỏ hơn khóa Quá trình duyệt từ bên phải với biến duyệt j sẽ dừnglại ở 17 (j=4) vì đây là phần tử không lớn hơn khóa Tiến hành đổi chỗ 2 phần tửcho nhau.
Trang 7Quá trình duyệt tiếp tục Tăng biến duyệt i và giảm biến duyệt j Lúc này i = j nên tasẽ chia mảng trên ra làm 2 mảng con A[0 1] và A[2 4] Ta thấy A[2 4] đã được sắpxếp tăng dần rồi, nên ta chỉ xét A[0 1], vì A[0] > A[1] nên ta đổi chỗ 2 phần tử chonhau và được mảng sắp xếp tăng dần cuối cùng:
4 Cài đặt giải thuật
Như đã nói ở trên, Quick sort cũng là một thuật toán đệ quy, bao gồm việc chiamảng thành 2 mảng con thỏa mãn yêu cầu trên, sau đó thực hiện lời gọi đệ quy với 2mảng con vừa tạo được Giả sử mảng được giới hạn bởi 2 tham số left và right chobiết chỉ số đầu và cuối của mảng, khi đó thuật toán được cài đặt như sau:
void QuickSort(int left, int right) {
int x = A[(left + right)/2]; //luu gia tri phan tugiua mang
int i = left; int j = right;
Trang 85 Độ phức tạp của thuật toán
Do hiệu quả của thuật toán phụ thuộc rất nhiều vào việc phần tử nào được chọn làphần tử chốt nên độ phức tạp thuật toán cũng phụ thuộc vào đó mà khác nhau.
Phân đoạn không cân bằng: không có phần nào cả, một bài toán con có kíchthước n-1 và bài toán kia có kích thước là 0 Đó là trường hợp xấu nhất xảyra khi dãy đã cho là dãy đã được sắp xếp và phần tử chốt được chọn là phầntử đầu của dãy => độ phức tạp thuật toán sẽ là O(n^2)
Phân đoạn hoàn hảo: phân đoạn luôn thực hiện dưới dạng phân thì đôi, mỗibài toán con có kích thước là n/2 => độ phức tạp thuật toán là O(nlogn)
Phân đoạn cân bằng: một bài toán con có kích thước n-k và bài toán kia cókích thước là k => độ phức tạp thuật toán là O(n)
6 Đánh giá thuật toán
Trang 96.1 Ưu điểm
Thuật toán có độ phức tạp nhỏ hơn các thuật toán sắp xếp đơn giản, tốc độxử lý tương đối nhanh Trong một số trường hợp, quicksort là thuật toáncó tốc độ tốt nhất
Thông dụng, được áp dụng nhiều trong lập trình, trong thư viện của cácngôn ngữ lập trình như C++, Java, C#
Có thể ứng dụng vào xử lý dữ liệu lớn
6.2 Nhược điểm
Thuật toán không có tính ổn định, không có tính thích ứng, dễ ảnh hưởngbởi dữ liệu đầu vào
Tốn không gian bộ nhớ hơn so với các thuật toán sắp xếp đơn giản
Tư tưởng và giải thuật khá phức tạp
Khó khăn trong việc lựa chọn phần tử làm chốt trong phân hoạch Việclựa chọn có thể ảnh hưởng rất nhiều đến hiệu suất của thuật toán tuy nhiênta không thế đưa ra lựa chọn tối ưu nhất.
7 Bài tập quick-sort
Ví dụ 1:dùng thuật toán Quick Sort sắp xếp day sau :
Chọn 7 làm pivot;Lượt 1 : 7
Trang 10Dãy là : 5246 7910LR
Sau lượt 1 ta được 3 dãy mới là : 5 2 4 6;7;9 10
Ta thấy dãy 7 có 1 phần tử nên không phải sét,dãy 9 10 đã đúng yêu cầu nênkhông phải sét nữa
Chọn 5 làm pivot Lượt 2 : 5
Đổi chỗ: 4 2 5 6 7 9 10LR
Ta lại chia dãy 5 2 4 6 thành 3 dãy mới là : 4 2;5;6
Ta thấy dãy 5;6 có 1 phần tử thôi nên bỏ qua ta lại xét dãy 4 2Chọn 4 làm pivot
Lượt 3: 4
2 5 6 7 9 10L R
Đổi chỗ : 2 4 5 6 7 9 10 LR
Sau tất cả dãy được sắp xếp là : 2 4 5 6 7 9 10
Ví dụ 2 : sắp xếp dãy sau bằng thuật toán Quick Sort
11 33 6 7 22 9 1Chọn 11 làm pivot
Lượt 1 :11
33 6 7 22 9 1
Đổi chỗ :1 33 6 7 22 9
Trang 11L RĐổi chỗ :1 6 7 22 9 33
Đổi chỗ :1 9 6 7 22 33L RĐổi chỗ : 1 9 6 7 11 22 33
LRTa được 3 dãy mới là : 1 9 6 7 ; 11 ; 22 33.
Ta thấy được dãy 11 có 1 phần tử nên không phải sét nữa ,dãy 22 33 đã thỏa mãnyêu cầu nên cũng không phải sét nữa
Ta xét dãy 1 9 6 7Chọn 1 làm pivotLượt 2:1
1 9 6 7 11 22 33LR
Ta được 2 dãy mới là : 1 ; 9 6 7
Dãy 1 có 1 phần tử nên không phải xét ,dãy 9 6 7 ta chọn 9 làm pivotLượt 3:9
Đỏi chỗ :1 7 6 9 11 22 33LR
Ta được 2 dãy mới là : 7 6 ; 9
Dãy 9 có 1 phần tử nên không phái xét ,ta xét dãy 7 6 chọn 7 làm pivotLượt 4:7
1 6 9 11 22 33L R
Trang 12Đổi chỗ : 1 6 7 9 11 22 33LR
Sau tất cả dãy được xắp xếp là : 1 6 7 9 11 22 33