2009-08-11 40 views
55

Tôi cần phải lặp qua std::queue. www.cplusplus.com nói:std :: iteration hàng đợi

Theo mặc định, nếu không có lớp chứa nào được chỉ định cho một lớp hàng đợi cụ thể, sử dụng mẫu lớp chứa tiêu chuẩn.

Vì vậy, bằng cách nào đó tôi có thể truy cập vào deque cơ bản của hàng đợi và lặp lại qua nó?

Trả lời

56

Nếu bạn cần lặp lại trên queue thì bạn cần một thứ gì đó không phải hàng đợi. Điểm của bộ điều hợp container chuẩn là cung cấp một giao diện tối thiểu. Nếu bạn cần phải làm lặp lại là tốt, tại sao không chỉ sử dụng một deque (hoặc danh sách) để thay thế?

+73

Trong khi tôi biết những gì bạn đang nói, tôi đã luôn luôn không thích cụm từ này "một cái gì đó nhiều hơn một hàng đợi". Một hàng đợi với liệt kê vẫn là một hàng đợi ... Ngoài ra, hãy quan sát cách 'deque' chỉ xảy ra để hỗ trợ điều tra, hoàn toàn tùy ý. Bạn cũng có thể tranh luận rằng 'deque' nên thuần túy như' hàng đợi' và không hỗ trợ lặp lại, và nếu bạn muốn lặp lại nó thì bạn muốn cái gì đó "nhiều hơn"; ví dụ. một 'deque_enumerable'. Đó là một con dốc trơn mặc dù, và cảm giác cá nhân của tôi là 'hàng đợi' nên có hỗ trợ liệt kê ở nơi đầu tiên. –

+4

@romkyns: Sẽ tốt hơn nếu tôi nhắc lại nó: "Bạn cần một cái gì đó có giao diện phong phú hơn giao diện' xếp hàng' để bạn nên chọn một đối tượng có giao diện phù hợp ". Giống như nó hay không, lặp lại không phải là một phần của giao diện 'hàng đợi' vì vậy nếu bạn muốn lặp lại, bạn cần phải chọn một cái gì đó khác. –

+1

Bởi vì trường hợp sử dụng của tôi yêu cầu một hàng đợi, nhưng tôi cần phải đổ nó ra cho mục đích gỡ lỗi và ghi nhật ký. Nó thường không mang tính xây dựng để cho rằng áp phích không biết họ đang làm gì. – EML

-2

Nói tóm lại: Số

Có một hack, sử dụng vector như container underlaid, vì vậy queue::front sẽ trở lại tham chiếu hợp lệ, chuyển nó sang con trỏ một lặp cho đến khi < = queue::back

+0

Nhưng bạn cũng có thể sử dụng một véc tơ trực tiếp ... –

+1

Bạn cũng có thể sử dụng trực tiếp deque - chứa tất cả các phương thức cần thiết làm hàng đợi nhưng cũng hỗ trợ lặp lại – Dewfy

0

Nếu bạn cần phải lặp hàng đợi ... hàng đợi không phải là vùng chứa bạn cần.
Tại sao bạn chọn hàng đợi?
Tại sao bạn không sử dụng vùng chứa mà bạn có thể lặp lại?


1.If bạn chọn một hàng đợi sau đó bạn nói rằng bạn muốn quấn một container vào một giao diện 'đợi': - trước - lại - đẩy - pop - ...

nếu bạn cũng muốn lặp lại, hàng đợi có giao diện không chính xác. Một hàng đợi là một bộ chuyển đổi cung cấp một tập hợp con bị hạn chế trong những thùng chứa gốc

2.The nghĩa của một hàng đợi là một FIFO và theo định nghĩa một FIFO là không iterable

+24

Tôi không các OP, nhưng đây là câu trả lời của tôi, trong trường hợp bất cứ ai là tò mò: 1) Tôi đã chọn một hàng đợi bởi vì tôi muốn có một hàng đợi. Tôi muốn enqueue ở một đầu và dequeue ở khác. Đây có phải là lựa chọn không hợp lý không? 2) Không rõ ràng rằng một "hàng đợi" không phải là số đếm, cũng không phải là cấu trúc để sử dụng thay thế. Câu trả lời của bạn sẽ hữu ích hơn nếu bạn giải thích sử dụng vùng chứa nào để thay thế. –

28

khi tôi đồng ý với những người khác rằng việc sử dụng trực tiếp của một iterable container là một giải pháp ưa thích, tôi muốn chỉ ra rằng tiêu chuẩn C++ đảm bảo đủ hỗ trợ cho một giải pháp do-it-yourself trong trường hợp bạn muốn nó vì bất kỳ lý do gì.

Cụ thể, bạn có thể kế thừa từ std::queue và sử dụng thành viên được bảo vệ Container c; để truy cập bắt đầu() và cuối() của vùng chứa cơ bản (miễn là phương pháp đó tồn tại ở đó). Dưới đây là một ví dụ mà làm việc trong VS 2010 và tested with ideone:

#include <queue> 
#include <deque> 
#include <iostream> 

template<typename T, typename Container=std::deque<T> > 
class iterable_queue : public std::queue<T,Container> 
{ 
public: 
    typedef typename Container::iterator iterator; 
    typedef typename Container::const_iterator const_iterator; 

    iterator begin() { return this->c.begin(); } 
    iterator end() { return this->c.end(); } 
    const_iterator begin() const { return this->c.begin(); } 
    const_iterator end() const { return this->c.end(); } 
}; 

int main() { 
    iterable_queue<int> int_queue; 
    for(int i=0; i<10; ++i) 
     int_queue.push(i); 
    for(auto it=int_queue.begin(); it!=int_queue.end();++it) 
     std::cout << *it << "\n"; 
    return 0; 
} 
+1

Vì vậy, chúng ta có thể làm tương tự với 'priority_queue', phải không? – Deqing

+3

@Deqing: đúng; nhưng việc lặp qua vùng chứa bên dưới sẽ không nằm trong thứ tự ưu tiên. –

+0

Tại sao xác định lại một lớp mới và không sử dụng 'deque' trực tiếp ?! –

-2

std::queue là một bộ chuyển đổi container, và bạn có thể chỉ định container được sử dụng (mặc định nó sử dụng một deque). Nếu bạn cần chức năng vượt quá điều đó trong bộ điều hợp thì chỉ cần sử dụng trực tiếp deque hoặc một vùng chứa khác.

+3

Trong khi câu trả lời của bạn là chính xác, hoàn toàn không cần, vì câu hỏi 2 năm tuổi này đã có hai câu trả lời cho biết chính xác như nhau (với một trong số đó là câu trả lời được chấp nhận). –

0

Tại sao không chỉ tạo bản sao của hàng đợi mà bạn muốn lặp lại và xóa từng mục một, in chúng khi bạn đi? Nếu bạn muốn làm nhiều hơn với các phần tử khi bạn lặp lại, thì hàng đợi là cấu trúc dữ liệu sai.

+2

Er, không. Sao chép sau đó phá hủy một hàng đợi là cách chi phí cao hơn bạn cần. Đây là lý do tại sao vòng lặp được phát minh. – Mac

+1

Đơn giản: Tạo hàng đợi trống. Bật từng mục ra khỏi hàng đợi chính của bạn cho đến khi trống, xử lý nó như mong muốn và đẩy nó vào hàng đợi trống. Khi hoàn tất, thiết lập hàng đợi chính bằng hàng đợi rỗng. Làm việc cho priority_queue là tốt. Lưu ý: Không an toàn cho chủ đề nếu một số chủ đề khác đang cố gắng truy cập vào hàng đợi cùng một lúc. Ngoài ra, nếu ban đầu của bạn đã được cấp phát heap (được tạo thông qua 'malloc' /' new'), hãy chắc chắn 'free' /' delete' nó hoặc bạn sẽ bị rò rỉ bộ nhớ. –

0

Xem hình ảnh trên https://stackoverflow.com/a/471461/383779 và sau đó quyết định xem thùng chứa nào phù hợp nhất với nhu cầu của bạn.

+2

Điều đó không thực sự hữu ích. Biểu đồ cho tôi biết tôi cần một - drumroll xin vui lòng - * hàng đợi *. –

3

bạn có thể lưu hàng đợi ban đầu vào hàng đợi tạm thời.Sau đó, bạn chỉ cần làm pop bình thường trên hàng đợi tạm thời phải đi qua một bản gốc, ví dụ:

queue tmp_q = original_q; //copy the original queue to the temporary queue 

while (!tmp_q.empty()) 
{ 
    q_element = tmp_q.top(); 
    std::cout << q_element <<"\n"; 
    tmp_q.pop(); 
} 

Cuối cùng, các tmp_q sẽ trống nhưng hàng đợi ban đầu là không bị ảnh hưởng.

+0

'std :: queue' dường như không có phương thức' .top() ' –

Các vấn đề liên quan