Cấu trúc dữ liệu “xâm nhập” nghĩa là gì?


120

Tôi đã thấy thuật ngữ xâm nhập được sử dụng để mô tả cấu trúc dữ liệu như danh sách và ngăn xếp, nhưng nó có nghĩa là gì?

Bạn có thể đưa ra một ví dụ mã về cấu trúc dữ liệu xâm nhập và cấu trúc dữ liệu này khác với cấu trúc không xâm nhập như thế nào?

Ngoài ra, tại sao làm cho nó xâm nhập (hoặc, không xâm nhập)? Những lợi ích là gì? Những bất lợi là gì?

Câu trả lời:


107

Cấu trúc dữ liệu xâm nhập là cấu trúc yêu cầu sự trợ giúp từ các phần tử mà nó dự định lưu trữ để lưu trữ chúng.

Hãy để tôi nói lại điều đó. Khi bạn đặt một cái gì đó vào cấu trúc dữ liệu đó, "cái gì đó" sẽ nhận thức được thực tế là nó nằm trong cấu trúc dữ liệu đó, theo một cách nào đó. Thêm phần tử vào cấu trúc dữ liệu sẽ thay đổi phần tử.

Ví dụ: bạn có thể xây dựng một cây nhị phân không xâm nhập, trong đó mỗi nút có một tham chiếu đến các cây con bên trái và bên phải, và một tham chiếu đến giá trị phần tử của nút đó.

Hoặc, bạn có thể xây dựng một cây xâm nhập trong đó các tham chiếu đến các cây con đó được nhúng vào chính giá trị.

Một ví dụ về cấu trúc dữ liệu xâm nhập sẽ là một danh sách có thứ tự các phần tử có thể thay đổi được. Nếu phần tử thay đổi, danh sách cần phải được sắp xếp lại, vì vậy đối tượng danh sách phải xâm phạm quyền riêng tư của các phần tử để có được sự hợp tác của chúng. I E. phần tử phải biết về danh sách mà nó có trong đó và thông báo cho nó về những thay đổi.

Hệ thống ORM thường xoay quanh cấu trúc dữ liệu xâm nhập, để giảm thiểu sự lặp lại trên danh sách lớn các đối tượng. Ví dụ: nếu bạn truy xuất danh sách tất cả nhân viên trong cơ sở dữ liệu, sau đó thay đổi tên của một trong số họ và muốn lưu lại vào cơ sở dữ liệu, danh sách nhân viên xâm nhập sẽ được thông báo khi đối tượng nhân viên thay đổi vì điều đó đối tượng biết nó nằm trong danh sách nào.

Một danh sách không xâm nhập sẽ không được thông báo, và sẽ phải tự tìm ra những gì đã thay đổi và cách nó thay đổi.


8
Tôi vẫn muốn xem một ví dụ và những ưu và nhược điểm, nhưng đây là một phần giới thiệu hay.
Rudiger

Thay vì mã bưu điện, tôi sẽ nói rằng STL là không xâm nhập, trong khi Boost.Intrusive là xâm nhập (rõ ràng).
stonemetal

1
Ưu điểm: Không cần sao chép dữ liệu của bạn vào một cấu trúc bên trong, nó có thể được sử dụng nguyên trạng. Nhược điểm: Bạn phải phá vỡ tính năng đóng gói trên dữ liệu của mình để hỗ trợ các vùng chứa mà dữ liệu của bạn sẽ được lưu trữ. Việc này có thể trở nên phức tạp nếu dữ liệu của bạn cần phải ở trong nhiều vùng chứa. Vùng chứa không xâm nhập Ưu điểm: Đóng gói tốt hơn mà không cần sửa đổi dữ liệu cho vùng chứa của bạn. Nhược điểm: Yêu cầu bản sao dữ liệu của bạn vào cấu trúc nút nội bộ.
stonemetal

3
boost.org/doc/libs/1_45_0/doc/html/intrusive.html có các ví dụ và mô tả tốt về ưu và nhược điểm.
Tony Delroy

5
Giải thích tuyệt vời với các ví dụ: boost.org/doc/libs/1_55_0/doc/html/intrusive/…
Paweł Szczur

22

Trong một vùng chứa xâm nhập, bản thân dữ liệu chịu trách nhiệm lưu trữ thông tin cần thiết cho vùng chứa. Điều đó có nghĩa là ở một bên, kiểu dữ liệu cần được chuyên biệt hóa tùy thuộc vào cách nó sẽ được lưu trữ, mặt khác nó có nghĩa là dữ liệu "biết" cách nó được lưu trữ và do đó có thể được tối ưu hóa tốt hơn một chút.

Không xâm phạm:

template<typename T>
class LinkedList
{
  struct ListItem
  {
    T Value;
    ListItem* Prev;
    ListItem* Next;
  };

  ListItem* FirstItem;
  ListItem* LastItem;

  [...]
  ListItem* append(T&& val)
  {
    LastItem = LastItem.Next = new ListItem{val, LastItem, nullptr};
  };
};

LinkedList<int> IntList;

Xâm nhập:

template<typename T>
class LinkedList
{
  T* FirstItem;
  T* LastItem;

  [...]
  T* append(T&& val)
  {
    T* newValue = new T(val);
    newValue.Next = nullptr;
    newValue.Prev = LastItem;
    LastItem.Next = newValue;
    LastItem = newValue;
  };
};

struct IntListItem
{
  int Value;
  IntListItem* Prev;
  IntListItem* Next;
};

LinkedList<IntListItem> IntList;

Cá nhân tôi thích thiết kế xâm nhập vì tính minh bạch của nó.


Dòng cuối cùng gây tò mò về cách sử dụng từ "trong suốt" vì ở trong một thùng chứa xâm nhập không trong suốt đối với đối tượng.
Xe trượt tuyết

@ArtB Rõ ràng hơn trong việc truyền tải dữ liệu được sử dụng chính xác như thế nào trong ứng dụng cuối cùng, trong trường hợp dữ liệu không xâm nhập, bạn thường phải đào sâu vào vùng chứa trong khi đối với dữ liệu xâm nhập, bạn chỉ thấy nó từ cấu trúc của dữ liệu.
API-Beast

1
Tôi cho rằng bất kỳ cách sử dụng "minh bạch" nào của trong suốt đều phải đủ tiêu chuẩn xét từ góc độ đó. Theo kinh nghiệm của tôi, "trong suốt" thường được sử dụng để chỉ ra rằng cách dữ liệu đang được xử lý là vô hình đối với miền (nghĩa là mô hình miền là thuần túy). Nếu thuật ngữ được sử dụng theo cả hai cách, tôi tự hỏi liệu có bất kỳ giá trị nào cho nó không.
Xe trượt tuyết

2
@ArtB Ôi! Có một số ý nghĩa Khoa học Máy tính đặc biệt cho sự trong suốt! Trong suốt có nghĩa là đối với tôi bạn có thể nhìn thấy nội dung bên trong, ví dụ như "không cản trở tầm nhìn", giống như thuật ngữ được sử dụng trong bất kỳ ngữ cảnh không phải cs nào.
API-Beast
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.