Пользовательский класс очереди C++

Итак, я пытаюсь создать очередь с односвязным списком. Я пытаюсь написать функцию для добавления элементов, и все отлично добавляется, но проблема в том, что это FILO вместо FIFO. Я не уверен, как обращаться с моими передними и задними указателями.

#include <iostream>
#include <string>
using namespace std;

class Queue{
    public:
        Queue();
       //~Queue();
       void add(const string & item);
       //string remove();
      // unsigned items() const;
       void show() const;
    private:
        struct Node{
            string data;
            Node *next;
        };
        Node *rear;
        Node *front;
        unsigned elements;
};

Queue::Queue():elements(0),rear(NULL),front(NULL){}

//Queue::~Queue(){

//}

void Queue::add(const string & item){
    Node *t=new Node;
    t->data=item;
    t->next=rear;
    if(front==NULL)
        front=t;
    rear=t;
    elements++;

}

void  Queue::show() const{

    Node *p=rear;
    for(; p->next!=rear; p=p->next){
        cout<<" "<<p->data;
    }
    cout<<"\n";
}
int main(){
    Queue obj;
    obj.add("I");
    obj.add("Am");
    obj.add("Super");
    obj.add("Cool");
    obj.show();
}

person Painguy    schedule 09.12.2012    source источник
comment
Пока вы не напишете функцию remove, невозможно сказать, FIFO это или LIFO, потому что ничего не выходит!   -  person Ben Voigt    schedule 09.12.2012
comment
Вы, кажется, пропустили этап, где рисуете квадратики и стрелки на бумаге.   -  person Beta    schedule 09.12.2012


Ответы (3)


в настоящее время это ни FIFO, ни FILO bu JINO (только вход, никогда выход).

то, что вы делаете, это вставить на задний конец. и ваше шоу повторяется сзади вперед, потому что это единственное связанное направление.

для эффективного FIFO вам потребуется удаление из начала вашей очереди. вы заметите, что вы можете найти передний элемент, но у вас нет простого способа найти второй элемент, необходимый для установки переднего указателя. это недостаток вашего односвязного дизайна, вам нужно выполнять итерацию от задней части к передней, чтобы найти элемент, указывающий на передний план.

  • с одним связанным списком вы можете сделать FILO (на самом деле, скорее всего, с именем LIFO или стеком)
  • для FIFO двусвязный список был бы лучшим дизайном.

если вы хотите придерживаться одного связанного списка, вы можете сделать некоторую рекурсию. вы устраняете передний указатель, потому что он бесполезен.

void  Queue::show_one(Node *p) const{
    if (p->next!=rear) {    // i kept the test for p->next!=rear
                            // either fix add or test for p->next!=NULL
        show_one(p->next);
    }
    cout<<" "<<p->data;
}

void  Queue::show() const{
    show_one(rear);
    cout<<"\n";
}

аналогично вы могли бы написать remove()

person stefan    schedule 09.12.2012
comment
Как бы я изменил направление связанного списка? Мой последний узел должен быть нулевым, а мой задний должен указывать на нулевой узел. следующий код заставляет все выводить правильно, но мне не нравится копировать каждый элемент, а затем выводить его. void Queue::show() const { string * t = NULL; t = новая строка[элементы]; Узел * p = задний; for(unsigned i = 0; i ‹ elements; i++, p = p-›next) t[i] = p-›data; for(unsigned i = elements; i--; ) cout ‹‹ ‹‹t[i]; cout ‹‹endl; удалить [] т; } - person Painguy; 09.12.2012

для достижения FILO (например, STACK?), При нажатии (добавлении) добавьте новый элемент в конец (вы будете иметь дело с задним указателем). Когда всплывает, избавьтесь от элемента, на который указывает задний указатель.

В вашем коде ваш задний указатель указывает на один элемент после конца, который равен нулю. Таким образом, push требует O(n), а pop стоит O(n). Это не эффективно. Поэтому рассмотрение двойного связанного списка может быть лучшим выбором для простой реализации.

person SDEZero    schedule 09.12.2012

Я понял, как перевернуть все это, чтобы теперь все работало правильно. Это эффективно? Для запуска main потребовалось 1,06 мс.

    #include <iostream>
    #include <string>
    using namespace std;
    bool die(const string &msg);

    class Queue{
        public:
            Queue();
           ~Queue();
           void add(const string & item);
           string remove();
           unsigned items() const;
           void show() const;
        private:
            struct Node{
                string data;
                Node *next;
            };
            Node *rear;
            Node *front;
            unsigned elements;
    };

    Queue::Queue():elements(0),rear(NULL),front(NULL){}

    Queue::~Queue(){
     unsigned el=items();
     for(unsigned i=0; i<el; i++)
      remove();
    }
    unsigned Queue::items()const{
        return elements;
    }

    string Queue::remove(){
        if(front==NULL) die("underflow");
        Node *t=front;
        string data=t->data;
        front=t->next;
        delete t;
        elements--;
        return data;
    }
    void Queue::add(const string &item){
     Node *t=new Node;
     t->data=item;
     t->next=NULL;
     if(front==NULL)
        front=t;
     else{
        Node *t2=rear;
        t2->next=t;
     }
     rear=t;
     elements++;
    }

    void  Queue::show() const{
        Node *t=front;
        for(unsigned i=0; i<items(); i++, t=t->next)
            cout<<t->data<<'\n';
    }

    bool die(const string &msg){
        cout<<"Error: "<<msg;
        exit(EXIT_FAILURE);
    }

    int main(){
        Queue obj;
        obj.show();
        obj.add("poo");
        obj.add("cra");
        obj.add("bil");
        obj.add("shi");
        obj.show();
        cout<<obj.remove()<<"\n";
        cout<<obj.remove()<<"\n";
        cout<<obj.remove()<<"\n";
        cout<<obj.remove()<<"\n";
    }
person Painguy    schedule 09.12.2012
comment
70 операторов добавления занимают около 1,40 мс - person Painguy; 09.12.2012