【问题标题】:Traversing queue in C++C ++中的遍历队列
【发布时间】:2013-03-27 23:58:02
【问题描述】:

我有一个需要打印的 C++ 队列。打印第一个节点然后删除它很容易,然后再次打印第一个节点,这将是第二个节点。但这会删除整个列表只是为了打印一次......作为一种解决方法,我创建了一个临时队列对象,我将它传递给我的打印方法并做与第一个对象相同的事情,这会很棒,除非它正在使用使队列动态的指针,因此从从第一个复制的任何对象中删除它们仍然是删除相同的数据。我还不擅长指针,但我确信必须有一种简单的方法来做到这一点,有什么建议吗?

代码如下:

queue2 = queue1; // Temporary queue is assigned values of main queue
queue2.printQueue(); // Temporary queue is passed to print method

这是我的打印方法:

int numberPrinted = 0;
while (!isEmptyQueue())
{
 cout << numberPrinted + 1 << ": " << front() << "\n";
 deleteQueue();    
 numberPrinted++;
 }

队列类文件:

#ifndef H_linkedQueue
#define H_linkedQueue

#include <iostream>
#include <cassert>
#include "queueADT.h"

using namespace std;

//Definition of the node
template <class Type>
struct nodeType
{
    Type info;
    nodeType<Type> *link;
};


template <class Type>
class linkedQueueType: public queueADT<Type>
{
public:
    bool operator==
                    (const linkedQueueType<Type>& otherQueue); 

    bool isEmptyQueue() const;
      //Function to determine whether the queue is empty. 
      //Postcondition: Returns true if the queue is empty,
      //               otherwise returns false.

    bool isFullQueue() const;
      //Function to determine whether the queue is full. 
      //Postcondition: Returns true if the queue is full,
      //               otherwise returns false.

    void initializeQueue();
      //Function to initialize the queue to an empty state.
      //Postcondition: queueFront = NULL; queueRear = NULL

    Type front() const;
      //Function to return the first element of the queue.
      //Precondition: The queue exists and is not empty.
      //Postcondition: If the queue is empty, the program 
      //               terminates; otherwise, the first 
      //               element of the queue is returned. 

    Type back() const;
      //Function to return the last element of the queue.
      //Precondition: The queue exists and is not empty.
      //Postcondition: If the queue is empty, the program 
      //               terminates; otherwise, the last 
      //               element of the queue is returned.

    void addQueue(const Type& queueElement);
      //Function to add queueElement to the queue.
      //Precondition: The queue exists and is not full.
      //Postcondition: The queue is changed and queueElement
      //               is added to the queue.

    void deleteQueue();
      //Function  to remove the first element of the queue.
      //Precondition: The queue exists and is not empty.
      //Postcondition: The queue is changed and the first 
      //               element is removed from the queue.
    int numberOfNodes();
    // Return number of nodes in the queue.
    void printQueue();
    //Print the queue.

    linkedQueueType(); 
      //Default constructor

    linkedQueueType(const linkedQueueType<Type>& otherQueue); 
      //Copy constructor

    ~linkedQueueType(); 
      //Destructor

private:
    nodeType<Type> *queueFront; //pointer to the front of 
                                //the queue
    nodeType<Type> *queueRear;  //pointer to the rear of 
                                //the queue
    int count;
};

    //Default constructor
template<class Type>
linkedQueueType<Type>::linkedQueueType() 
{
    queueFront = NULL; //set front to null
    queueRear = NULL;  //set rear to null
} //end default constructor

template<class Type>
bool linkedQueueType<Type>::isEmptyQueue() const
{
    return(queueFront == NULL);
} //end 

template<class Type>
bool linkedQueueType<Type>::isFullQueue() const
{
    return false;
} //end isFullQueue

template <class Type>
void linkedQueueType<Type>::initializeQueue()
{
    nodeType<Type> *temp;

    while (queueFront!= NULL)  //while there are elements left
                               //in the queue
    {
        temp = queueFront;  //set temp to point to the 
                            //current node
        queueFront = queueFront->link;  //advance first to  
                                        //the next node
        delete temp;    //deallocate memory occupied by temp
    }

    queueRear = NULL;  //set rear to NULL
} //end initializeQueue


template <class Type>
void linkedQueueType<Type>::addQueue(const Type& newElement)
{
    nodeType<Type> *newNode;

    newNode = new nodeType<Type>;   //create the node

    newNode->info = newElement; //store the info
    newNode->link = NULL;  //initialize the link field to NULL

    if (queueFront == NULL) //if initially the queue is empty
    {
        queueFront = newNode;
        queueRear = newNode;
    }
    else        //add newNode at the end
    {
        queueRear->link = newNode;
        queueRear = queueRear->link;
    }
    count++;
}//end addQueue

template <class Type>
Type linkedQueueType<Type>::front() const
{
    assert(queueFront != NULL);
    return queueFront->info; 
} //end front

template <class Type>
Type linkedQueueType<Type>::back() const
{
    assert(queueRear!= NULL);
    return queueRear->info;
} //end back

template <class Type>
void linkedQueueType<Type>::deleteQueue()
{
    nodeType<Type> *temp;

    if (!isEmptyQueue())
    {
        temp = queueFront;  //make temp point to the 
                            //first node
        queueFront = queueFront->link; //advance queueFront 

        delete temp;    //delete the first node

        if (queueFront == NULL) //if after deletion the 
                                //queue is empty
            queueRear = NULL;   //set queueRear to NULL
        count--;
    }
    else
        cout << "Cannot remove from an empty queue" << endl;
}//end deleteQueue


    //Destructor
template <class Type>
linkedQueueType<Type>::~linkedQueueType() 
{
    //Write the definition of the destructor
} //end destructor

template <class Type> 
bool linkedQueueType<Type>::operator==
                    (const linkedQueueType<Type>& otherQueue)
{
    bool same = false;

    if (count == otherQueue.count)
        same = true;

    return same;

} //end assignment operator

    //copy constructor
template <class Type>
linkedQueueType<Type>::linkedQueueType
                 (const linkedQueueType<Type>& otherQueue) 
{
    //Write the definition of the copy constructor
}//end copy constructor
template <class Type> 
int linkedQueueType<Type>::numberOfNodes()
{
    return count;

} 

template <class Type> 
void linkedQueueType<Type>::printQueue()
{
    int numberPrinted = 0;
while (!isEmptyQueue())
{
 cout << numberPrinted + 1 << ": " << front() << "\n";
 deleteQueue();    
 numberPrinted++;
 }
}
#endif

【问题讨论】:

  • 您使用的队列类是某种标准队列类还是您自己编写的?无论哪种方式,它是否提供任何类型的迭代器?
  • 这是一个标准的队列类,不过我已经对其进行了一些修改。我不相信。我将发布课程文件...

标签: c++ queue traversal


【解决方案1】:

您的队列的printQueue 方法已经可以访问队列的私有内部。不要使用公共接口来打印队列,只需使用内部queueFront 指针并遍历列表,打印每个元素。

类似的东西(这个作业之后的伪代码):

for(node* n = queueFront; n; n = n->next)
{
    // Print data from node n.
}

【讨论】:

  • 我不确定我是否完全理解...你能举个例子吗?
  • 非常感谢您的编辑,我想我可以解决这个问题。
  • 那应该是“……到受保护的队列内部……”
【解决方案2】:

如果您使用自己编写的队列类,请向其添加迭代器。如果您正在使用已经具有迭代器的队列类,请遍历它以打印它。如果您使用的队列类没有迭代器,请切换到另一个有迭代器的队列类。

如果您使用的是std::queue,请切换到std::liststd::deque

cplusplus.com 上的 an example 显示了如何遍历双端队列:

#include <iostream>
#include <deque>

int main ()
{
  std::deque<int> mydeque;

  for (int i=1; i<=5; i++) mydeque.push_back(i);

  std::cout << "mydeque contains:";

  std::deque<int>::iterator it = mydeque.begin();

  while (it != mydeque.end())
    std::cout << ' ' << *it++;

  std::cout << '\n';
  return 0;
}

或者:

for (std::deque<int>::iterator it = mydeque.begin(); it != mydeque.end(); ++it)
  // print *it here

【讨论】:

  • 我不相信我正在使用的课程有迭代器,我必须坚持使用这个课程代码来完成作业(仍在学校),我怎么能在我的课程中做到这一点正在使用?
  • 感谢编辑显示示例,我将不得不查看它,看看是否可以做到...
  • @Blake:你不能遍历std::queue。如果你必须使用std::queue,你不能遍历它。
【解决方案3】:

如果队列是您自己的代码,并且假设您可以在内部迭代其元素,您可以给它一个friend ostream&amp; operator&lt;&lt;(ostream&amp;, const your_queue_type&amp;) 并将元素写入输出流。

class Queue
{
 public:
  // methods
 friend ostream& operator<<(ostream& o, const Queue& q)
 {
   // iterate over nodes and stream them to o: o << some_node and so on
 }
};

然后

Queue q = ....;
std::cout << q << std::endl; // calls your ostream& operator<<

【讨论】:

    【解决方案4】:

    我不知道这有多大用处,但是由于您使用 nodeType&lt;Type&gt;.link 将每个节点附加到下一个节点,那么您可能想要执行以下操作:

    int numberPrinted = 1;
    nodeType<Type> *temp;
    if (queueFront != NULL) 
    {
        temp = queueFront;
        do
        {
            cout << numberPrinted << ": " << temp->info << "\n";
            numberPrinted++;
        }while(temp->link!=NULL);
    }
    

    这样你就可以在不改变队列的情况下跟随指针。

    【讨论】:

      【解决方案5】:

      这是一个简单的方法,只需一个指针和一个 while 循环

      while(pointer != NULL) pointer.info pointer = pointer.next

      【讨论】:

      • 欢迎来到 Stack Overflow!您能否解释一下:(a)您提出的解决方案如何解决所提出的问题? (b) pointer.info pointer = pointer.next这个语句是什么奇怪的C++语法?
      猜你喜欢
      • 1970-01-01
      • 2021-01-28
      • 2015-08-12
      • 1970-01-01
      • 2020-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-29
      相关资源
      最近更新 更多