Các quy tắc cụ thể để sử dụng một danh sách liên kết thay vì một mảng là gì?


18

Một danh sách được liên kết có thể được sử dụng khi bạn muốn chèn và xóa các phần tử giá rẻ và khi các phần tử không nằm cạnh nhau trong bộ nhớ.

Điều này rất trừu tượng và tôi muốn một lời giải thích cụ thể về lý do tại sao một danh sách được liên kết nên được sử dụng chứ không phải là một mảng. Tôi không có nhiều kinh nghiệm về lập trình, vì vậy tôi chưa có nhiều kinh nghiệm trong thế giới thực.


3
Thành thật mà nói, tôi không nghĩ các ví dụ sẽ có ý nghĩa rất lớn đối với bạn cho đến khi bạn có một số kinh nghiệm viết một cái gì đó, và sau đó thấy hiệu quả của việc thay đổi cấu trúc dữ liệu đối với mã của bạn. Hãy thử viết một cái gì đó bạn quan tâm và tìm ra cấu trúc dữ liệu và bộ chứa nào phù hợp nhất hoặc xem một số mã hiện có và suy nghĩ về lý do tại sao mỗi bộ chứa được chọn và tác động của nó sẽ thay đổi.
Vô dụng

Tôi chỉ không nghĩ rằng có thể hữu ích để truyền đạt sự đánh đổi và tác dụng phụ của việc lựa chọn cấu trúc dữ liệu đến OP (thiếu kinh nghiệm) mà không có ví dụ hoạt động lâu hơn nhiều so với hợp lý ở đây. Các ví dụ được đưa ra dưới dạng câu trả lời là tốt, và trả lời câu hỏi khi được hỏi, nhưng không phải (những gì tôi đọc là) một yêu cầu ngụ ý cho sự hiểu biết thực tế.
Vô dụng

Câu trả lời:


37

Đây là một phần của một ví dụ giữa một ví dụ và một sự tương tự. Bạn có một số việc phải làm, vì vậy bạn lấy một tờ giấy và viết:

  • ngân hàng
  • cửa hàng tạp hóa
  • bỏ khô

Sau đó, bạn nhớ rằng bạn cũng cần phải mua tem. Vì địa lý của thị trấn của bạn, bạn cần phải làm điều đó sau khi ngân hàng. Bạn có thể sao chép toàn bộ danh sách của mình lên một mảnh giấy mới:

  • ngân hàng
  • tem
  • cửa hàng tạp hóa
  • bỏ khô

hoặc bạn có thể viết nguệch ngoạc trên cái bạn có:

  • ngân hàng ....... GIAI ĐOẠN
  • cửa hàng tạp hóa
  • bỏ khô

Khi bạn nghĩ về những việc lặt vặt khác, bạn có thể viết chúng ở cuối danh sách, nhưng với các mũi tên nhắc nhở bạn thứ tự để thực hiện chúng. Đây là một danh sách được liên kết. Nó nhanh hơn và dễ dàng hơn là sao chép toàn bộ danh sách mỗi khi bạn thêm thứ gì đó.

Sau đó, điện thoại di động của bạn đổ chuông trong khi bạn ở ngân hàng "này, tôi đã nhận được tem, không nhận thêm nữa". Bạn chỉ cần gạch chéo STAMPS ra khỏi danh sách, bạn không viết lại một cái hoàn toàn mới mà không có STAMPS trong đó.

Bây giờ bạn thực sự có thể triển khai danh sách việc vặt trong mã (có thể là ứng dụng sắp xếp việc vặt của bạn theo thứ tự dựa trên địa lý của bạn) và có một cơ hội hợp lý bạn thực sự sẽ sử dụng danh sách được liên kết cho mã đó. Bạn muốn thêm và xóa nhiều mục, vấn đề đặt hàng, nhưng bạn không muốn ghi lại toàn bộ danh sách sau mỗi lần chèn hoặc xóa.



@Dennis vâng, tôi biết, nhờ di chuyển ngữ nghĩa. Tuy nhiên điều này không đúng với tất cả các ngôn ngữ nên ví dụ này là viết tắt.
Kate Gregory

1
@KateGregory đủ công bằng, nhưng vẫn tốt khi chỉ ra rằng cấu trúc dữ liệu "cơ bản" thường tốt hơn cấu trúc dữ liệu tuyệt vời mà chúng ta tìm hiểu ở trường (hoặc ở nơi khác). Tôi không muốn học sinh mới sử dụng LL ở mọi nơi vì nó phù hợp về mặt lý thuyết trong khi thực tế có thể là một lựa chọn kém. Sử dụng cấu trúc dữ liệu phù hợp là rất quan trọng và đôi khi mọi người thay đổi nó. Liên quan một chút là bài nói chuyện này của Jonathan Blow (người tạo ra "Braid") về cấu trúc dữ liệu .
Dennis

1
@Ray: Một danh sách được liên kết có thể vượt trội hơn cấu trúc cây nếu bạn mong đợi có thứ tự 4 yếu tố và so sánh tương đối rẻ. Tôi không biết chính xác nơi bị cắt là nơi không phải là trường hợp này. Ngoài ra, cấu trúc cây yêu cầu dữ liệu của bạn có thể được sắp xếp, trong khi cấu trúc danh sách cho phép bạn duy trì thứ tự chèn (hoặc bất kỳ thứ tự tùy ý nào).
David Stone

2
Tôi không nghĩ rằng sự tương tự này là rất chính xác. Là con người, chúng ta có thể (ít nhất là cho một danh sách ngắn như vậy) tìm thấy một yếu tố trong O (1). Nhưng nếu bạn muốn thực hiện một thao tác chèn ngẫu nhiên trong danh sách được liên kết, bạn sẽ phải vượt qua một nửa các yếu tố trung bình khiến bạn chỉ mất O (n) để tìm vị trí bạn muốn chèn. Việc chèn thực tế sau đó chỉ tốn O (1) nhưng với một mảng, chi phí của bạn cũng chỉ có thể là O O (n). Vì vậy, lý do không chỉ là do di chuyển ngữ nghĩa mà là thuật toán. Tuy nhiên, yếu tố không đổi được ẩn bởi big-O lớn hơn nhiều cho danh sách thích, do truy cập bộ nhớ không liền kề.
5gon12eder

18
  • Hashtables sử dụng chuỗi để giải quyết xung đột băm thường có một danh sách được liên kết cho mỗi nhóm cho các thành phần trong nhóm đó.
  • Bộ cấp phát bộ nhớ đơn giản sử dụng danh sách miễn phí các vùng bộ nhớ không sử dụng, về cơ bản là danh sách được liên kết với con trỏ danh sách bên trong bộ nhớ trống
  • Trong hệ thống tệp FAT , siêu dữ liệu của một tệp lớn được sắp xếp dưới dạng danh sách liên kết của các mục nhập FAT.

12

"Ngăn xếp cuộc gọi" của ngôn ngữ C được triển khai dưới dạng danh sách được liên kết trong API nhị phân x86 (và hầu hết các loại khác).

Đó là, gọi thủ tục bằng ngôn ngữ C tuân theo kỷ luật nhập trước, xuất cuối. Kết quả của việc thực hiện các lệnh gọi hàm (có thể là đệ quy) được gọi là "ngăn xếp cuộc gọi", hoặc đôi khi chỉ là "ngăn xếp".

Lệnh CALLx86 kết thúc với việc liệt kê một danh sách được liên kết bằng cách sử dụng "ngăn xếp cuộc gọi". Một CALLhướng dẫn đẩy nội dung của% EIP đăng ký, địa chỉ của các hướng dẫn sau các CALLvào bộ nhớ stack. Prolog gọi là fject đẩy nội dung của thanh ghi% EBP, địa chỉ thấp nhất của các biến cục bộ trong funcio gọi, vào bộ nhớ ngăn xếp. Sau đó, hàm prolog được gọi đặt% EBP thành cơ sở ngăn xếp của hàm hiện tại.

Điều đó có nghĩa là% EBP là một con trỏ tới một vị trí bộ nhớ chứa địa chỉ của giá trị% EBP của hàm gọi. Đó không gì khác hơn là một danh sách được liên kết, được triển khai một phần trong phần cứng thông qua CALL.

Theo như những gì nó tốt cho việc này, thì đó là cách CPU x86 thực hiện các lệnh gọi hàm, đặc biệt là các hàm gọi trong đó hàm có bản sao của các đối số và các biến cục bộ của hàm. Mỗi lệnh gọi chức năng sẽ đẩy một số thông tin vào "ngăn xếp cuộc gọi" cho phép CPU chọn nơi mà nó dừng lại trong chức năng gọi mà không bị nhiễu từ chức năng được gọi hoặc chức năng gọi.


3

Một danh sách liên kết có thể được sử dụng để thực hiện một hàng đợi tin nhắn.

Hàng đợi tin nhắn là một cấu trúc trong đó chúng tôi lưu trữ thông tin về các sự kiện để xử lý sau này. Ví dụ: khi người dùng nhấn phím hoặc di chuyển chuột, đây là một sự kiện. Một ứng dụng có thể đang bận vào thời điểm xảy ra sự kiện, do đó không thể dự kiến ​​sẽ xử lý sự kiện vào thời điểm chính xác khi nó xảy ra. Vì vậy, sự kiện được đặt trong hàng đợi tin nhắn, (thông tin về phím nào được nhấn hoặc nơi chuột di chuyển) và khi ứng dụng có thời gian rảnh, nó sẽ kiểm tra hàng đợi tin nhắn, tìm nạp các sự kiện từ nó và xử lý họ (Điều này xảy ra trong khung thời gian tính bằng mili giây, vì vậy nó không đáng chú ý.)

Từ kịch bản sử dụng mà tôi vừa mô tả, rõ ràng là chúng ta không bao giờ quan tâm đến việc có quyền truy cập ngẫu nhiên vào các sự kiện được lưu trữ trong hàng đợi tin nhắn; chúng tôi chỉ quan tâm để có thể lưu trữ thư trong đó và truy xuất chúng. Vì vậy, sẽ hợp lý khi sử dụng danh sách được liên kết, cung cấp thời gian chèn / xóa tối ưu.

. một số lượng tin nhắn hạn chế trong đó.)

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.