Tại sao std :: stack sử dụng std :: deque theo mặc định?


91

Vì các hoạt động duy nhất cần thiết để một vùng chứa được sử dụng trong một ngăn xếp là:

  • trở lại()
  • push_back ()
  • pop_back ()

Tại sao vùng chứa mặc định cho nó là deque thay vì vector?

Không phân bổ lại deque cung cấp một bộ đệm các phần tử trước front () để push_front () là một hoạt động hiệu quả? Có phải những phần tử này không bị lãng phí vì chúng sẽ không bao giờ được sử dụng trong bối cảnh ngăn xếp không?

Nếu không có chi phí cho việc sử dụng deque theo cách này thay vì một vectơ, tại sao mặc định cho priority_queue lại là một vectơ không phải là một deque? (priority_queue yêu cầu front (), push_back () và pop_back () - về cơ bản giống như đối với ngăn xếp)


Cập nhật dựa trên các câu trả lời bên dưới:

Có vẻ như cách deque thường được thực hiện là một mảng kích thước thay đổi của các mảng kích thước cố định. Điều này làm cho việc phát triển nhanh hơn so với một vectơ (yêu cầu phân bổ lại và sao chép), vì vậy đối với một cái gì đó như ngăn xếp chỉ là thêm và xóa các phần tử, deque có thể là lựa chọn tốt hơn.

priority_queue yêu cầu lập chỉ mục nhiều, vì mọi thao tác xóa và chèn đều yêu cầu bạn chạy pop_heap () hoặc push_heap (). Điều này có thể làm cho vectơ trở thành lựa chọn tốt hơn ở đó vì dù sao việc thêm một phần tử vẫn được phân bổ không đổi.


1
Lý do trong 'bản cập nhật' của bạn không hoàn toàn đúng. vector thường thêm và xóa các phần tử từ cuối nhanh hơn deque. deque nhanh hơn để tăng bộ nhớ , không phải đẩy các phần tử.
Mooing Duck

Câu trả lời:


75

Khi vùng chứa phát triển, việc phân bổ lại cho một vector yêu cầu sao chép tất cả các phần tử vào khối bộ nhớ mới. Việc phát triển một deque phân bổ một khối mới và liên kết nó với danh sách các khối - không cần bản sao.

Tất nhiên, bạn có thể chỉ định rằng một vùng chứa sao lưu khác sẽ được sử dụng nếu bạn muốn. Vì vậy, nếu bạn có một ngăn xếp mà bạn biết rằng sẽ không phát triển nhiều, hãy yêu cầu nó sử dụng một vector thay vì một deque nếu đó là sở thích của bạn.


1
Nhưng khi danh sách các con trỏ đến các khối lớn lên, danh sách này đôi khi phải được phân bổ lại giống như một vectơ phải; về mặt tiệm cận, bất kỳ mức tăng hiệu quả nào tốt nhất đều là một yếu tố không đổi. Và thao tác trình vòng lặp cần thiết để thực hiện đẩy và bật một cách chính xác phức tạp std::dequehơn nhiều so với thực tế std::vectorvà các thao tác này có thể được sử dụng thường xuyên hơn nhiều so với phân bổ lại. Tôi rất khó tin rằng điều đó std::dequesẽ đánh bại std::vectortrong thực tế.
Marc van Leeuwen

@Michael Burr: Vậy tại sao không sử dụng list, tại sao deque?
bappak

@MarcvanLeeuwen về việc bạn nói rằng bạn rất khó tin ... bạn có thể vui lòng nói rõ quan điểm được không? bạn có nghĩa là bạn đang tin rằng std::dequecó cơ hội để đánh bại std::vectortrong thực tế, hay bạn có nghĩa là bạn vẫn còn nghi ngờ điều đó? cảm ơn.
aafulei

@fleix Tôi không hiểu tại sao việc cá nhân tôi có thời gian dễ dàng hơn để tin rằng điều đó std::dequesẽ hiệu quả cũng như std::vectortrong các ứng dụng thực tế lại quan trọng như vậy . Nhưng đối với giá trị của nó, kinh nghiệm cá nhân của tôi là tôi cần cấu trúc dữ liệu ngăn xếp và hàng đợi không phải cho một nhiệm vụ quan trọng và phức tạp lớn, mà cho nhiều trường hợp nhỏ được rắc rối qua mã của tôi. Vì vậy, tôi quan tâm nhiều hơn đến hành vi nhỏ hơn là lớn; và deque tỏa sáng đặc biệt buồn tẻ ở đó. Sở thích của tôi là không sử dụng, nhưng (tự triển khai) các danh sách được liên kết đơn lẻ để thay thế. Nhưng số dặm của bạn có thể khác nhau.
Marc van Leeuwen

12

Xem Guru của Herb Sutter của Tuần 54 để biết giá trị tương đối của vector và deque ở nơi mà một trong hai sẽ làm.

Tôi tưởng tượng sự không nhất quán giữa priority_queue và queue chỉ đơn giản là những người khác nhau đã triển khai chúng.


2
priority_queue không thực sự sử dụng push / pop_front và các tham chiếu đến các phần tử bên cạnh phần tử đầu tiên bị vô hiệu bởi các hoạt động đống. Vì vậy, không có lợi ích nào của deque sẽ áp dụng, không giống như trường hợp của một hàng đợi thông thường.
Potatoswatter

9
Ngoài ra, priority_queuevẫn phải được sắp xếp, vì vậy chi phí truy cập ngẫu nhiên deque::iteratorcàng cao càng có vấn đề.
Potatoswatter

1
@Potatoswatter: priority_queuecó một "trật tự ma thuật" được duy trì, nó không được sắp xếp. Tuy nhiên, quan điểm của bạn là đúng.
Mooing Duck
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.