HEAP SORT: Thuật toán sắp xếp vun đống

Ngày đăng: 11/09/2020   -    Cập nhật: 23/10/2020


Trong bài viết này, bạn sẽ được tìm hiểu về thuật toán Heap sort. Đây là thuật toán được sử dụng rất rộng rãi để cài đặt hàng đợi ưu tiên hoặc giải quyết bài toán tìm đường đi ngắn nhất.

1. Thuật toán Heap sort là gì?


Thuật toán Heap sort (Sắp xếp vun đống)

Thuật toán Heap sort (sắp xếp vun đống)
 

Thuật toán Heap sort là một kỹ thuật sắp xếp dựa trên so sánh dựa trên cấu trúc dữ liệu Binary Heap.

Nó tương tự như sắp xếp lựa chọn, nơi đầu tiên chúng ta tìm phần tử lớn nhất và đặt phần tử lớn nhất ở cuối.

Chúng ta lặp lại quá trình tương tự cho các phần tử còn lại.

Một Binary Heap là một cây nhị phân hoàn chỉnh trong đó các mục được lưu trữ theo một thứ tự đặc biệt sao cho giá trị trong nút cha lớn hơn (hoặc nhỏ hơn) so với giá trị trong hai nút con của nó.

Loại trước được gọi là max heap và loại sau được gọi là min heap.

Heap có thể được biểu diễn bằng một cây hoặc mảng nhị phân.


Tại sao biểu diễn dựa trên mảng cho Binary Heap?


Vì một Binary Heap là một cây nhị phân hoàn chỉnh, nó có thể dễ dàng được biểu diễn dưới dạng một mảng.

Nếu nút cha được lưu trữ ở chỉ mục i, nút con bên trái có thể được tính bằng 2 * i và nút con bên phải bằng 2 * i + 1 (giả sử việc lập chỉ mục bắt đầu từ 0).

Thuật toán Heap Sort được dùng để sắp xếp theo thứ tự tăng dần:


  • Xây dựng một heap tối đa từ dữ liệu đầu vào.
  • Tại thời điểm này, mục lớn nhất được lưu trữ ở gốc của heap. Thay thế nó bằng mục cuối cùng của heap, sau đó giảm kích thước của heap đi 1. Cuối cùng, heap được “vun đống”.
  • Lặp lại bước 2 trong khi kích thước của đống lớn hơn 1

Biểu diễn Heap dưới dạng mảng, ta có:

  • Gốc của cây là A[i]
  • Con trái của A[i]A[2*i]
  • Con phải của A[i]A[2*i + 1]
  • Số lượng phần tử của heap là Heapsize[A] ≤ length[A]

Phân loại: Có 2 loại

  • Max-heaps (Phần tử lớn nhất ở gốc): Với mọi nút i, ngoại trừ gốc: A[parent(i)] ≥ A[i]
  • Min-heaps (Phần tử nhỏ nhất ở gốc): Với mọi nút i, ngoại trừ gốc: A[parent(i)] ≤ A[i]

2. Làm thế nào để xây dựng Heap?


Thủ tục Heapify chỉ có thể được áp dụng cho một nút nếu các nút con của nó được “vun đống”. Vì vậy việc vun đống phải được thực hiện theo thứ tự từ dưới lên.

Hãy hiểu rõ hơn thông qua ví dụ sau:



// Dữ liệu đầu vào: 4, 10, 3, 5, 1
//          4(0)
//         /   \
//      10(1)   3(2)
//     /   \
//  5(3)    1(4)

// Các số trong ngoặc biểu thị các chỉ số trong mảng biểu diễn dữ liệu.
// Áp dụng quy trình heapify cho chỉ mục 1:
//          4(0)
//         /   \
//     10(1)    3(2)
//     /   \
//  5(3)    1(4)

// Áp dụng quy trình heapify cho chỉ mục 0:
//        10(0)
//        /  \
//     5(1)  3(2)
//    /   \
//  4(3)    1(4)
// Thủ tục heapify tự gọi đệ quy để xây dựng heap theo cách từ trên xuống.
 

3. Triển khai thuật toán Heap sort trong Java


Từ ví dụ ở mục 2, chúng ta dễ dàng chuyển chúng thành code – có nội dung như bên dưới:


package heap.sort.algo;

public class HeapSort {
    public void sort(int arr[]) {
        int n = arr.length;

        // Xây dựng Heap (sắp xếp lại mảng)
        for (int i = n / 2 - 1i >= 0i--)
            heapify(arrni);

        // Trích xuất từng phần tử từ Heap
        for (int i = n - 1i > 0i--) {
            // Di chuyển root hiện tại đến end
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;

            // gọi max - heapify trên Heap đã sắp xếp
            heapify(arri0);
        }
    }

    // Để vun đống một cây con bắt nguồn từ nút i là
    // một chỉ mục trong arr[]. n là kích thước của Heap
    void heapify(int arr[], int nint i) {
        int largest = i// Khởi tạo largest như root
        int l = 2 * i// left = 2*i
        int r = 2 * i + 1// right = 2*i + 1

        // Nếu nút con bên trái lớn hơn nút con của gốc
        if (l < n && arr[l] > arr[largest])
            largest = l;

        // Nếu nút con bên phải lớn hơn largest
        if (r < n && arr[r] > arr[largest])
            largest = r;

        // Nếu largest không phải là root
        if (largest != i) {
            int swap = arr[i];
            arr[i] = arr[largest];
            arr[largest] = swap;

            // Vun đống lại các cây con bị ảnh hưởng
            heapify(arrnlargest);
        }
    }

    // In mảng kích thước n
    static void printArray(int arr[]) {
        int n = arr.length;
        for (int i = 0i < n; ++i)
            System.out.print(arr[i] + " ");
        System.out.println();
    }

    public static void main(String args[]) {
        int arr[] = { 410351 };
        int n = arr.length;

        System.out.println("Mảng ban đầu:");
        printArray(arr);

        HeapSort ob = new HeapSort();
        ob.sort(arr);

        System.out.println("Mảng sau khi sắp xếp:");
        printArray(arr);
    }
}
 

Chạy chương trình trên ta được:


Mảng ban đầu:
4 10 30 5 1
Mảng sau khi sắp xếp:
1 3 4 5 10
 

Ghi chú:

  • Heap sort là một thuật toán in-place - Việc triển khai điển hình của nó không ổn định.
  • Độ phức tạp về thời gian của heapify là O(Logn). Độ phức tạp thời gian của createAndBuildHeap()O(n) và độ phức tạp thời gian tổng thể của Heap Sort là O(nLogn).
 
Heap sort có hạn chế sử dụng vì Quick sortMerge sort tốt hơn trong thực tế. Tuy nhiên, bản thân cấu trúc dữ liệu Heap được sử dụng rất nhiều, do đó việc tìm hiểu và ứng dụng tốt HeapSort không phải là chuyện dư thừa.

Bổ sung hoặc cập nhật sớm về thuật toán Heap sort sẽ giúp bạn có thêm nhiều lựa chọn giải quyết các vấn đề trong các bài toán thực tế, đặc biệt là các bài toán liên quan đến cấu trúc dữ liệu Heap.


---
HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI
Học Lập trình chất lượng cao (Since 2002). Học làm Lập trình viên. Hành động ngay!
Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội
SĐT: 02435574074 - 0914939543
Email: hello@niithanoi.edu.vn
Fanpage: https://facebook.com/NIIT.ICT/
 
#niit #niithanoi #niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp #java #php #python
Bình luận Facebook
Đăng ký tư vấn
Nhân viên gọi điện tư vấn miễn phí sau khi đăng ký
Được cập nhật các ưu đãi sớm nhất
Hotline: 0383180086
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Hãy đăng ký để nhận những thông tin mới nhất về học bổng mới nhất tại NIIT - ICT Hà Nội
top
Đóng lại Đăng ký học tại NIIT - ICT Hà Nội
6260+ học viên đã theo học tại NIIT - ICT Hà Nội và có việc làm tốt trong ngành lập trình. Nắm lấy cơ hội ngay hôm nay!
Chọn khóa học
  • KHÓA HỌC LẬP TRÌNH FRONT END VỚI REACT.JS
  • KHÓA HỌC LẬP TRÌNH PHP WEB
  • Khóa học PHP Full stack [2023] cho người mới bắt đầu
  • Khóa học BIG DATA với Hadoop và Spark
  • Khóa học Lập trình Android tại Hà Nội
  • [Tuyển sinh 2023] Lập trình viên Quốc tế DigiNxt
  • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại Hà Nội
  • LẬP TRÌNH GAME
    • Khóa học Lập trình Game Unity
  • LẬP TRÌNH WEB FRONT END
    • KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG
    • KHÓA HỌC ANGULAR & TYPESCRIPT (FRONT END)
  • LẬP TRÌNH WEB BACK END
    • LẬP TRÌNH JAVA WEB VỚI FRAME WORK
    • Lập trình Web với Django
    • Lập trình PHP với Laravel Framework
  • CHƯƠNG TRÌNH ĐÀO TẠO ỨNG DỤNG CÔNG NGHỆ
    • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại TP HCM
  • LẬP TRÌNH WEB FULL STACK
    • Khóa học Java Full stack (IJFD)
  • LẬP TRÌNH MOBILE
    • FRONT-END VỚI REACTJS VÀ REACT NATIVE
    • Lập trình Android Nâng cao
  • ĐÀO TẠO CHO DOANH NGHIỆP
    • KHÓA HỌC BUSINESS ANALYSIC TỪ CƠ BẢN ĐẾN NÂNG CAO 2023
    • Khóa học Magento: Làm chủ CMS TMĐT lớn nhất
    • Khóa học IOT: Xây dựng Sản phẩm IOT với Raspberry Pi
    • Khóa học Automation Testing Chuyên nghiệp
  • KHÓA HỌC DỰ ÁN
    • Học sử dụng bộ Office: Word, Excel, Power Point, Mail chuyên nghiệp
  • KHÓA HỌC KHÁC
    • VBA Excel Toàn Tập (Cơ Bản - Nâng Cao)
    • VBA Excel Nâng cao
    • Khóa học JMeter: Performance Testing
    • Khóa học Tester đạt chuẩn Quốc tế ISTQB Foundation Level
    • Khoá Học Tester đạt chuẩn quốc tế ISTQB Advanced Level
Bạn chưa chọn khóa học cần đăng ký
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Đăng ký học thành công!
Cảm ơn bạn đã đăng ký học tại NIIT - ICT HÀ NỘI!