[Khái quát] Cấu trúc dữ liệu


TỔNG QUAN CẤU TRÚC DỮ LIỆU

Cấu trúc dữ liệu là một thành phần không thể thiếu trong môn học. Nó áp dụng cho rất nhiều, hầu như là toàn bộ bài toán dù lớn hay nhỏ. Thế cấu trúc dữ liệu là gì?
Trích Wikipedia EN: “Trong ngành khoa học máy tính, cấu trúc dữ liệu là cách tổ chức, quản lý và lưu trữ dữ liệu theo một định dạng nào đó mà ta có thể truy cập và chỉnh sửa một cách hiệu quả. Nói đúng hơn, cấu trúc dữ liệu là một tập các dữ liệu, mối quan hệ giữa chúng, và các hàm hoặc toán tử có thể áp dụng lên chúng.
Theo Wiki, ta có thể hiểu nôm na rằng đó là một cách tổ chức (bao gồm bố trí, quản lý, lưu trữ,…) để ta có thể dễ dàng thao tác trên dữ liệu (truy cập; chỉnh sửa – thêm, xóa, sắp xếp;…). Dùng một Arrays để lưu trữ danh sách điểm số, tên của các thành viên trong một lớp học, cũng có thể xem như là một cách cấu trúc dữ liệu, vì Arrays này có sự bố trí các dữ liệu cùng loại liền kề nhau, khi duyệt từng ô dữ liệu để thao tác sẽ khá là dễ dàng.
Một cách định nghĩa tương tự của geeksforgeek ngắn gọn: “Cấu trúc dữ liệu là một cách tổ chức dữ liệu trên máy tính cụ thể sao cho chúng có thể được sử dụng một cách hiệu quả”. Khi đã hiểu khái niệm rồi thì định nghĩa tổng quát này sẽ giúp bạn dễ nhớ hơn.
Dưới đây mình sẽ đưa ra một vài cấu trúc dữ liệu tiêu biểu, để cho các bạn hình dung rõ hơn về nó.
Arrays


Hình 1: Lưu trữ chuỗi số dùng cấu trúc dữ liệu Arrays
Ở hình 1, chúng ta dùng Arrays để lưu trữ chuỗi số 1, 6, 5, 8, 10. Chú ý các địa chỉ cách nhau 1 đơn vị, nghĩa là các số được lưu trữ liền kề nhau. Tập các ô nhớ liền kề nhau tạo thành một vùng nhớ. Một vùng nhớ có các giá trị liên quan với nhau sẽ dễ dàng hơn trong việc xử lí. Giả dụ như khi bạn muốn tìm kiếm số 5 trong chuỗi số 1, 6, 5, 8, 10. Giả sử có rất nhiều chuỗi khác cũng lưu trữ trong bộ nhớ, nhưng ta chỉ muốn tìm số 5 trong chuỗi trên mà thôi. Chính nhờ việc sắp xếp liền kề nhau, máy tính sẽ biết khu vực 201-205 là khu vực của chuỗi 1, 6, 5, 8, 10, và chỉ cần tiếp cận khu vực đó duyệt từng phần tử là được.
LinkedList


Hình 2: Lưu trữ chuỗi số dùng cấu trúc dữ liệu LinkedList
Đây là một dạng lưu trữ liên kết, không phụ thuộc vào vị trí giữa các phần tử. Một phần tử ngoài lưu trữ dữ liệu, còn lưu trữ con trỏ dẫn đến dữ liệu tiếp theo. Hình 2 là một LinkedList lưu trữ một chuỗi số 1, 5, 6, 10, 8. Chắc hẳn bạn đang có một thắc mắc, việc lưu trữ một chuỗi số phức tạp hơn cả Arrays, nhưng tại sao nó vẫn được sử dụng. Chúng ta hãy xét đến nhược điểm của Arrays và ưu điểm của LinkedList để tìm ra lí do.
Arrays có kích thước cố định. Chúng ta sẽ thử cho một ví dụ để hiểu vì sao kích thước của Arrays là cố định.
Chúng ta có một dòng code
int[] Arrays = new int[3];
i[0]=2;
i[1]=4;
i[2]=6;
int x = 18;
Như thế, trong ô nhớ máy tính sẽ biểu thị như sau


Hình 3: Ví dụ về cấu trúc dữ liệu
Vùng nhớ có địa chỉ từ 201-203 là vùng nhớ của Arrays, và ô nhớ 204 là của bộ nhớ x. Giả sử chúng ta tồn tại dòng lệnh add() trong Arrays với chức năng thêm phần tử vào cuối Arrays, ta thêm một dòng lệnh như sau.
arrays.add(8);
Với cương vị là một người tạo ra ngôn ngữ Java, bạn làm thế nào để Arrays nằm trong một vùng nhớ, và x vẫn giữ nguyên vị trí cũ? Nếu bạn đẩy x vào ô nhớ 205 và thay ô nhớ 204 thành số 8, điều này sẽ rất nguy hiểm vì việc thay đổi vị trí ô nhớ có thể dẫn đến nhiều sự sai lệch trong tính toán, ví dụ như ô nhớ 205 đã có giá trị nào đó và bạn đè giá trị 18 lên ô nhớ ấy (tất nhiên bạn có thể xử lí bằng cách nào đó nữa nhưng như thế sẽ tốn rất nhiều thời gian và nó sẽ phức tạp thêm). Hoặc một cách giải quyết như bài toán nối 2 chuỗi mà String trong Java đã làm, đó là dành ra một vùng nhớ mới và lưu trữ các giá trị. Có vẻ vì sự phiền phức đó mà Java đã không làm, mà thay vào đó là sự ra đời của LinkedList. Nếu ta muốn thêm số 8 vào trong chuỗi đã cho, ta chỉ cần lưu số 8 vào một ô nhớ x bất kì, và cho ô nhớ 203 một pointer trỏ đến ô nhớ x đó là xong.

Tóm lại, các thao tác làm thay đổi kích thước trên Arrays là không thể, đó là điểm yếu lớn nhất của Arrays khiến cho LinkedList ra đời. Tuy độ phức tạp sẽ cao hơn một tí nhưng sẽ giải quyết được bài toán kích thước. Phụ thuộc vào ưu nhược điểm của từng loại cấu trúc dựa trên bài toán cụ thể mà ta sẽ chọn loại nào phù hợp.
Graph
Như đã giới thiệu ở bài trước, graph là một đồ thị dùng để mô hình lại dữ liệu có liên kết với nhau, phục vụ cho việc học tập, nghiên cứu. Trong cấu trúc dữ liệu, graph cũng được xem như một loại cấu trúc thể hiện rõ quan hệ giữa các dữ liệu theo dạng non-linear (phi tuyến tính). Quan hệ tuyến tính giữa các dữ liệu được xem là quan hệ theo một đường có thứ tự nhất định. Các cấu trúc dữ liệu Arrays và LinkedList là những dạng tuyến tính, còn ở graph có một sự đa dạng hơn, không chỉ sắp xếp theo một đường thẳng có thứ tự, mà mỗi phần tử còn có thể liên kết tới nhiều phần tử khác, hoặc chính nó. Sự đa dạng của nó giúp giải quyết được nhiều bài toán thực tế, bởi vốn dĩ mối liên kết giữa các đối tượng ngoài thực tế đâu chỉ là một đường thẳng đâu, nhỉ!
Tổng kết lại bài, chúng ta đã tìm hiểu về cấu trúc dữ liệu và các dạng cơ bản của nó. Mình cũng muốn giải thích tổng quan từng bài một trong môn Cấu trúc dữ liệu nhưng có vẻ sẽ khá là dài, nên mình xin kết thúc tại đây. Cảm ơn các bạn đã theo dõi!
Nội dung bài viết thuộc về Lê Công Diễn.

Người viết: Lê Công Diễn
Mang đi nhớ ghi nguồn

Nhận xét

Bài đăng phổ biến từ blog này

Deploy project Springboot MIỄN PHÍ sử dụng Render

Ứng dụng Mã hóa bất đối xứng (Asymmetric cryptography) vào Chữ ký số (Digital Signature)

API và HTTP - Một số khái niệm cơ bản cần biết về Web (Phần 2)