Có std :: deque thực sự có chèn thời gian liên tục ở đầu không?


8

Tiêu chuẩn nói:

Một deque là một thùng chứa trình tự hỗ trợ các vòng lặp truy cập ngẫu nhiên (27.2.7). Ngoài ra, nó hỗ trợ các hoạt động chèn và xóa thời gian liên tục ở đầu hoặc cuối; chèn và xóa ở giữa mất thời gian tuyến tính.

Tuy nhiên, nó cũng nói trong Điều khoản tương tự:

Tất cả các yêu cầu phức tạp trong Điều khoản này chỉ được nêu dưới dạng số lượng hoạt động trên các đối tượng được chứa. [Ví dụ: Hàm tạo sao chép của loại vector<vector<int>>có độ phức tạp tuyến tính, mặc dù độ phức tạp của việc sao chép từng loại chứa vector<int>chính nó là tuyến tính. - ví dụ cuối]

Điều này không có nghĩa là việc chèn vào lúc bắt đầu, deque<int>được cho phép mất thời gian tuyến tính miễn là nó không thực hiện nhiều hơn một số lượng hoạt động không đổi trên ints đã có trong deque và intđối tượng mới được chèn ?

Ví dụ: giả sử rằng chúng ta thực hiện một deque bằng cách sử dụng "vectơ kích thước-K". Dường như cứ sau mỗi lần K chèn vào đầu, một vectơ kích thước K mới phải được thêm vào lúc đầu, vì vậy tất cả các vectơ kích thước K khác phải được di chuyển. Điều này có nghĩa là độ phức tạp thời gian của phần chèn lúc đầu được khấu hao O (N / K) trong đó N là tổng số phần tử, nhưng K là hằng số, vì vậy đây chỉ là O (N). Nhưng dường như điều này được Tiêu chuẩn cho phép, bởi vì việc di chuyển một vectơ kích thước K không di chuyển bất kỳ phần tử nào của nó và "các yêu cầu phức tạp" chỉ "được nêu trong số lượng hoạt động" trên các intđối tượng được chứa .

Tiêu chuẩn có thực sự cho phép điều này? Hoặc chúng ta nên giải thích nó là có một yêu cầu chặt chẽ hơn, tức là số lượng hoạt động không đổi trên các đối tượng được chứa cộng với thời gian bổ sung không đổi?


2
Giải thích của bạn nghe có vẻ hợp lý. Để thêm dầu vào lửa, [deque.modifier] có một phần chèn ở giữa deque làm mất hiệu lực tất cả các trình vòng lặp và tham chiếu đến các phần tử của deque. Việc chèn vào một trong hai đầu của deque làm mất hiệu lực tất cả các trình vòng lặp cho deque, nhưng không có ảnh hưởng đến tính hợp lệ của các tham chiếu đến các phần tử của deque. Giống như ví dụ vector của bạn hoạt động kể từ khi di chuyển làm mất hiệu lực các trình vòng lặp nhưng không phải là các tham chiếu.
NathanOliver

Tôi nghĩ rằng ví dụ này hơi khó hiểu vì nó sử dụng "tuyến tính" một lần cho tuyến tính đối với số phần tử của vector<vector<int>>nhưng sau đó tuyến tính đối với các phần tử bên trong vector<int>. Nếu bạn chỉ xem xét số lượng phần tử của vectơ ngoài hte, tôi sẽ coi việc sao chép vectơ bên trong là không đổi, mặc dù tôi có thể sai, nó đã trễ ở đây
idclev 463035818

Câu trả lời:


2

Ví dụ: giả sử rằng chúng ta thực hiện một deque bằng cách sử dụng "vectơ kích thước-K".

Đó sẽ không phải là một thực hiện hợp lệ. Chèn ở phía trước của một không hợp vectorlệ tất cả các con trỏ / tham chiếu trong container. dequeđược yêu cầu để không làm mất hiệu lực bất kỳ con trỏ / tham chiếu nào khi chèn phía trước.

Nhưng bây giờ hãy bỏ qua điều đó.

Nhưng dường như điều này được Tiêu chuẩn cho phép, bởi vì việc di chuyển một vectơ cỡ K không di chuyển bất kỳ phần tử nào của nó và "các yêu cầu phức tạp" chỉ "được nêu trong số lượng hoạt động" trên các đối tượng int có trong .

Vâng, điều đó sẽ được cho phép. Thật vậy, việc triển khai thực tế dequekhông giống nhau lắm (mặc dù họ không sử dụng std::vectorchính nó vì những lý do rõ ràng). Phác thảo rộng của dequeviệc triển khai là một loạt các con trỏ tới các khối (có không gian để tăng trưởng ở cả phía trước và phía sau), với mỗi khối chứa tối đa các mục X cũng như một con trỏ tới các khối tiếp theo / trước đó (để tạo một khối phần tử lặp nhanh).

Nếu bạn chèn đủ các phần tử ở phía trước hoặc phía sau, thì mảng con trỏ khối phải phát triển. Điều đó sẽ yêu cầu một hoạt động có thời gian tuyến tính liên quan đến số lượng vật phẩm trong deque, nhưng thực tế không hoạt động trên chính các vật phẩm, vì vậy nó không được tính. Đặc tả không có gì để nói về sự phức tạp của hoạt động đó.

Nếu không có điều khoản này, tôi không chắc liệu tập hợp tính năng duy nhất deque(chèn trước / sau nhanh truy cập ngẫu nhiên) có thể thực hiện được hay không.


"Việc chèn vào một trong hai đầu của deque làm mất hiệu lực tất cả các trình vòng lặp cho deque, nhưng không có tác dụng đối với tính hợp lệ của các tham chiếu đến các phần tử của deque."
Brian

Rõ ràng việc chèn ở phía trước hoặc phía sau đôi khi sẽ mất thời gian tuyến tính. Nhưng nếu mảng con trỏ thực sự có không gian ở phía trước, thì thời gian nên được khấu hao không đổi. Nếu nó không có không gian ở phía trước, thì thời gian không được khấu hao không đổi. Tôi đang hỏi về việc sau này được cho phép.
Brian

@Brian: " Nhưng nếu mảng con trỏ thực sự có không gian ở phía trước, thì thời gian nên được khấu hao không đổi " Đó không phải là " hằng số khấu hao " nghĩa là gì. Điều đó có nghĩa là khoảng cách giữa N khi nó không phải là hằng số luôn tăng. Nếu vectorviệc thực hiện thay đổi kích thước tự động chỉ thêm một số lượng bổ sung không đổi, thì việc chèn sẽ không phải là "hằng số khấu hao". Vì vậy, nó không chỉ đơn thuần là có không gian; bạn phải chèn thêm không gian mỗi lần.
Nicol Bolas

@Brian: Và vâng, không có gì về các dequeyêu cầu mà cả hai chèn là "hằng số khấu hao" đối với số lượng vật phẩm trong container; nó chỉ là hằng số đối với số lượng thao tác trên các vật phẩm trong container.
Nicol Bolas

"Hằng số khấu hao" có nghĩa là có một số hằng số c sao cho nếu bạn thực hiện N thao tác, thì tổng thời gian thực hiện tối đa là cN. Giống như tôi đã nói, nếu deque không giữ khoảng trống ở phía trước, thì rõ ràng các phần chèn ở phía trước không thể được khấu hao không đổi. Nếu deque không giữ đủ không gian ở phía trước (nhiều hơn một lượng không đổi, như bạn nói) thì có thể nó được khấu hao không đổi. Tuy nhiên, trong cả hai trường hợp, nó sẽ không đổi về các thao tác trên các phần tử.
Brian

1

Tôi nghĩ rằng bạn đang đạt được một chút, trong cách bạn diễn giải ý nghĩa của các miền phức tạp. Bạn đang cố gắng phân biệt "thời gian tuyến tính" và "độ phức tạp tuyến tính" mà tôi không tin có ý nghĩa nhiều.

Tiêu chuẩn rõ ràng rằng việc chèn ở phía trước là thời gian không đổi và tôi nghĩ tất cả chúng ta đều đồng ý về điều đó. Đoạn văn sau chỉ cho chúng ta biết rằng những gì mà số lượng hoạt động "không đổi" đó liên quan đến bên dưới chỉ đơn giản là không được chỉ định hoặc ràng buộc bởi tiêu chuẩn.

Và điều này không phải là bất thường. Bất kỳ thuật toán hoạt động trên một số cơ sở trừu tượng. Ngay cả khi chúng tôi viết một thuật toán theo các hướng dẫn máy riêng lẻ và chúng tôi đã nói rằng chỉ có các lệnh N máy được tạo bởi thuật toán của chúng tôi, chúng tôi sẽ không điều tra mức độ phức tạp của từng độ phức tạp trong từng bộ xử lý và thêm vào kết quả của chúng tôi Chúng tôi sẽ không nói rằng một số hoạt động cuối cùng làm nhiều hơn ở cấp độ phân tử lượng tử và do đó thuật toán O (n) của chúng tôi thực sự là O (N × M 3 ) hoặc somesuch. Chúng tôi đã chọn không xem xét mức độ trừu tượng đó. Và, trừ khi độ phức tạp nói phụ thuộc vào đầu vào của thuật toán, điều đó hoàn toàn tốt.

Trong trường hợp của bạn, kích thước của các vectơ bên trong được di chuyển / sao chép không thực sự phù hợp, bởi vì chúng không thay đổi khi deque phát triển. Số lượng các vectơ bên trong không, nhưng kích thước của mỗi một là một thuộc tính độc lập. Do đó, nó không liên quan khi mô tả sự phức tạp của việc chèn một phần tử mới vào vector bên ngoài.

Thời gian thực hiện thực tế (có thể được mô tả bằng một số thuật ngữ nếu bạn chọn) có khác nhau tùy thuộc vào nội dung của các vectơ bên trong được sao chép không? Phải, tất nhiên. Nhưng điều đó không liên quan gì đến việc nhiệm vụ mở rộng vectơ bên ngoài tăng lên trong khối lượng công việc như chính vectơ bên ngoài phát triển.

Vì vậy, ở đây, tiêu chuẩn nói rằng nó sẽ không sao chép N hoặc N 2 hoặc thậm chí đăng nhập các vectơ bên trong N khi bạn đặt một vectơ khác ở phía trước; điều đó nói lên rằng số lượng các hoạt động này sẽ không thay đổi về quy mô khi deque của bạn tăng lên. Người ta cũng nói rằng, với mục đích của quy tắc đó, nó không quan tâm đến việc sao chép / di chuyển các vectơ bên trong thực sự liên quan hoặc chúng lớn như thế nào.

Phân tích phức tạp không phải là về hiệu suất. Phân tích phức tạp là về cách hiệu suất quy mô.


Bootnote: nếu bạn thực sự muốn, bạn có thể mô tả độ phức tạp của hoạt động không phải là O (1) , mà là O (A + B + C + D + E + F + ...) trong đó các biến bên trong liên quan đến kích thước của ảnh hưởng đến các yếu tố hiện có hoặc một số chức năng khác của chúng ... nhưng điều đó sẽ không hữu ích, (b) bên cạnh điểm của quy tắc được xác định trong đoạn đó và (c) lãng phí thời gian, vì tiêu chuẩn đã thông báo khá nhiều cho chúng tôi rằng sẽ không có tác động đến những yếu tố hiện có.
Tiểu hành tinh có cánh
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.