Tại sao lại chèn vào giữa danh sách liên kết O (1)?


105

Theo bài viết Wikipedia về danh sách liên kết , việc chèn vào giữa danh sách liên kết được coi là O (1). Tôi nghĩ nó sẽ là O (n). Bạn có cần phải xác định nút có thể ở gần cuối danh sách không?

Phân tích này không giải thích cho việc tìm ra hoạt động của nút (mặc dù nó là bắt buộc) và chỉ là phần chèn?

CHỈNH SỬA :

Danh sách được liên kết có một số lợi thế so với mảng. Chèn một phần tử tại một điểm cụ thể của danh sách là một hoạt động thời gian không đổi, trong khi việc chèn vào một mảng có thể yêu cầu di chuyển một nửa số phần tử hoặc nhiều hơn.

Tuyên bố trên là một chút sai lầm đối với tôi. Hãy sửa cho tôi nếu tôi sai, nhưng tôi nghĩ kết luận nên là:

Mảng:

  • Tìm điểm chèn / xóa O (1)
  • Thực hiện chèn / xóa O (n)

Danh sách được Liên kết:

  • Tìm điểm chèn / xóa O (n)
  • Thực hiện chèn / xóa O (1)

Tôi nghĩ rằng lần duy nhất bạn không phải tìm vị trí là nếu bạn giữ một số loại con trỏ vào nó (như với phần đầu và phần đuôi trong một số trường hợp). Vì vậy, chúng tôi không thể nói thẳng rằng danh sách được liên kết luôn đánh bại các mảng cho các tùy chọn chèn / xóa.

Câu trả lời:


113

Bạn nói đúng, bài viết coi "Lập chỉ mục" là một thao tác riêng biệt. Vì vậy, nút chèn chính nó là O (1), nhưng đến nút giữa đó là O (n).


3
Mà làm cho một sự khác biệt lớn khi chèn hơn 1 đối tượng ở vị trí tương đương ...
Có QUIT - Anony-Mousse

@ Anony-Mousse bạn có thể giải thích thêm một chút được không? tức là chúng ta cần tìm vị trí chèn một lần duy nhất khi chèn nhiều đối tượng?
MyTitle

2
Đó là O (n) với kích thước của danh sách hiện có, không phải là số lần chèn bạn định thực hiện ở đó.
Có QUIT - Anony-Mousse


25

Không, khi bạn quyết định rằng bạn muốn chèn, có nghĩa là bạn đã ở giữa việc lặp qua danh sách.

Các hoạt động trên Danh sách được liên kết thường được thực hiện theo cách mà chúng không thực sự được coi là một "danh sách" chung chung, mà là một tập hợp các nút - hãy nghĩ về chính nút đó như là trình vòng lặp cho vòng lặp chính của bạn. Vì vậy, khi xem qua danh sách, bạn nhận thấy như một phần của logic kinh doanh của mình rằng một nút mới cần được thêm vào (hoặc một nút cũ bị xóa) và bạn làm như vậy. Bạn có thể thêm 50 nút trong một lần lặp và mỗi nút đó chỉ là O (1) thời gian để hủy liên kết hai nút liền kề và chèn nút mới của bạn ..

Chỉnh sửa: Trời ạ, bạn gõ đoạn thứ hai và đột nhiên thay vì là người trả lời đầu tiên, bạn là người thứ 5 nói điều tương tự với 4 đoạn đầu tiên!


1
Ha yeah, điều đó thật tệ ... tôi đã +1 của bạn bởi vì điều đáng nói là độ phức tạp của việc chèn danh sách liên kết được xem xét trong bối cảnh đã ở con trỏ mong muốn.
Daniel Macias

6

Đối với mục đích so sánh với một mảng, biểu đồ hiển thị, đó là O (1) vì bạn không phải di chuyển tất cả các mục sau nút mới.

Vì vậy, có, họ đang giả định rằng bạn đã có con trỏ đến nút đó, hoặc việc nhận được con trỏ là không bình thường. Nói cách khác, vấn đề được nêu: "Đã cho nút tại X , mã để chèn sau nút này là gì?" Bạn có thể bắt đầu tại điểm chèn.


5

Chèn vào danh sách được liên kết khác với việc lặp lại trên đó. Bạn không định vị mục, bạn đang đặt lại con trỏ để đưa mục vào đó. Không quan trọng nếu nó sẽ được chèn gần đầu trước hay gần cuối, việc chèn vẫn liên quan đến các con trỏ được chỉ định lại. Tất nhiên, nó sẽ phụ thuộc vào cách nó được triển khai, nhưng đó là điểm mạnh của danh sách - bạn có thể chèn dễ dàng. Truy cập thông qua chỉ mục là nơi một mảng tỏa sáng. Tuy nhiên, đối với một danh sách, thông thường sẽ là O (n) để tìm mục thứ n. Ít nhất đó là những gì tôi nhớ từ trường.


3

Bởi vì nó không liên quan đến bất kỳ vòng lặp nào.

Chèn giống như:

  • chèn phần tử
  • liên kết đến trước đó
  • liên kết đến tiếp theo
  • làm xong

đây là thời gian không đổi trong mọi trường hợp.

Do đó, chèn n phần tử lần lượt là O (n).


3

Phân tích này không giải thích cho việc tìm ra hoạt động của nút (mặc dù nó là bắt buộc) và chỉ là phần chèn?

Bạn đã hiểu. Chèn tại một điểm nhất định giả sử rằng bạn đã giữ một con trỏ đến mục mà bạn muốn chèn sau:

InsertItem(item * newItem, item * afterItem)


2

Không, nó không tính đến việc tìm kiếm. Nhưng nếu bạn đã có một con trỏ đến một mục ở giữa danh sách, thì việc chèn tại điểm đó là O (1).

Nếu bạn phải tìm kiếm nó, bạn phải thêm vào thời gian tìm kiếm, phải là O (n).


0

Bài viết về so sánh mảng với danh sách. Tìm vị trí chèn cho cả mảng và danh sách là O (N) nên bài báo bỏ qua.


1
Tìm điểm chèn của một mảng có phải là O (1) không? Vì các mảng được lưu trữ trong bộ nhớ liền kề, tất cả những gì nó phải làm là thêm phần bù vào.
Rob Sobers

@ vg1890 - Bạn phải tìm phần bù trước.

0

O (1) là tùy thuộc vào thực tế rằng bạn có một mục mà bạn sẽ chèn mục mới. (trước hoặc sau). Nếu bạn không, nó là O (n) vì bạn phải tìm thấy món đồ đó.


0

Tôi nghĩ đó chỉ là một trường hợp bạn chọn để tính cho ký hiệu O (). Trong trường hợp chèn hoạt động bình thường để đếm là các hoạt động sao chép. Với một mảng, việc chèn vào giữa bao gồm việc sao chép mọi thứ phía trên vị trí lên trong bộ nhớ. Với một danh sách được liên kết, điều này sẽ trở thành thiết lập hai con trỏ. Bạn cần phải tìm vị trí không có vấn đề gì để chèn.


0

Nếu bạn có tham chiếu của nút để chèn sau hoạt động là O (1) cho một danh sách liên kết.
Đối với một mảng, nó vẫn là O (n) vì bạn phải di chuyển tất cả các nút liên quan.


0

Các trường hợp phổ biến nhất có lẽ là chèn ở đầu hoặc cuối danh sách (và cuối danh sách có thể mất thời gian để tìm).

Ngược lại với việc chèn các mục vào đầu hoặc cuối mảng (yêu cầu thay đổi kích thước mảng nếu ở cuối hoặc thay đổi kích thước và di chuyển tất cả các phần tử nếu ở đầu).


Có thể làm cho các mục chèn vào cuối một mảng là O (1) nếu bạn giữ một vùng đệm gồm các phần tử trống ở cuối, mặc dù đôi khi các mục chèn vẫn là O (1). Hầu hết các bộ sưu tập đều làm được điều này. Cũng có thể làm cho các mục trơ vào đầu mảng là O (1) bằng cách thay đổi toán tử chỉ mục của bạn để trả về số phần tử (n + x)% len, trong đó x là số lần bạn đã chèn các mục vào đầu của danh sách. Deques đôi khi được triển khai như thế này (nhưng đôi khi cũng được triển khai với danh sách được liên kết kép.
Brian
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.