logo

Đang load dữ liệu

logo devmaster

VIỆN CÔNG NGHỆ VÀ ĐÀO TẠO DEVMASTER

Đào tạo - Phần mềm - Cho thuê nhân sự

  • 0969.609.003
  • 0978.611.889
  • Trang chủ
  • Các khoá đào tạo
    • Chuyên đề WEB - PHP

      • Lập trình web với HTML5 - CSS3- JQuery - Bootstrap - Ajax - [36 giờ]
      • Lập trình web frontend - reactjs - [75 giờ]
      • Lập trình web với mã nguồn mở PHP&MYSQL - PHP FRAMEWORK [126 giờ]

      Chuyên đề Mobile

      • Lập trình Games/Apps trên nền tảng Android - [120 giờ]
      • Lập trình Games/Apps trên nền tảng IOS - [120 giờ]

      Chuyên đề JAVA

      • Ngôn ngữ lập trình hướng đối tượng với java - [40 giờ]
      • Lập trình ứng dụng với java - [100 giờ]
      • Lập trình web site với java framework (JPA, HIBERNATE, SPRING MVC, SPRINGBOOT) - [276 giờ]

      Chuyên đề NETWORK/SECURITY

      • Khoá học Quản trị hạ tầng mạng CCNA v6 - [72 giờ]
      • Khoá học quản trị hệ thống với Windows SERVER 2012- [72 giờ]
      • Chuyên gia bảo mật hệ thống CompTIA + - [110 giờ]

      Chuyên đề .NET

      • Nền tảng lập trình hướng đối tượng với C# - [40 giờ]
      • Lập trình ứng dụng WINDOWS FORM - [100 giờ]
      • Lập trình Web với ASP.NET MVC 5, WebAPI - [145 giờ]

      Chuyên đề khác

      • Ngôn ngũ lập trình C/C++ - [80 giờ]
  • Lập trình cho trẻ em
  • Dịch vụ
    • Đào tạo theo như cầu
    • Cung cấp thiết bị - Phần mềm
    • Tư vấn - Thiết kế mạng hạ tầng
    • Tư vấn - Triển khai dịch vụ mạng
    • Tư vấn - Tư vấn, triển khai giám sát hệ thống
    • Thực tập dự án
  • Lịch khai giảng
  • Tin tức
    • Tin tức và sự kiện
    • Tin hoạt động
    • Tin công nghệ
    • Hội thảo, workshop, Codecam
    • Thông tin việc làm
    • Cẩm nang chia sẻ kiến thức
  • Tiện ích
  • Liên hệ

Cẩm nang chia sẻ kiến thức

May - 2019

26

Các thuật toán sắp xếp

Cẩm nang chia sẻ kiến thức

Các thuật toán sắp xếp

Merge sort

Giống như Quick sort, Merge sort là thuật toán chia để trị. Chia mảng thành các mảng nhỏ, sau đó gộp các mảng nhỏ đã sắp xếp lại với nhau.

Ví dụ với mảng 38, 27, 43, 3, 9, 82, 10, trình tự của merge sort sẽ như sau:

Triển khai thuật toán: Vì merge sort là một thuật toán sử dụng rất nhiều bộ nhớ nên sẽ tốt hơn khi sử dụng linked list, với linked list thì việc tách mảng và lưu trữ sẽ đơn giản hơn rất nhiều so với sử dụng mảng thông thường (Bạn cần có kiến thức cơ bản về con trỏ trước khi xem đoạn code dưới).

// C++ code for linked list merged sort
#include
using namespace std;
 
/* Link list node */
class Node {
public:
int data;
Node* next;
};
 
/* function prototypes */
Node* SortedMerge(Node* a, Node* b);
void FrontBackSplit(Node* source, Node** frontRef, Node** backRef);
 
void MergeSort(Node** headRef)
{
Node* head = *headRef;
Node* a;
Node* b;
 
/* Điều kiện dừng, khi linked list có 0 hoặc 1 node */
if ((head == NULL) || (head->next == NULL)) {
return;
}
 
/* Chia thành 2 linked list nhỏ a, b*/
FrontBackSplit(head, &a, &b);
 
/* Đệ quy để chia thành các linked list nhỏ nhất */
MergeSort(&a);
MergeSort(&b);
 
/* answer = merge the two sorted lists together */
*headRef = SortedMerge(a, b);
}
 
/* Trộn 2 mảng đã được sắp xếp */
Node* SortedMerge(Node* a, Node* b)
{
Node* result = NULL;
 
if (a == NULL)
return (b);
else if (b == NULL)
return (a);
 
if (a->data <= b->data) {
result = a;
result->next = SortedMerge(a->next, b);
}
else {
result = b;
result->next = SortedMerge(a, b->next);
}
return (result);
}
 
/* Chia đôi linked list source thành frontRef và backRef */
void FrontBackSplit(Node* source,
Node** frontRef, Node** backRef)
{
Node* fast;
Node* slow;
slow = source;
fast = source->next;
 
/* Node fast di chuyển 2 bước thì Node slow di chuyể n được 1 bước */
while (fast != NULL) {
fast = fast->next;
if (fast != NULL) {
slow = slow->next;
fast = fast->next;
}
}
 
/* Cuối cùng Note slow sẽ là Node ở giữa */
*frontRef = source;
*backRef = slow->next;
slow->next = NULL;
}
 
void printList(Node* node)
{
while (node != NULL) {
cout << node->data << " ";
node = node->next;
}
}
 
/* Hàm thêm 1 node vào đầu mỗi linked list */
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node();
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
 
int main()
{  
Node* a = NULL;
 
/* Tạo linked list: 2->3->20->5->10->15 */
push(&a, 15);
push(&a, 10);
push(&a, 5);
push(&a, 20);
push(&a, 3);
push(&a, 2);
 
/* Sử dụng merge sort */
MergeSort(&a);
 
cout << "Sorted Linked List is: \n";
printList(a);
 
return 0;
}
 
// This is code is contributed by rathbhupendra

 

Counting sort

Counting sort là một kỹ thuật sắp xếp các đối tượng trong một phạm vị cụ thể. Nó hoạt động bằng cách đếm số lượng các đôi tượng có giá trị giống nhau. Sau đó sử dụng một chút toán học để tính toán vị trí cuối cùng của đối tượng đó.

Độ phức tạp của thuật toán này là O(n+k) với n là số lượng đối lượng, k là phạm vị giá trị của n đối tượng.

Hãy tìm hiểu thông qua 1 ví dụ:

Phạm vị giá trị k 10, giá trị của n nằm trong đoạn từ [0, 9].
Input: 1, 4, 1, 2, 7, 5, 2
  1) Đếm số lượng các đối tượng có giá trị giống nhau.
  Index:     0  1  2  3  4  5  6  7  8  9
  Count:     0  2  2  0  1  1  0  1  0  0
 
  2) Sửa lại giá trị của mảng Count sao cho giá trị tại mỗi vị trí i sẽ bằng tổng giá trị tại vị trí i + giá trị tại vị trí i - 1.
  Index:     0  1  2  3  4  5  6  7  8  9
  Count:     0  2  4  4  5  6  6  7  7  7
 
Giá trị của mảng Count sẽ chỉ ra vị trí cuối cùng của các đối tượng.
 
  3) Sắp xếp lại các phần tử vào mảng Output.
  Với Input là: 1, 4, 1, 2, 7, 5, 2. Vị trí của 1 là 2 trong mảng Output.
Giảm giá trị tại vị trí 1 của mảng Count xuống 1 đơn vị
Giá tiếp theo là 4, vị trí trong mảng Output là 5. Giảm giá trị tại vị trí 4 của mảng Count xuống 1 đơn vị
Cứ như vậy và ta sẽ thu được kết quả của mảng Output là : 1, 1, 2, 2, 4, 5, 7
Triển khai thuật toán:
 
// C++ Program for counting sort  
#include  
#include
using namespace std;  
k = 256
#define RANGE 255  
  
void countSort(char arr[])  
{  
    // Mảng Output
    char output[strlen(arr)];  
  
    // Mảng count với 256 phần tử từ 0-255 với giá trị là 0 tại mỗi vị trí    
    int count[RANGE + 1], i;  
    memset(count, 0, sizeof(count));  
  
    // Đếm số lượng đối tượng có cùng giá trị và lưu kết quả vào mảng count  
    for(i = 0; arr[i]; ++i)  
        ++count[arr[i]];  
  
    // Thay đổi giá trị của mảng count    
    for (i = 1; i <= RANGE; ++i)  
        count[i] += count[i-1];  
  
    // Xây dựng mảng Output
    for (i = 0; arr[i]; ++i)  
    {  
        output[count[arr[i]]-1] = arr[i];  
        --count[arr[i]];  
    }  
  
    for (i = 0; arr[i]; ++i)  
        arr[i] = output[i];  
}  
  
// Driver  code
int main()  
{  
    char arr[] = "geeksforgeeks";
  
    countSort(arr);  
  
    cout<< "Sorted character array is " << arr;  
    return 0;  
}  

Đây là một đoạn code sắp xếp mảng các ký tự, thuật toán cũng có thể được sử dụng để sắp xếp mảng các số nguyên. Với mảng các số nguyên bao gồm cả số âm và dương thì cần phải thay đổi thuật toán 1 chút. Lí do là vì trong c++ bạn không thể truy cập giá trị tại ví trí âm trong mảng. Để giải quyết vấn đề này bạn cần tính lại khoảng k và xây dựng lại mảng count sao cho phần tử nhỏ nhất ở trị trí 0.

Radix sort

Các thuật toán quen thuộc như quick sort, merge sort, heap sort,… là các thuật toán sắp xếp dựa vào giá trị của các phép so sánh, độ phức tạo của các thuật toán này không thể tốt hơn O(nLogn). Còn với thuật toán counting sort ở trên, là một thuật toán tuyến tính với độ phức tạp là O(n+k). Trong trường hợp k bằng n*n thì counting sort là một lựa chọn tồi. Radix sort là một lựa chọn tốt trong TH này.

Tư tưởng của thuật toán này là sắp xếp các số theo giá trị của hàng chục, hàng trăm, hàng nghìn, …

Ví dụ:

với một mảng các số 170, 45, 75, 90, 802, 24, 2, 66
 
Đầu tiên sắp xếp theo hàng đơn vị
170, 90, 802, 2, 24, 45, 75, 66
  0   0    2  2   4   5   5   6
Tiếp theo đến hàng chục
802, 2, 24, 45, 66, 170, 75, 90
0   0  2   4   6    7   7   9
  
Cứ như vậy sẽ thu được kết quả cuối cùng
2, 24, 45, 66, 75, 90, 170, 802

Triển khai thuật toán:

// C++ implementation of Radix Sort
#include
using namespace std;
  
// Tìm giá trị lớn nhất trong mảng
int getMax(int arr[], int n)
{
    int mx = arr[0];
    for (int i = 1; i < n; i++)
        if (arr[i] > mx)
            mx = arr[i];
    return mx;
}
  
// Sử dụng thuật toán counting sort để sắp xếp lại vị trí của các đôi tượng theo giá trị hàng đơn vị, hàng chục,...
void countSort(int arr[], int n, int exp)
{
    int output[n];
    int i, count[10] = {0};
 
    for (i = 0; i < n; i++)
        count[ (arr[i]/exp)%10 ]++;
  
    for (i = 1; i < 10; i++)
        count[i] += count[i - 1];
  
    for (i = n - 1; i >= 0; i--)
    {
        output[count[ (arr[i]/exp)%10 ] - 1] = arr[i];
        count[ (arr[i]/exp)%10 ]--;
    }
  
    for (i = 0; i < n; i++)
        arr[i] = output[i];
}
  
// Radix Sort
void radixsort(int arr[], int n)
{  
    int m = getMax(arr, n);  
    // Sử dụng couting sort để sắp xếp lại vị trí các đôi tượng
    for (int exp = 1; m/exp > 0; exp *= 10)
        countSort(arr, n, exp);
}
  
void print(int arr[], int n)
{
    for (int i = 0; i < n; i++)
        cout << arr[i] << " ";
}
  
int main()
{
    int arr[] = {170, 45, 75, 90, 802, 24, 2, 66};
    int n = sizeof(arr)/sizeof(arr[0]);
    radixsort(arr, n);
    print(arr, n);
    return 0;
}

 

Nguồn: Sưu tầm từ internet via Devmaster Academy

Các bài viết cùng chủ đề

BÍ QUYẾT HỌC LẬP TRÌNH CHO CÁC BẠN ĐẦU NĂM HỌC MỚI ❤
BÍ QUYẾT HỌC LẬP TRÌNH CHO CÁC BẠN ĐẦU NĂM HỌC MỚI...
5 Phương pháp hay để mở rộng các dự án React của bạn một cách dễ dàng
5 Phương pháp hay để mở rộng các dự án React của b...
Lab06.1 - Data Access In ASPNET MVC 5
Lab06.1 - Data Access In ASPNET MVC 5
Lab05 - Data Validation and Annotation In ASPNET MVC 5
Lab05 - Data Validation and Annotation In ASPNET M...
Lab 04 - Model in ASP.NET MVC 5 - Phần tự thực hành
Lab 04 - Model in ASP.NET MVC 5 - Phần tự thực hàn...
Lab 04 - Model in ASP.NET MVC 5 - Bài 4.2
Lab 04 - Model in ASP.NET MVC 5 - Bài 4.2

Các khóa đào tạo chuyên đề

Thiết kế và lập trình Website PHP, Laravel chuyên nghiệp - FullStack
Thiết kế và lập trình Website PHP, Laravel chuyên nghiệp - FullStack
Lập trình ứng dụng trên nền tảng android Lập trình ứng dụng trên nền tảng android
Lập trình Ứng dụng với Công nghệ ASP.NET Core MVC, WebAPI, ReactJS - FullStack

Lập trình Ứng dụng với Công nghệ ASP.NET Core MVC, WebAPI, ReactJS - FullStack
Lập trình ứng dụng với WINDOWS FORM Lập trình ứng dụng với WINDOWS FORM
Lập trình ứng dụng với JAVA (FORM) Lập trình ứng dụng với JAVA (FORM)
Thiết kế và lập trình Ứng dụng với công nghệ Java (Java Framework springBoot, hibernate,...) - FullStack
Thiết kế và lập trình Ứng dụng với công nghệ Java (Java Framework springBoot, hibernate,...) - FullStack
Thiết kế và lập trình website với công nghệ HTML5, CSS3, Javascript, Bootstrapt 4, Jquery Thiết kế và lập trình website với công nghệ HTML5, CSS3, Javascript, Bootstrapt 4, Jquery
Lập trình frontend với reacjs (Full) Lập trình frontend với reacjs (Full)
Viện Công Nghệ Và Đào Tạo Devmaster

DEVMASTER ACADEMY

Địa chỉ: Tầng 6 - Tòa nhà VIỆN CÔNG NGHỆ
Số 25, Vũ Ngọc Phan - Láng Hạ - Đống Đa - Hà Nội

Hotline: 0969 609 003 | 0978 611 889

devmaster.contact@gmail.com

hna.tvchung@gmail.com

CÁC KHÓA HỌC CHUYÊN ĐỀ

  • Thiết kế và lập trình Website PHP, Laravel chuyên nghiệp - FullStack
  • Lập trình ứng dụng trên nền tảng android
  • Lập trình Ứng dụng với Công nghệ ASP.NET Core MVC, WebAPI, ReactJS - FullStack
  • Lập trình ứng dụng với WINDOWS FORM
  • Lập trình ứng dụng với JAVA (FORM)
  • Thiết kế và lập trình Ứng dụng với công nghệ Java (Java Framework springBoot, hibernate,...) - FullStack
  • Thiết kế và lập trình website với công nghệ HTML5, CSS3, Javascript, Bootstrapt 4, Jquery
  • Lập trình frontend với reacjs (Full)
Viện Công Nghệ Và Đào Tạo Devmaster

VIỆN CÔNG NGHỆ VÀ ĐÀO TẠO DEVMASTER - Học thực tế * Làm thực tế * Cam kết việc làm
Copyright by Ⓒ DEVMASTER 2015