Работа с деком, лишнее опустошение переменной

114
21 января 2022, 02:50

Написал вот этот код:

#include<iostream>
using namespace std;

struct deque
{
    int data;
    deque *next, *prev;
};
bool isEmpty(deque* deq)//проверка на существование елемента по адресу
{
    if (deq == NULL)
        return true;
    else return false;
}
deque *Push_left(deque *deq, int data)
{
    deque *dq;
    if (isEmpty(deq)) 
    {
        dq = new deque;
        dq->data = data;
        dq->next = NULL;
        dq->prev = NULL;
    }
    else
    {
        dq = new deque;
        dq->data = data;
        dq->next = deq;
        dq->prev = NULL;
        deq->prev = dq;
    }
    return dq;
}
deque *Push_right(deque *deq, int data)
{
    deque *dq;
    if (isEmpty(deq)) 
    {
        dq = new deque;
        dq->data = data;
        dq->next = NULL;
        dq->prev = NULL;
    }
    else
    {
        dq = new deque;
        dq->data = data;
        dq->next = NULL;
        dq->prev = deq;
        deq->next = dq;
    }
    return dq;
}
deque *Pop_left(deque *deq)
{
    deque*dq;
    if (isEmpty(deq))
    {
        cout << "Delete is impossible, elem. not found;" << endl;
        dq = deq;
    }
    else
    {
        while (deq->prev != NULL) deq = deq->prev;
        dq = deq->next;
        delete deq;
    }
    return dq;
}
deque *Pop_right(deque *deq)
{
    deque*dq;
    if (isEmpty(deq))
    {
        cout << "Delete is impossible, elem. not found;" << endl;
        dq = deq;
    }
    else
    {
        while (deq->next != NULL) deq = deq->next;
        dq = deq->prev;
        delete deq;
    }
    return dq;
}

deque *Print_left(deque * deq)
{
    deque *q = deq;
    deque *tmp = NULL;
    while (q != NULL)
    {
        cout << q->data << '\t' << q->next <<'\t'<<q->prev << endl;
        tmp = Push_left(tmp, q->data);  
        q = Pop_left(q);
    }
    while (tmp != NULL)
    {
        q = Push_right(q, tmp->data);
        tmp = Pop_right(tmp);
    }
    cout << endl;
    return q;
}
deque *Print_right(deque * deq)
{
    deque *q = deq;
    deque *tmp = NULL;
    while (q != NULL)
    {
        cout << q->data << '\t' << q->prev << endl;
        tmp = Push_right(tmp, q->data);
        q = Pop_right(q);
    }
    while (tmp != NULL)
    {
        q = Push_left(q, tmp->data);
        tmp = Pop_left(tmp);
    }
    cout << endl;
    return q;
}
/*deque *Servise_left(deque * deq, int x)
{
    deque *q = deq;
    deque *tmp = NULL;
    while (q != NULL)
    {
        tmp = Push_left(tmp, q->data); 
        q = Pop_left(q);
    }
    tmp = deq;
    while (tmp != NULL)
    {
        q = Push_right(q, tmp->data);
        if (q->data = x) q = Push_right(q, 0);
        tmp = Pop_right(tmp);
    }
    cout << endl;
    return q;
}
deque *Servise_right(deque * deq, int x)
{
    deque *q = deq;
    deque *tmp = NULL;
    while (q != NULL)
    {
        tmp = Push_right(tmp, q->data);  
        q = Pop_right(q);
    }
    tmp = deq;
    while (tmp != NULL)
    {
        q = Push_left(q, tmp->data);
        if(q->data = x) q = Push_left(q, 0);
        tmp = Pop_left(tmp);
    }
    cout << endl;
    return q;
}*/


int main()
{
    deque *first = NULL, *last = NULL;
    char k;
    int x;

    int f, data;
    do
    {
        system("CLS");
        cout << "1. Add element" << endl;
        cout << "2. Del element" << endl;
        cout << "3. Print" << endl;
        cout << "4. Servise" << endl;
        cout << "5. Exit" << endl;
        cout << endl;
        cout << "Your choice - ";
        cin >> f;
        switch (f)
        {
        case 1:
        {
            if (first == NULL)
            {
                cout << "Element data = ";
                cin >> data;
                first = last = Push_left(first, data);
            }
            else
            {
                cout << "Element data = ";
                cin >> data;
                cout << "Left or Right - ";
                cin >> k;
                if (k == 'L' || k == 'l')
                    first = Push_left(first, data);
                else
                    last = Push_right(last, data);
            }
            system("pause");
            break;
        }
        case 2:
        {
            if (first == NULL)
            {
                cout << "\n Queue is empty" << endl;
            }
            else {
                cout << "Left or Right - ";
                cin >> k;
                if (k == 'L' || k == 'l')
                    Pop_left(first);
                else
                    Pop_right(last);
                system("pause");
                break;
            }
        }
        case 3:
        {
            if (first == NULL)
            {
                cout << "\n Queue is empty" << endl;
            }
            else
            {
                cout << "Left or Right - ";
                cin >> k;
                if (k == 'L' || k == 'l')
                    first = Print_left(first);
                else
                    last = Print_right(last);
            }
            system("pause");
            break;
        }
        case 4:
        {
            if (first == NULL)
            {
                cout << "\n Queue is empty" << endl;
            }
            else
            {
                cout << "Seached number - ";
                cin >> x;
                cout << "Left or Right - ";
                cin >> k;
                if (k == 'L' || k == 'l')
                    first = Servise_left(first,x);
                else
                    last = Servise_right(last,x);
            }
            system("pause");
            break;
        }
        default: break;
        }
    } while (f != 4);
    system("pause");
    return 0;
}

Ошибка в неём происходит в этом месте:

deque *Print_left(deque * deq)
{
    deque *q = deq;
    deque *tmp = NULL;
    while (q != NULL)
    {
        cout << q->data << '\t' << q->next <<'\t'<<q->prev << endl;
        tmp = Push_left(tmp, q->data); 
        q = Pop_left(q);
    }
    while (tmp != NULL)
    {
        q = Push_right(q, tmp->data);
        tmp = Pop_right(tmp);
    }
    cout << endl;
    return q;
}
deque *Print_right(deque * deq)
{
    deque *q = deq;
    deque *tmp = NULL;
    while (q != NULL)
    {
        cout << q->data << '\t' << q->prev << endl;
        tmp = Push_right(tmp, q->data);  
        q = Pop_right(q);
    }
    while (tmp != NULL)
    {
        q = Push_left(q, tmp->data);
        tmp = Pop_left(tmp);
    }
    cout << endl;
    return q;
}

Ошибка заключается в том, что tmp и deq потеряли значение после первой итерации первого цикла. Переменная deq вроде как и должна был это сделать, а tmp в моей задумке должен был сохранить своё значение. В каком месте она опустошается и как это исрпавить?

Answer 1

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

struct deque
{
    int data;
    deque *next = NULL, //nullptr
          *prev = NULL;
};

Тут можно проще:

bool isEmpty(deque* deq)
{
    return deq == NULL; 
}

Если у вас есть указатель на первый элемент очереди, то просто нужно добавлять к этой очереди еще один элемент, и нет никакого смысла что либо возвращать. И смотрите как сокращается ваш код:

void Push_left(deque* deq, const int data)
{
    // эти определения не нужно повторять каждый раз
    deque* dq = new deque;
    dq->data = data;    
    if (!isEmpty(deq))
    {        
        dq->next = deq;        
        deq->prev = dq;
    }  
}

То же самое здесь:

 void Push_right(deque* deq, int data)
{
    deque* dq = new deque;
    dq->data = data;    
    if (!isEmpty(deq))
    {           
        dq->prev = deq;
        deq->next = dq;
    }    
}

Чтобы снимать с очереди, не нужно трогать указатель, указывающий на начало очереди(это логическая ошибка), поскольку вам всегда нужно будет найти начало. Для этого пройдитесь другим указателем. И, впринципе, можно тоже ничего не возвращать, но можно возвращать и bool чтобы иметь возможность написать код while(Pop_left(deq) {...}

bool Pop_left(deque* deq)
{   
    if (isEmpty(deq))
    {
        //вы выдаете ошибку, поэтому не `cout` a `cerr`
        cerr << "Delete is impossible, elem. not found;" << endl;  
        return false;
    }
    //тут просто нужно снимать первый элемент, а головой сделать второй
    else
    {
        deque* dq = deq;
        deq = deq->next; 
        delete dq;
    }
    return true;
}
bool Pop_right(deque* deq)
{    
    if (isEmpty(deq))
    {
        cout << "Delete is impossible, elem. not found;" << endl;
        return false;
    }
    else
    {
        deque* dq = deq;
        while (dq->next != NULL) dq = deq->next;
        //(dq->next == NULL) !
        delete dq;
        //
        dq = NULL;
    }
    return true;
}

Теперь об ощибках, которые вас беспокоили. Зачем вы пытаетесь что либо класть в очередь или снимать с него, когдв вам нужно просто вывести? Так просто выводите:

void Print_left(deque* deq)
{
    deque* q = deq;    
    while (q != NULL)
    {
        cout << q->data << '\t' << endl;
        q = q->next;
    }
}
void Print_right(deque* deq)
{
    deque* q = deq;  
    //идем с конца  
    while (q->next ) q = q->next;
    while (q)    
    {
        cout << q->data << '\t' ;
        q = q->prev;
    }   
}

В программе вам нужен всего один нулевой указатель(допустим deque *first = NULL), который будет указывать на начало очереди, и вам нужно просто вызвать ваши функции с этим указателем, и никаких присваиваний не нужно. Например:

case 1:        
    if (first == NULL)
    {
        cout << "Element data = ";
        cin >> data;
        Push_left(first, data);
    }

Не скажу, что это лучший вариант представления очереди, но, думаю, вам он вполне подойдет. P.S. надеюсь после моих обьяснений, функцию Servise_right, сможете переписать сами. И старайтесь писать коды так, чтобы не было повторений

READ ALSO
Использование цикла в JS

Использование цикла в JS

Понимаю, что задача весьма тривиальная

104
Диалоги в Unity 2D

Диалоги в Unity 2D

Подскажите как именно сделать диалог в UnityЧто бы например при нажатии на нпс мышкой, рядом появлялось сообщение, с возможностью нажать кнопку...

134
c# linq запрос к двумерному массиву с помощью linq

c# linq запрос к двумерному массиву с помощью linq

выполняю задание, необходимо сделать linq запрос к двумерному массиву и найти в нем заданный элемент и его индексыпростой запрос без linq findElement(value){

87
Проблема с назначением в инспекторе

Проблема с назначением в инспекторе

Суть проблемы в следующем: Есть статический родитель(префаб) и есть дети, которые динамически появляются на уровне кода, беря за основу родителяТак...

220