Danh sách liên kết
Trang này sẽ giới thiệu tóm tắt về danh sách liên kết.
Giới thiệu
Danh sách liên kết (Linked List) là một cấu trúc dữ liệu dùng để lưu trữ dữ liệu, kết nối các phần tử thông qua các con trỏ giống như một sợi dây xích. Đặc điểm của nó là việc chèn và xóa dữ liệu rất thuận tiện, nhưng hiệu suất tìm kiếm và đọc dữ liệu lại kém.
So sánh với mảng
Cả danh sách liên kết và mảng (Array) đều có thể dùng để lưu trữ dữ liệu. Khác với danh sách liên kết, mảng lưu trữ tất cả các phần tử theo thứ tự liên tiếp. Các cấu trúc lưu trữ khác nhau mang lại những ưu thế khác nhau cho chúng:
Danh sách liên kết nhờ cấu trúc dạng chuỗi nên có thể dễ dàng xóa, chèn dữ liệu, độ phức tạp thao tác là \(O(1)\). Nhưng cũng chính vì vậy, hiệu quả tìm kiếm, đọc dữ liệu không cao bằng mảng, độ phức tạp thao tác truy cập ngẫu nhiên là \(O(n)\).
Mảng có thể thuận tiện tìm kiếm và đọc dữ liệu, độ phức tạp thao tác truy cập ngẫu nhiên là \(O(1)\). Nhưng độ phức tạp thao tác xóa, chèn là \(O(n)\).
Xây dựng danh sách liên kết
Mẹo
Khi xây dựng danh sách liên kết, phần sử dụng con trỏ khá trừu tượng. Chỉ dựa vào văn bản và code có thể khó hiểu, khuyến khích kết hợp với hình vẽ để hiểu rõ hơn.
Danh sách liên kết đơn
Danh sách liên kết đơn bao gồm trường dữ liệu và trường con trỏ, trong đó trường dữ liệu dùng để chứa dữ liệu, trường con trỏ dùng để kết nối nút hiện tại và nút tiếp theo.
Hiện thực
1 2 3 4 | |
1 2 3 4 | |
Danh sách liên kết đôi
Danh sách liên kết đôi cũng có trường dữ liệu và trường con trỏ. Điểm khác biệt là trường con trỏ có phân biệt trái phải (hoặc trước, sau), dùng để kết nối nút phía trước, nút hiện tại và nút phía sau.
Hiện thực
1 2 3 4 5 | |
1 2 3 4 5 | |
Chèn dữ liệu vào danh sách liên kết
Danh sách liên kết đơn
Quy trình đại khái như sau:
- Khởi tạo dữ liệu
nodecần chèn; - Trỏ con trỏ
nextcủanodevào nút tiếp theo củap; - Trỏ con trỏ
nextcủapvàonode.
Quá trình cụ thể có thể tham khảo hình dưới đây:
Code hiện thực như sau:
Hiện thực
1 2 3 4 5 6 | |
1 2 3 4 5 | |
Danh sách liên kết vòng đơn
Nối đầu và đuôi danh sách lại, danh sách liên kết trở thành danh sách liên kết vòng (Circular Linked List). Do danh sách nối đầu đuôi, khi chèn dữ liệu cần kiểm tra danh sách gốc có rỗng không: nếu rỗng thì tự vòng lại chính nó, nếu không rỗng thì chèn dữ liệu bình thường.
Quy trình đại khái như sau:
- Khởi tạo dữ liệu
nodecần chèn; - Kiểm tra danh sách
pđã cho có rỗng không; - Nếu rỗng, trỏ con trỏ
nextcủanodevà cảpvào chínhnode; - Nếu không, trỏ con trỏ
nextcủanodevào nút tiếp theo củap; - Trỏ con trỏ
nextcủapvàonode.
Quá trình cụ thể có thể tham khảo hình dưới đây:
Code hiện thực như sau:
Hiện thực
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 5 6 7 8 9 10 | |
Danh sách liên kết vòng đôi
Khi chèn dữ liệu vào danh sách liên kết vòng đôi, ngoài việc kiểm tra danh sách đã cho có rỗng không, còn cần sửa đổi đồng thời hai con trỏ trái, phải.
Quy trình đại khái như sau:
- Khởi tạo dữ liệu
nodecần chèn; - Kiểm tra danh sách
pđã cho có rỗng không; - Nếu rỗng, trỏ cả con trỏ
leftvàrightcủanode, cũng nhưpvào chínhnode; - Nếu không, trỏ con trỏ
leftcủanodevàop; - Trỏ con trỏ
rightcủanodevào nút bên phải củap; - Trỏ con trỏ
leftcủa nút bên phảipvàonode; - Trỏ con trỏ
rightcủapvàonode.
Code hiện thực như sau:
Hiện thực
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
Xóa dữ liệu khỏi danh sách liên kết
Danh sách liên kết đơn (vòng)
Giả sử nút cần xóa là p, khi xóa nó khỏi danh sách, chỉ cần ghi đè giá trị của nút tiếp theo p->next lên p, đồng thời cập nhật nút sau của nút tiếp theo. (Lưu ý: Cách này giả định p không phải là nút cuối cùng hoặc danh sách là vòng).
Quy trình đại khái như sau:
- Gán giá trị của nút tiếp theo cho
p, để xóa bỏp->valuecũ; - Tạo một nút tạm
tđể lưu địa chỉ củap->next; - Trỏ con trỏ
nextcủapvào nút sau của nút tiếp theo (tức làp->next->next), để xóa bỏ liên kết tớip->nextcũ; - Xóa
t. Lúc này tuy địa chỉ của nútpgốc vẫn đang được sử dụng, cái bị xóa thực chất là nútp->nextgốc, nhưng do dữ liệu củapđã bịp->nextghi đè,pcũ coi như đã biến mất.
Quá trình cụ thể có thể tham khảo hình dưới đây:
Code hiện thực như sau:
Hiện thực
1 2 3 4 5 6 | |
1 2 3 | |
Danh sách liên kết vòng đôi
Quy trình đại khái như sau:
- Trỏ con trỏ phải của nút bên trái
pvào nút bên phảip; - Trỏ con trỏ trái của nút bên phải
pvào nút bên tráip; - Tạo một nút tạm
tlưu địa chỉ củap; - Gán địa chỉ nút bên phải
pchop, để tránhptrở thành con trỏ lơ lửng (dangling pointer); - Xóa
t.
Code hiện thực như sau:
Hiện thực
1 2 3 4 5 6 7 | |
1 2 3 4 | |
Kỹ thuật
Danh sách liên kết XOR
Danh sách liên kết XOR (XOR Linked List) về bản chất vẫn là danh sách liên kết đôi, nhưng nó tận dụng giá trị phép XOR bit để chỉ sử dụng bộ nhớ của một con trỏ mà vẫn thực hiện được chức năng của danh sách liên kết đôi.
Chúng ta định nghĩa lr = left ^ right trong cấu trúc Node, tức là giá trị XOR bit của địa chỉ hai phần tử trước và sau. Khi duyệt xuôi, dùng địa chỉ phần tử trước XOR với lr của nút hiện tại sẽ được địa chỉ phần tử sau; khi duyệt ngược, dùng địa chỉ phần tử sau XOR với lr của nút hiện tại sẽ được địa chỉ phần tử trước.
Như vậy, có thể thực hiện chức năng tương tự danh sách liên kết đôi với một nửa lượng bộ nhớ dành cho con trỏ.
Last updated on this page:, Update history
Found an error? Want to help improve? Edit this page on GitHub!
Contributors to this page:OI-wiki
All content on this page is provided under the terms of the CC BY-SA 4.0 and SATA license, additional terms may apply