Bối cảnh và vấn đề nghiên cứu

Đồ án môn học "Cấu trúc dữ liệu và giải thuật" do sinh viên Đỗ Tường Vy (mã số sinh viên: 2021010354, lớp 20DHT05) thực hiện dưới sự hướng dẫn của giảng viên Nguyễn Quốc Thanh tại Trường Đại học Tài chính – Marketing (Khoa Công nghệ thông tin), hoàn thành vào tháng 12 năm 2020 tại Thành phố Hồ Chí Minh.

Trong công tác quản lý danh mục hàng hóa tại các đơn vị bán lẻ, việc lưu trữ, tra cứu và phân loại sản phẩm đòi hỏi các cấu trúc dữ liệu phù hợp nhằm đảm bảo hiệu năng xử lý. Văn bản đồ án đặt ra yêu cầu xây dựng các chức năng tìm kiếm và sắp xếp dữ liệu quản lý danh mục sản phẩm đồng hồ đeo tay trên hai cấu trúc nền tảng của khoa học máy tính: mảng cấu trúc (array of structures) và danh sách liên kết đơn (singly linked list).

Mục tiêu và nhiệm vụ nghiên cứu được văn bản xác định cụ thể như sau:

  1. Thiết kế và khai báo cấu trúc dữ liệu dongho để mô hình hóa đầy đủ các thuộc tính của đối tượng sản phẩm đồng hồ theo yêu cầu nghiệp vụ.
  2. Xây dựng tập dữ liệu mẫu gồm 10 phần tử đại diện cho các mặt hàng đồng hồ thực tế để phục vụ quá trình thực nghiệm và kiểm thử.
  3. Hiện thực hóa các thao tác cơ bản (nhập, xuất) và các thuật toán tìm kiếm (tìm kiếm tuyến tính - Linear Search, tìm kiếm nhị phân - Binary Search) cùng các giải thuật sắp xếp nội (Shaker Sort, Selection Sort, Interchange Sort, Bubble Sort, Insertion Sort, Quick Sort) trên mảng cấu trúc tĩnh.
  4. Chuyển đổi và cài đặt cấu trúc danh sách liên kết đơn tương ứng; phân tích khả năng thích ứng, hiện thực hóa các thao tác quản lý nút (node), danh sách (list), cùng các giải thuật tìm kiếm và sắp xếp trên cấu trúc động này.

Đối tượng nghiên cứu của đồ án là cấu trúc bản ghi thông tin sản phẩm đồng hồ và các giải thuật xử lý dữ liệu nội tại trên bộ nhớ. Phạm vi nghiên cứu về mặt không gian và học thuật được thực hiện trong khuôn khổ học phần Cấu trúc dữ liệu và giải thuật tại Trường Đại học Tài chính – Marketing; phạm vi dữ liệu giới hạn trên tập dữ liệu mẫu gồm 10 sản phẩm cụ thể; phạm vi kỹ thuật tập trung vào việc hiện thực hóa thuật toán bằng ngôn ngữ lập trình C++ trên nền tảng console.

Cơ sở lý thuyết và phương pháp

Văn bản đồ án xây dựng cơ sở lý thuyết dựa trên các khái niệm trừu tượng hóa dữ liệu và các thuật toán xử lý danh sách trong bộ nhớ chính:

  • Cấu trúc bản ghi struct dongho: Bao gồm các trường thông tin quy định:
    • MaSP: Chuỗi ký tự số có độ dài 11 ký tự (char MaSP[11]).
    • HangSX: Chuỗi tối đa 10 ký tự lưu tên hãng sản xuất (char HangSX[10]).
    • GioiTinh: Chuỗi tối đa 10 ký tự biểu diễn phân loại giới tính (char GioiTinh[10]).
    • TrongLuong: Kiểu số nguyên không âm (int TrongLuong >= 0), đơn vị tính theo gram (g).
    • BaoHanh: Kiểu số nguyên không âm (int BaoHanh >= 0), đơn vị tính theo tháng.
    • Gia: Kiểu số thực dương (float Gia >= 0), đơn vị tính bằng triệu đồng (VND).
  • Cấu trúc danh sách liên kết đơn: Được tạo thành từ hai thành phần chính:
    • Cấu trúc nút (struct node / NODE): Chứa trường dữ liệu DONGHO data và con trỏ tự trỏ struct node *pNext trỏ đến phần tử kế tiếp.
    • Cấu trúc quản lý danh sách (struct list / LIST): Quản lý tập hợp các nút thông qua hai con trỏ NODE *pHead (trỏ vào nút đầu) và NODE *pTail (trỏ vào nút cuối).
  • Hệ thống thuật toán tìm kiếm và sắp xếp:
    • Thuật toán tìm kiếm: Linear Search (duyệt tuần tự từng phần tử từ đầu đến cuối), Binary Search (tìm kiếm nhị phân bằng cách chia đôi không gian tìm kiếm trên tập dữ liệu đã sắp xếp).
    • Thuật toán sắp xếp: Shaker Sort (sắp xếp rung lắc hai chiều), Selection Sort (chọn trực tiếp), Interchange Sort (đổi chỗ trực tiếp), Bubble Sort (nổi bọt), Insertion Sort (chèn trực tiếp), Quick Sort (sắp xếp nhanh theo phân hoạch chốt).

Phương pháp nghiên cứu thực tế được tác giả áp dụng là phương pháp thực nghiệm lập trình và kiểm thử chức năng (functional testing). Tác giả viết mã nguồn trực tiếp bằng C++, phân tách chương trình thành các hàm chức năng độc lập (chương trình con) và xây dựng các hàm kiểm thử main() chứa dữ liệu khởi tạo sẵn để quan sát, ghi nhận kết quả thực thi trên giao diện dòng lệnh.

Nguồn dữ liệu thực nghiệm được tác giả lập bảng cố định gồm 10 sản phẩm đồng hồ với các thông số như sau:

STT Mã SP Hãng sản xuất Giới tính Trọng lượng (g) Thời gian bảo hành (tháng) Giá bán (triệu VND)
1 1910 Casio Nam 70 60 5,0
2 1901 Tag Heuer Nam 160 23 34,0
3 1903 Rolex Nam 156 24 100,0
4 1904 Omega Trung tính 55 12 23,0
5 1907 Longines Nữ 140 12 23,0
6 1906 Tissot Trung tính 180 12 5,4
7 1905 Timex Trung tính 100 12 2,0
8 1908 Calvin Klein Nữ 90 24 5,0
9 1902 Movado Nam 100 16 12,0
10 1909 Citizen Nam 150 24 2,5

Nội dung chính theo từng chương

Chương 1: Giới thiệu

Chương 1 thiết lập các yêu cầu nền tảng của bài toán quản lý danh mục đồng hồ. Tác giả định nghĩa chi tiết cấu trúc dữ liệu struct dongho, xác định rõ các ràng buộc về kiểu dữ liệu và miền giá trị hợp lệ cho từng thuộc tính. Bên cạnh bảng dữ liệu mẫu gồm 10 bản ghi, chương này phác thảo toàn bộ danh mục các chức năng dự kiến xây dựng trên hai cấu trúc dữ liệu:

  • Danh mục trên mảng cấu trúc: Nhập mảng, xuất mảng, tìm kiếm theo MaSP (Linear Search, Binary Search), tìm kiếm theo HangSX (Linear Search, Binary Search), và 7 giải thuật sắp xếp (Shaker Sort, Selection Sort, Interchange Sort, Bubble Sort, Insertion Sort, Quick Sort, Merge Sort).
  • Danh mục trên danh sách liên kết: Nhập, xuất, tìm kiếm theo MaSP, tìm kiếm theo tên hãng, và các giải thuật sắp xếp tương ứng.

Chương 2: Tìm kiếm và sắp xếp trên mảng cấu trúc

Chương 2 trình bày chi tiết mã nguồn cài đặt và kết quả kiểm thử trên mảng cấu trúc tĩnh (dongho arr[100]):

  • Thao tác cơ sở: Xây dựng các hàm nhap_o và nhap_mang để tiếp nhận dữ liệu từ bàn phím; hàm xuat_o và xuat_mang để định dạng hiển thị danh sách ra màn hình.
  • Chức năng tìm kiếm:
    • Cài đặt LinearSearch và BinarySearch để tra cứu theo khóa chính MaSP. Kết quả kiểm thử cho thấy giải thuật tìm chính xác mã 1903 (Rolex) và trả về thông báo "Khong tim thay" khi tra cứu mã 1902 trên mảng con kiểm thử.
    • Cài đặt LinearSearch_h và BinarySearch_h để tra cứu theo khóa HangSX. Kiểm thử cho kết quả tìm thấy đồng hồ hãng Omega và báo không tìm thấy với hãng Casio khi phần tử không tồn tại trong tập dữ liệu kiểm thử.
  • Chức năng sắp xếp:
    • Cài đặt ShakerSort theo MaSP: Duyệt hai chiều luân phiên (lượt đi đẩy phần tử nhỏ nhất về đầu mảng, lượt về đẩy phần tử lớn nhất về cuối mảng) kết hợp hàm hoán vị swap.
    • Cài đặt SelectionSort theo MaSP: Tìm vị trí phần tử có khóa MaSP nhỏ nhất trong đoạn chưa sắp xếp bằng hàm strcmp và hoán vị về đầu đoạn.
    • Cài đặt InterchangeSort theo HangSX: So sánh trực tiếp từng cặp phần tử nghịch thế để hoán vị chuỗi tên hãng theo thứ tự bảng chữ cái.
    • Cài đặt BubbleSort theo TrongLuong: So sánh các cặp phần tử kề nhau từ cuối mảng để đưa các sản phẩm có trọng lượng nhẹ lên phía trước.
    • Cài đặt InsertionSort theo Gia: Chia mảng thành dãy đã sắp xếp và chưa sắp xếp, chèn giá trị Gia của phần tử hiện hành vào đúng vị trí thích hợp. Kết quả hiển thị danh sách giá tăng dần từ 2 triệu (Timex) đến 100 triệu (Rolex).
    • Cài đặt QuickSort theo thời gian BaoHanh: Phân hoạch mảng dựa trên phần tử chốt x = arr[(left + right) / 2].BaoHanh, thực hiện phân chia và gọi đệ quy trên hai dãy con.

Chương 3: Tìm kiếm và sắp xếp trên danh sách liên kết

Chương 3 chuyển đổi bài toán sang cấu trúc dữ liệu động là danh sách liên kết đơn:

  • Xây dựng cấu trúc dữ liệu: Định nghĩa kiểu dữ liệu DONGHO, cấu trúc nút NODE và cấu trúc danh sách LIST. Hiện thực hóa các hàm cơ sở: KhoiTao (thiết lập pHead và pTail trỏ về NULL), KhoiTaoNODE (cấp phát bộ nhớ động bằng toán tử new), ThemVaoDau (chèn nút vào đầu danh sách) và duyệt in danh sách inDSLK.
  • Chức năng tìm kiếm: Cài đặt hàm timkiem (theo MaSP) và timkiemten (theo HangSX) bằng giải thuật tìm kiếm tuyến tính Linear Search. Tác giả nêu rõ nguyên lý: do danh sách liên kết đơn chỉ cho phép duyệt tuần tự từ đầu danh sách thông qua con trỏ pNext, không thể truy xuất ngẫu nhiên đến phần tử chính giữa trong thời gian $O(1)$, vì vậy không thể áp dụng thuật toán tìm kiếm nhị phân Binary Search trên cấu trúc này.
  • Chức năng sắp xếp:
    • Shaker Sort: Tác giả phân tích và kết luận Shaker Sort không thể thực hiện trên danh sách liên kết đơn vì giải thuật đòi hỏi duyệt ngược từ phần tử cuối cùng về đầu danh sách, điều mà liên kết đơn một chiều không hỗ trợ.
    • Selection Sort: Duyệt danh sách qua con trỏ p, tìm nút min có MaSP nhỏ nhất trong phần còn lại của danh sách và hoán đổi dữ liệu swap(min->data, p->data).
    • Interchange Sort: Dùng hai vòng lặp lồng nhau qua con trỏ p và q để so sánh và hoán đổi dữ liệu khi phát hiện nghịch thế MaSP.
    • Bubble Sort: Sử dụng các cặp con trỏ duyệt danh sách (p1, p2, q1, q2) để so sánh và hoán đổi các nút kề cận theo trường TrongLuong.
    • Insertion Sort: Xây dựng hàm phụ trợ Insert_Sorted để chèn một nút vào đúng vị trí trên danh sách mới theo thứ tự khóa tăng dần, sau đó duyệt từng nút từ danh sách ban đầu để tái cấu trúc danh sách.
    • Quick Sort: Tách danh sách liên kết thành hai danh sách con l1 (chứa các nút có dữ liệu nhỏ hơn hoặc bằng nút chốt x) và l2 (chứa các nút có dữ liệu lớn hơn hoặc bằng nút chốt x), sau đó tiến hành sắp xếp từng danh sách con và nối lại thành danh sách hoàn chỉnh.

Thiết kế và triển khai thuật toán

Các giải thuật được hiện thực hóa qua hệ thống chương trình con C++ có sự phân hóa rõ nét giữa hai cấu trúc lưu trữ:

Thuật toán Tiêu chí xử lý / Khóa Cài đặt trên Mảng cấu trúc Cài đặt trên Danh sách liên kết đơn
Linear Search MaSP / HangSX Duyệt chỉ số mảng từ 0 đến n - 1 Duyệt con trỏ t = t->pNext từ pHead đến NULL
Binary Search MaSP / HangSX Tính chỉ số giữa mid = (left + right) / 2 Không áp dụng được (không hỗ trợ truy xuất ngẫu nhiên)
Shaker Sort MaSP Duyệt luân phiên 2 chiều với biến chặn left, right Không áp dụng được (không hỗ trợ duyệt ngược)
Selection Sort MaSP Tìm chỉ số min trong đoạn [i+1, n-1], gọi swap Tìm con trỏ min trỏ tới nút nhỏ nhất, gọi swap(min->data, p->data)
Interchange Sort HangSX / MaSP So sánh a[i] với a[j], hoán vị trực tiếp So sánh nút p với nút q, hoán vị vùng dữ liệu data
Bubble Sort TrongLuong Vòng lặp duyệt ngược từ cuối mảng n-1 về i Duyệt danh sách qua các con trỏ tạm để hoán vị các phần tử kề nhau
Insertion Sort Gia Dịch chuyển các phần tử mảng sang phải để tạo vị trí chèn Sử dụng hàm Insert_Sorted để chèn nút vào danh sách mới
Quick Sort BaoHanh Phân hoạch mảng thành các dãy con dựa trên giá trị chốt Tách danh sách thành hai danh sách l1, l2 rồi liên kết lại

Trong quá trình triển khai, thao tác so sánh chuỗi ký tự (MaSP, HangSX) được chuẩn hóa bằng hàm thư viện strcmp(). Việc hoán vị giữa hai phần tử trên mảng cấu trúc được thực hiện qua hàm swap hoán đổi toàn bộ bản ghi. Đối với danh sách liên kết đơn, tác giả áp dụng phương thức hoán đổi nội dung trường dữ liệu data giữa các nút thay vì thay đổi các liên kết con trỏ pNext (ngoại trừ hàm Insert_Sorted và QuickSort can thiệp trực tiếp vào cấu trúc liên kết nút).

Kết quả và đóng góp

Văn bản đồ án ghi nhận các kết quả thực nghiệm sau quá trình chạy thử nghiệm chương trình:

  • Toàn bộ 10 phần tử dữ liệu đồng hồ mẫu đã được đưa vào kiểm thử thành công trên cả hai cấu trúc lưu trữ.
  • Kết quả tìm kiếm tuyến tính và tìm kiếm nhị phân trên mảng phản ánh chính xác thông tin bản ghi cần tìm khi đối chiếu khóa chính hoặc khóa phụ.
  • Các giải thuật sắp xếp trên mảng cấu trúc trả về thứ tự dữ liệu chuẩn xác theo từng trường thuộc tính:
    • Sắp xếp theo giá bán (InsertionSort): Sắp xếp thành công danh sách từ giá thấp nhất 2 triệu đồng (Timex) đến giá cao nhất 100 triệu đồng (Rolex).
    • Sắp xếp theo trọng lượng (BubbleSort): Danh sách sau sắp xếp hiển thị trọng lượng tăng dần từ 55g (Omega) đến 180g (Tissot).
    • Sắp xếp theo mã sản phẩm (ShakerSort, SelectionSort): Sắp xếp đúng theo thứ tự từ điển của chuỗi ký tự số.
  • Về mặt lý thuyết cấu trúc dữ liệu, tác giả đóng góp việc làm rõ ranh giới ứng dụng giữa mảng tĩnh và danh sách liên kết đơn. Tác giả chỉ ra cụ thể hai trường hợp bất khả thi trên danh sách liên kết đơn:
    1. Không thể áp dụng Binary Search do danh sách liên kết đơn không có cơ chế định chỉ số trực tiếp truy xuất phần tử giữa $O(1)$.
    2. Không thể áp dụng Shaker Sort do cấu trúc nút chỉ có một con trỏ pNext hướng về phía sau, không thể thực hiện lượt duyệt lùi từ cuối về đầu danh sách.

Hạn chế và hướng nghiên cứu tiếp

Dựa trên nội dung trình bày trong văn bản, đồ án bộc lộ một số hạn chế kỹ thuật:

  • Dữ liệu thử nghiệm có quy mô nhỏ (chỉ gồm 10 bản ghi mẫu, thậm chí một số hàm kiểm thử main() chỉ chạy trên tập con 2 hoặc 4 phần tử), chưa đánh giá được hiệu năng thực tế về thời gian chạy (execution time) hoặc dung lượng bộ nhớ tiêu thụ khi số lượng phần tử tăng lên mức lớn.
  • Mã nguồn có một số điểm chưa nhất quán giữa các phần:
    • Chiều dài khai báo trường HangSX và GioiTinh ở Chương 1 là 10 ký tự (char HangSX[10]), nhưng trong định nghĩa cấu trúc của Chương 3 lại tăng lên 20 ký tự (char HangSX[20]).
    • Trong Chương 3, tiêu đề mục 3.9 ghi sắp xếp theo "thời gian Bảo hành" nhưng bên trong mã nguồn hàm Insert_Sorted lại so sánh theo trường Gia.
    • Mục 3.2 (bước 4) của Chương 3 xuất hiện đoạn mã nguồn nhập liệu chứa tên biến và kiểu dữ liệu không thuộc đối tượng đồ án (BeCon, TTBC, "Nhap thong tin nhan vien"), cho thấy việc tái sử dụng đoạn mã nguồn mẫu chưa được hiệu chỉnh đồng bộ.
    • Các giải thuật Merge Sort có tên trong danh mục chức năng ban đầu nhưng chưa được trình bày mã nguồn cài đặt và kết quả kiểm thử trong nội dung chi tiết.

Các hướng phát triển tiếp theo được gợi mở từ giới hạn nghiên cứu:

  • Mở rộng cấu trúc sang danh sách liên kết đôi (Doubly Linked List) với hai con trỏ pNext và pPrev để hiện thực hóa hoàn chỉnh giải thuật Shaker Sort và tối ưu hóa các thao tác duyệt ngược.
  • Cài đặt đầy đủ giải thuật Merge Sort trên cả hai cấu trúc dữ liệu như dự kiến ban đầu.
  • Xây dựng mô đun đo lường thời gian thực thi (tính bằng mili-giây) và đếm số phép so sánh, số lần hoán vị để so sánh thực nghiệm độ phức tạp thuật toán giữa các giải thuật $O(n^2)$ và $O(n \log n)$.

Giá trị tham khảo

Báo cáo đồ án mang lại giá trị tham khảo cụ thể cho sinh viên ngành Công nghệ thông tin, Kỹ thuật phần mềm và Hệ thống thông tin quản lý khi tiếp cận môn học Cấu trúc dữ liệu và giải thuật:

  • Cung cấp mô hình tham chiếu chi tiết về cách ánh xạ một thực thể kinh doanh cụ thể (danh mục sản phẩm đồng hồ với nhiều kiểu dữ liệu hỗn hợp: chuỗi ký tự, số nguyên, số thực) vào cấu trúc bản ghi struct trong C++.
  • Minh họa phương pháp cài đặt song song các giải thuật sắp xếp kinh điển (Selection Sort, Interchange Sort, Bubble Sort, Insertion Sort, Quick Sort) trên hai cấu trúc lưu trữ khác nhau, giúp người học nắm bắt sự khác biệt giữa thao tác mảng dựa trên chỉ số số học và thao tác danh sách liên kết dựa trên con trỏ bộ nhớ.
  • Phần phân tích lý do không áp dụng được Binary Search và Shaker Sort trên danh sách liên kết đơn là tài liệu đối sánh trực quan, hỗ trợ củng cố hiểu biết lý thuyết về đặc trưng truy xuất tuần tự của cấu trúc động.

Câu hỏi thường gặp

1. Cấu trúc dữ liệu struct dongho trong đồ án gồm những trường thông tin nào và miền giá trị của chúng ra sao?
Cấu trúc dongho gồm 6 trường thông tin: MaSP (chuỗi 11 ký tự số), HangSX (chuỗi tối đa 10 ký tự, ở Chương 3 khai báo 20 ký tự), GioiTinh (chuỗi tối đa 10 ký tự, ở Chương 3 khai báo 20 ký tự), TrongLuong (số nguyên không âm $\ge 0$, đơn vị gram), BaoHanh (số nguyên không âm $\ge 0$, đơn vị tháng), và Gia (số thực dương $\ge 0$, đơn vị triệu VND).

2. Tập dữ liệu mẫu dùng trong các hàm kiểm thử của đồ án có những sản phẩm cụ thể nào?
Tập dữ liệu mẫu gồm 10 sản phẩm đồng hồ: Casio (1910, Nam, 70g, 60 tháng, 5 triệu), Tag Heuer (1901, Nam, 160g, 23 tháng, 34 triệu), Rolex (1903, Nam, 156g, 24 tháng, 100 triệu), Omega (1904, Trung tính, 55g, 12 tháng, 23 triệu), Longines (1907, Nữ, 140g, 12 tháng, 23 triệu), Tissot (1906, Trung tính, 180g, 12 tháng, 5,4 triệu), Timex (1905, Trung tính, 100g, 12 tháng, 2 triệu), Calvin Klein (1908, Nữ, 90g, 24 tháng, 5 triệu), Movado (1902, Nam, 100g, 16 tháng, 12 triệu), Citizen (1909, Nam, 150g, 24 tháng, 2,5 triệu).

3. Tại sao tác giả khẳng định giải thuật Shaker Sort và Binary Search không thể áp dụng trên danh sách liên kết đơn?
Theo tác giả, Binary Search yêu cầu xác định trực tiếp phần tử ở giữa danh sách bằng chỉ số để thu hẹp phạm vi tìm kiếm, điều mà danh sách liên kết đơn không hỗ trợ do phải duyệt tuần tự từ đầu. Đối với Shaker Sort, giải thuật yêu cầu hai lượt duyệt luân phiên: lượt đi đưa phần tử nhỏ nhất về đầu và lượt về duyệt ngược từ phần tử cuối cùng để đẩy phần tử lớn nhất về cuối dãy; danh sách liên kết đơn chỉ có liên kết một chiều từ trước ra sau nên không thể duyệt ngược từ cuối danh sách.

4. Thuật toán Quick Sort trên danh sách liên kết đơn được tác giả thiết kế theo cơ chế nào?
Tác giả thiết kế hàm QuickSort(LIST *list) bằng cách chọn nút đầu tiên làm nút chốt x, sau đó tách danh sách ban đầu thành hai danh sách con l1 và l2. Danh sách l1 lưu trữ các nút có trường dữ liệu nhỏ hơn hoặc bằng trường dữ liệu của x, danh sách l2 lưu trữ các nút có dữ liệu lớn hơn hoặc bằng x. Tiếp theo, giải thuật sắp xếp từng danh sách con và nối các thành phần l1, x, l2 lại với nhau để tạo thành danh sách hoàn chỉnh.

5. Các giải thuật sắp xếp trên mảng cấu trúc được phân công sắp xếp theo những trường dữ liệu nào?
Trên mảng cấu trúc, tác giả phân chia tiêu chí sắp xếp cụ thể: ShakerSort và SelectionSort sắp xếp theo MaSP; InterchangeSort sắp xếp theo chuỗi tên HangSX; BubbleSort sắp xếp theo TrongLuong; InsertionSort sắp xếp theo trường Gia; và QuickSort sắp xếp theo thời gian BaoHanh.

Kết luận

Đồ án môn học "Cấu trúc dữ liệu và giải thuật" của sinh viên Đỗ Tường Vy đã giải quyết bài toán quản lý danh mục sản phẩm đồng hồ thông qua việc cài đặt các giải thuật tìm kiếm và sắp xếp trên mảng cấu trúc và danh sách liên kết đơn bằng C++. Nghiên cứu đã kiểm thử thành công các thuật toán kinh điển trên bộ dữ liệu mẫu gồm 10 bản ghi, đồng thời chỉ ra các giới hạn vận hành của giải thuật tìm kiếm nhị phân và Shaker Sort trên danh sách liên kết một chiều. Báo cáo là tài liệu học thuật thực hành có cấu trúc rõ ràng, phục vụ hữu ích cho việc học tập và củng cố kiến thức nền tảng trong chuyên ngành công nghệ thông tin.