- vừa được xem lúc

Counting Sort

0 0 11

Người đăng: Hạnh

Theo Viblo Asia

Một đôi mắt thật đẹp!

Chào các bạn!

Tiếp theo chuỗi series về các thuật toán sắp xếp và tìm kiếm căn bản, thì ở bài viết này mình sẽ trình bày các bạn phần thuật toán Sắp xếp đếm - Counting Sort.

Đây là một thuật toán sắp xếp có lẽ đặc biệt khác so với các thuật toán trước đó. Nó không phụ thuộc vào số lượng phần tử của dãy số, mà lại phụ thuộc vào giá trị mà dãy số này chứa.

Hãy cùng tìm hiểu nó ngay sau đây nhé!


Đặt vấn đề

Cho dãy số gồm NN phần tử, việc của bạn là sắp xếp chúng theo thứ tự tăng dần. Tất nhiên NN ứng với cả triệu số.

Kèm các điều kiện đặc biệt:

  • Các phần tử đều là số nguyên không âm, có giá trị không quá 1.000.0001.000.000

Ý tưởng thuật toán

Thay vì ta xử lý so sánh và đổi chỗ như những thuật toán trước đây, thì ta dùng một hàm map để đếm số lần giá trị này xuất hiện trong dãy số.

Hàm mapping được định nghĩa như sau:

f(X)=kf(X) = k

Ở đây:

  1. XX là một giá trị bất kì nằm trong dãy số,
  2. kk là số lần xuất hiện của giá trị XX trong dãy số

Để ý ra rằng, hàm f(X)f(X) này chính là count(X)count(X). Và quay lại điều kiện nêu ra ở khúc đặt vấn đề, ta thấy các giá trị của dãy số chỉ nằm trong đoạn [0;1.000.000][0; 1.000.000]. Do đó, ta có thể xây dựng thuật toán này như sau:

  1. Khởi tạo: Khởi tạo một mảng counting1.000.000 + 1 phần tử
  2. Reset: Set tất cả các giá trị từ vị trí 0 đến 1.000.000 bằng 0
  3. Đếm: Lướt qua từng phần tử của dãy số đã cho ban đầu, thực hiện: counting[arr[i]]++
  4. Điền: Chạy qua các giá trị từ vị trí 0 đến 1.000.000 của counting, ta điền đúng số lượng số lượng số đó vào dãy số ban đầu.

Tới đây, bạn đã hiểu vì sao thuật toán này được gọi là thuật toán sắp xếp đếm chưa nào. Đó là vì nó đếm luôn giá trị nằm trong dãy số đã cho luôn, rồi sau đó cứ thế điền lại vào thôi.

Tuy bạn cần chú ý đặc thù của thuật toán này, mà điều kiện giá trị của phần tử trong dãy là yếu tố quyết định.


Và dưới đây là code mà mình đã chuẩn bị:

void countingSort(int *arr, int l, int r) { // Reset for (int value=0; value<=maxNumber; value++) counting[value] = 0; // Đếm for (int i=l; i<=r; i++) counting[arr[i]]++; // Điền vào for (int value=0; value<=maxNumber; value++) { while (counting[value]) { arr[l++] = value; counting[value]--; } }
}

Full code bạn có thể xem ở đây: https://ideone.com/qmLz6H

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

Dễ thấy rằng, độ phức tạp của giải thuật trên là O(N+maxValue)O(N + maxValue) bất kể dãy số ban đầu có thứ tự như thế nào và dù có số lượng bao nhiêu đi nữa.

Và nếu bạn nhấn vào link full code ở phía trên, không bất ngờ bạn cũng có thể tìm thấy dòng Memory + thời gian thực thi:

Success #stdin #stdout 0.02s 7456KB

Với thời gian thực thi nhanh hơn hẳn các thuật toán trước đó mình trình bày với dãy số 1 triệu phần tử.

Kết luận

Trên đây, mình đã trình bày các bạn về thuật toán Counting Sort. Hi vọng bài viết sẽ giúp bạn phần nào hiểu được ý tưởng cũng như cài đặt nó mà không cần học thuộc bất cứ dòng code nào.

Nếu bạn có bất cứ ý kiến nào đóng góp, xin hãy gửi comment, mình sẽ trả lời và khắc phục cho những lần sau.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Học lập trình game cần những gì?

Lập trình game là làm gì. Các ngôn ngữ các bạn có thể sử dụng để lập trình game : C, C++, C#, Java, Python,... Các bước cơ bản để lập trình game. . Hiển thị: Đã là game thì hiển thị không thể thiếu, lúc đầu các bạn chỉ làm cho phần hiển thị thật đơn giản, các bạn đừng quá chú tâm vào việc làm sao ch

0 0 32

- vừa được xem lúc

[MFC] Http request with winsock2.h

Giới thiệu. Xin chào, trong bài này mình sẽ giới thiệu 1 số lưu ý khi sử dụng thư viện winsock2.h (thư viện window socket) sử dụng trong window app. Đầu tiên, bạn sẽ dễ dàng search được 1 ví dụ cụ thể trên document của winsock2.

0 0 22

- vừa được xem lúc

Design parttern

Builder. 1. Ý tưởng. Builder là một mẫu thiết kế sáng tạo cho phép bạn xây dựng các đối tượng phức tạp theo từng bước.

0 0 22

- vừa được xem lúc

Kỹ thuật viết mã nguồn hiệu quả

Kỹ thuật viết mã nguồn hiệu quả? Hôm nay bài viết này mình không đề cập tới thuật toán, hãy coi như rằng chúng ta đã có thuật toán tốt nhất có thể và bây giờ chúng ta phải làm gì để có thể tăng tính hiệu quả của code. Bài viết này mình sẽ lấy ngôn ngữ lập trình C/C++ để minh họa về các hàm, các thao

0 0 23

- vừa được xem lúc

Singleton Design pattern

Singleton Design pattern. 1. Vấn đề. - Ý tưởng:.

0 0 21

- vừa được xem lúc

So sánh Python và C++

Cuộc tranh luận giữa Python và C ++ là một chủ đề hấp dẫn vì cả hai ngôn ngữ lập trình đều rất khác nhau về cú pháp, tính đơn giản, cách sử dụng và cách tiếp cận tổng thể để lập trình. Vì vậy, mọi người cảm thấy khó khăn khi lựa chọn ngôn ngữ lập trình nào để học.

0 0 26