1 .GIỚI THIỆU
4. KIỂU DỮ LIỆU DANH SÁCH
4.4 TỔNG QUAN VỀ SÁCH LIÊN KẾT (LINKED LIST) VÀ MẢNG
Tổng quan về mảng
Mảng là một khối vùng nhớ được cấp phát cho toàn bộ mảng để lưu trữ dữ liệu. Các phần tử trong mảng được truy cập trực tiếp một cách nhanh chóng thơng qua chỉ số của mỗi phần tử như trong hình sau:
62
Ưu điểm:
Đơn giản và dễ sử dụng
Truy cập phần tử nhanh (constant access) Hạn chế:
Cố định kích thướng: kích thước của mảng là tĩnh vì phải được chỉ định trước khi sử dụng
Việc cấp phát phải nguyên một khối liên tục: Việc cấp phát vùng nhớ cho mảng đôi khi sẽ không thực hiện được khi kích thước lớn.
Thao tác chèn, xóa phức tạp: Để chèn 1 phần tử vào một vị trí trong mảng, chúng ta cần di chuyển tất cả các phần tử khác (bắt đầu từ vị trí cần chèn cho đến hết mảng) sang bên phải để có chỗ trống thêm phần tử vào đúng vị trí. Thao tác này càng trở nên phức tạp nếu vị trí cần chèn ở đầu mảng.
Mảng động (Dynamic arrays): Mảng động là một cấu trúc dữ liệu danh sách cho phép
các phần tử được thêm hoặc xóa, truy cập ngẫu nhiên. Một cách đơn giản để cài đặt mảng động là bắt đầu khởi tạo với một mảng có kích thước cố định. Khi mảng đầy thì sẽ tạo một mảng mới gấp đơi kích thước so mới mảng ban đầu. Tương tự giảm kích thước mảng đi một nửa nếu số phần tử trong mảng ít hơn một nửa.
Chúng ta sẽ thấy cài đặt của mảng động trong chương 5 (Ngăn xếp và hàng đợi).
Danh sách liên kết (Linked List)
Danh sách liên kết cũng có ưu điểm và hạn chế:
Ưu điểm:
Danh sách liên kết có thể được mở rộng rất nhanh (constant time). Để tạo một mảng thì chúng ta phải cấp phát vùng nhớ với một số lượng phần tử cho trước. Để thêm
63
nhiều phần tử vào mảng khi mảng đầy thì chúng ta phải tạo một mảng mới và sao chép mảng cũ vào mảng mới. Điều này sẽ làm mất rất nhiều thời gian.
Chúng ta có thể khặc phục trường hợp trên bằng cách cấp phát nhiều không gian từ lúc ban đầu cho mảng, nhưng có thể sẽ rơi vào tình trạng cấp nhiều hơn lượng thực tế cần và sẽ lãng phí bộ nhớ. Với linked list, có thể bắt đầu với việc cấp phát không gian cho một phần tử và sẽ thêm phần tử mới một cách dễ dàng mà không cần phải sao chép hay cấp pháp lại vùng nhớ.
Hạn chế:
Có một số vấn đề với linked list. Hạn chế chính của linked list là thời gian truy cập tới mỗi phần tử. Mảng là truy cập ngẫu nhiên (random-access), có nghĩa là chỉ mất O(1) để truy xuất tới bất kỳ phần tử nào trong danh sách. Linked list trong trường hợp xất nhất phải mất O(n) cho việc truy cập tới mỗi phần tử. Mảng được định nghĩa như là một khối ô nhớ liên tục, và các phần tử của mảng sẽ nằm bên cạnh nhau, vì thế thời gian truy cập của mảng rất nhanh (do truy cập với không gian cục bộ).
Mặc dù việc cấp phát động vùng nhớ là một ưu điểm lớn, nhưng với việc lưu trữ và truy xuất dữ liệu thì sẽ phải trả chi phí lớn. Thỉnh thoảng liked list khó thao tác. Nếu phần tử cuối cùng bị xóa, trước khi xóa thì cần phải chỉ ra được con trỏ sẽ lưu trữ tham chiếu NULL, khi đó địi hỏi phải duyệt tồn bộ linked list mới tới liên kết đó.
Cuối cùng, linked list phải mất thêm vùng nhớ cho mỗi phần tử vì phải chứa thêm con trỏ.
Bảng sau thể hiện sự so sánh giữa Linked list, Array, Dynamic Array:
Tiêu chí Linked
List
Array Dynamic Array
64
Chèn/Xóa ở đầu O(1) O(n), nếu mảng không đầy để có thể di chuyển được phần tử
O (n)
Chèn ở cuối O(n) O(1), nếu mảng không đầy O(1) nếu mảng khơng đầy
O(n), nếu mảng đầy
Xóa ở cuối O(n) O(1) O(n)
Chèn ở giữa O(n) O(n), nếu mảng không đầy để có thể di chuyển phần tử
O(n)
Xóa ở giữa O(n) O(n), nếu mảng khơng đầy để có thể di chuyển phần tử
O(n)