VieTopikKhoá học
  • Games
  • Cá nhân
Tải app
© 2026 VieTopikChính sách bảo mậtĐiều khoản sử dụngCài appEnglish
  • Trang chủ
  • Học
  • Luyện thi
  • Cẩm nang
  • Games
  • Cá nhân
Cấu trúc dữ liệu và giải thuậtCấu trúc tuyến tính
Bài 4/18
5 phút

Linked list

Bình luận
Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

Chèn một đơn gấp vào đầu List<T> thì mọi đơn phía sau phải dời chỗ, tốn O(n). Linked list không xếp phần tử liền nhau, nên chèn vào đầu chỉ mất một bước. Đổi lại, muốn tới phần tử thứ 1000 thì phải đi qua 999 phần tử trước.

Khái niệm

⛓️ Linked list: danh sách mà mỗi phần tử (gọi là node) giữ giá trị và tham chiếu tới node kế tiếp, node cuối trỏ tới null.

Tham chiếu tới node kế tiếp (property Next trong ví dụ) không chứa node đó, mà chỉ trỏ tới nó, như bài Value type và reference type của khoá C# Core.

Ví dụ

var first = new Node("DH1");
first.Next = new Node("DH2");
first.Next.Next = new Node("DH3");

Node? current = first;
while (current != null)
{
    Console.WriteLine(current.Value);
    current = current.Next;
}

class Node
{
    public string Value { get; }
    public Node? Next { get; set; }

    public Node(string value)
    {
        Value = value;
    }
}
  • Mỗi Node giữ Value và Next. Next của DH3 là null, đánh dấu hết danh sách.
  • Duyệt bằng cách đi theo Next từ node đầu, tới khi gặp null.
  • Node? cho phép biến chứa null, như string? ở bài null và nullable của khoá C# Core.
Thao tác List<T> Linked list
Lấy phần tử thứ i O(1) O(n), đi từ đầu
Thêm vào đầu O(n), dời cả list O(1), đổi một tham chiếu
Thêm vào cuối O(1) trung bình O(1) nếu giữ node cuối

.NET có sẵn LinkedList<T> với AddFirst, AddLast, RemoveFirst, RemoveLast, đều O(1).

LinkedList<T> nối node theo cả hai chiều: mỗi node có Next và Previous. Nó không có list[i], lấy theo vị trí bằng ElementAt(i) thì phải đi từ node đầu.

▶ Mô phỏng: LinkedList đi tìm từng node

var orders = new LinkedList<string>();
orders.AddLast("DH1");
orders.AddLast("DH2");
orders.AddLast("DH3");
orders.AddLast("DH4");
Console.WriteLine(orders.ElementAt(1));
Console.WriteLine(orders.ElementAt(3));
orders.RemoveFirst();
Xem từng bước
  1. AddLast(DH1): list đang rỗng, first và last cùng trỏ tới node DH1.
  2. AddLast(DH2): next của DH1 trỏ tới node mới, prev của nó trỏ về DH1, last trỏ tới nó. Đổi 3 tham chiếu: O(1).
  3. AddLast(DH3): next của DH2 trỏ tới node mới, prev của nó trỏ về DH2, last trỏ tới nó. Đổi 3 tham chiếu: O(1).
  4. AddLast(DH4): next của DH3 trỏ tới node mới, prev của nó trỏ về DH3, last trỏ tới nó. Đổi 3 tham chiếu: O(1).
  5. ElementAt(1): không nhảy thẳng được, bắt đầu từ first: đang ở DH1, vị trí 0.
  6. Tới vị trí 1: ElementAt(1) ra DH2 sau 1 bước đi theo next. Không có ô đánh số nên phải đi từng node: O(n).
  7. ElementAt(3): không nhảy thẳng được, bắt đầu từ first: đang ở DH1, vị trí 0.
  8. Đi theo next: tới DH2, vị trí 1. Chưa tới, đi tiếp.
  9. Đi theo next: tới DH3, vị trí 2. Chưa tới, đi tiếp.
  10. Tới vị trí 3: ElementAt(3) ra DH4 sau 3 bước đi theo next. Không có ô đánh số nên phải đi từng node: O(n).
  11. RemoveFirst(): bỏ node DH1, first chuyển sang DH2. Chỉ đổi tham chiếu: O(1).

Thử ngay

Thêm đơn gấp DH0 vào đầu danh sách. Đặt ba dòng này ngay trên dòng Node? current = first;:

var urgent = new Node("DH0");
urgent.Next = first;
first = urgent;

Đoán trước khi chạy: danh sách in ra theo thứ tự nào? Có node nào phải dời chỗ không?

Xem kết quả
DH0
DH1
DH2
DH3

DH0 đứng đầu nhưng không node nào phải dời. Chỉ có hai tham chiếu đổi: urgent.Next trỏ tới DH1, và first trỏ tới urgent.

Lỗi hay gặp

Lấy phần tử theo vị trí trên LinkedList<T>. Linked list không có ô đánh số, nên không có [i].

// SAI — lỗi compile: LinkedList không có [i]
var orders = new LinkedList<string>();
orders.AddLast("DH1");
orders.AddLast("DH2");
Console.WriteLine(orders[1]);
// ĐÚNG — cần lấy theo vị trí thì dùng List<T>
var orders = new List<string>();
orders.Add("DH1");
orders.Add("DH2");
Console.WriteLine(orders[1]);

Tóm tắt

  • Linked list gồm các node, mỗi node giữ giá trị và tham chiếu tới node kế.
  • Thêm, bớt ở đầu là O(1). Lấy phần tử thứ i là O(n).
  • .NET có LinkedList<T>. Không có [i].
  • Trong thực tế, List<T> thường nhanh hơn vì các ô nằm liền nhau. Chỉ dùng linked list khi thêm bớt ở đầu hoặc giữa thật nhiều.
Array và List bên trongStack

Bình luận

Đang tải bình luận…

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt