Tôi thường sử dụng Deque trong phần mềm sản xuất ở đâu?


21

Tôi khá quen thuộc với việc sử dụng Ngăn xếp, Hàng đợi và Cây trong các ứng dụng phần mềm nhưng tôi chưa bao giờ sử dụng Deque (Hàng đợi kết thúc kép) trước đây. Tôi thường gặp chúng ở đâu trong tự nhiên? Nó sẽ ở cùng một nơi với Hàng đợi nhưng có thêm gribbflower?



Dường như có một số nhầm lẫn trong chủ đề này. Trên internet "deque" là một hàng đợi hai đầu (wikipedia đề cập đến việc thực hiện danh sách được liên kết). Tuy nhiên, trong C ++ STL, "std :: deque" là một cấu trúc giống như mảng được triển khai dưới dạng mảng của các khối dữ liệu. Nó cung cấp quyền truy cập ngẫu nhiên, tương tự như std :: vector, nhưng khả năng thay đổi kích thước của nó gần với danh sách std :: vì khi dữ liệu được thêm vào, nó thêm các khối và không phân bổ lại và di chuyển dữ liệu hiện có.
DXM

1
@DXM: deque STL vẫn là hàng đợi hai đầu và cung cấp các hoạt động nhanh hơn ở cuối (tùy thuộc vào việc thực hiện). Rằng nó cung cấp quyền truy cập vào giữa cũng như không làm cho hoạt động chính của nó ít giống như hàng đợi.
gbjbaanb

@gbjbaanb: Tất cả những gì tôi nói là nếu bạn nhìn vào giao diện công cộng của 3 lớp: std :: vector, std :: list (hoặc std :: queue) và std :: deque, bạn sẽ thấy std :: vector và std :: deque có giao diện công cộng giống hệt nhau và khả năng giống hệt nhau (std :: deque linh hoạt hơn một chút với chi phí cho dung lượng bộ nhớ lớn hơn). std :: list và std :: queue mặt khác hoạt động giống như các bộ phận CS, danh sách liên kết và hàng đợi tương ứng. CS deque! = Std :: deque
DXM

Tôi thấy câu trả lời này thực tế hơn bởi shiv.mymail - stackoverflow.com/questions/3880254/
roottraveller

Câu trả lời:


21

Một cách mà một deque được sử dụng là "tuổi" các mặt hàng. Nó thường được sử dụng như một tính năng hoàn tác hoặc lịch sử. Một hành động mới được chèn vào deque. Các mặt hàng lâu đời nhất là ở phía trước. Một giới hạn về kích thước của deque buộc các vật phẩm ở phía trước phải được gỡ bỏ tại một số điểm khi các vật phẩm mới được chèn vào (làm lão hóa các vật phẩm cũ nhất). Sau đó, nó cung cấp một cách nhanh chóng để truy cập vào cả hai đầu của cấu trúc vì bạn biết ngay các mục cũ nhất và mới nhất để xóa mặt trước và thực hiện hành động cũ nhất trong thời gian O (1) hoặc hoàn tác trong O (1).


Tôi không nghĩ rằng deques được sử dụng / cần thiết ở đây. Một ngăn xếp đơn giản (có thể giới hạn kích thước) là đủ.
Konrad Rudolph

2
@Konrad Làm thế nào để bạn già các mục trong một ngăn xếp đơn giản? (tức là làm thế nào để bạn loại bỏ các lệnh "quá cũ"?)
Andres F.

@AresresF. Là tuổi độc lập với kích thước ngăn xếp? Nếu vậy, thì tôi chưa bao giờ nghe nói về cấu trúc dữ liệu này. Mặt khác, nó chỉ đơn giản là một ngăn xếp với kích thước cố định có thể được thực hiện theo nghĩa của một deque, hoặc đơn giản bằng cách đưa ra một cấu trúc dữ liệu đơn giản hơn được gọi là ngăn xếp có kích thước cố định.
Konrad Rudolph

Vì vậy, deques hữu ích sau tất cả;) Chưa bao giờ nghe nói về một ngăn xếp có kích thước cố định (theo nghĩa của bạn, về việc loại bỏ các mục cũ nhất). Điều này có ý nghĩa, nhưng đó không phải là "stack" thường có nghĩa là gì, và liệu nó có thực sự đơn giản hơn hay không vẫn còn được nhìn thấy :)
Andres F.

Điều này đã được đăng trong các bình luận của câu hỏi ban đầu: en.wikipedia.org/wiki/Double-ends_queue Nó chỉ là một hàng đợi kết thúc kép. Tôi đã sử dụng nó trong thực tế theo cách tôi đã nêu ở trên (đó là lý do tại sao tôi đăng nó). Trong một ngăn xếp thực sự, các hoạt động duy nhất bạn nên có là đẩy, pop, top và peek (chúng ta có thể tranh luận với người khác, nhưng nói chung là như vậy). Bạn không nên có kiến ​​thức về những gì ở dưới cùng của ngăn xếp hoặc thậm chí làm thế nào để truy cập vào dưới cùng. Trong một "ngăn xếp có kích thước cố định", bạn sẽ chỉ tạo ra tràn ngăn xếp thay vì các mục cũ khi bạn điền vào nó.
jmq

1

Câu hỏi tuyệt vời. Tôi không thể nhớ khóa học CS 102 của chúng tôi đề cập đến một ứng dụng duy nhất cho hàng đợi hai đầu.

Cho đến ngày nay, ứng dụng duy nhất tôi biết là bộ lập lịch ăn cắp công việc được đề cập trong bài viết Wikipedia .

Nó hoạt động về cơ bản như sau:

Trong một mô hình thủ tục đơn luồng thông thường, mọi lệnh gọi hàm sẽ đẩy một bản ghi kích hoạt trên một ngăn xếp cuộc gọi được gọi là . Một bản ghi kích hoạt chứa các biến cục bộ và tham số của cuộc gọi đó. Khi cuộc gọi đến phương thức được hoàn thành (Hồi trả về), bản ghi kích hoạt cuối cùng được bật từ ngăn xếp cuộc gọi.

Điều này đặc biệt quan trọng bởi vì đó là cách thức đệ quy được thực hiện: cấu trúc của đệ quy được thể hiện trong trạng thái hiện tại của ngăn xếp cuộc gọi.

Khi song song thuật toán đệ quy, chúng ta có thể khai thác thuộc tính này bằng cách thay thế ngăn xếp cuộc gọi bằng hàng đợi cuộc gọi. Mỗi luồng trong tính toán có hàng đợi cuộc gọi riêng của nó và đẩy và bật các bản ghi kích hoạt như trong một thực thi tuần tự.

Nhưng một khi một luồng đã hoàn thành công việc của nó (= hàng đợi cuộc gọi của nó trống), nó sẽ đánh cắp công việc từ một luồng khác bằng cách xóa một bản ghi kích hoạt khỏi hàng đợi cuộc gọi của luồng đó bằng cách xóa khỏi đầu cuối của nhầm lẫn.

Về cơ bản, hàng đợi cuộc gọi hoạt động như hai ngăn xếp cuộc gọi hiện phục vụ hai luồng.


Bạn có một nguồn cho điều này? Nghe có vẻ thú vị.
kyjelly90210

1
@ Richard1987 Bài viết Wikipedia trích dẫn bài báo gốc. Một số triển khai tồn tại, ví dụ như trong triển khai đánh cắp công việc mở rộng song song GNU c ++ stdlib (nhưng mã này rất kinh khủng để đọc) hoặc thực hiện song song phân chia và chinh phục chung của bạn (nhưng sau này sử dụng kiểu lập trình rất thành ngữ đặc biệt là thư viện và do đó khó đọc)
Konrad Rudolph
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.