#include <iostream>
#include <string>
using namespace std;
class uzel
{
private:
	int dannye;
	uzel* u_sled;
	uzel* u_pred;
public:
	friend class spisok;
};
class spisok
{
private:
	uzel* u_golova;
	uzel* u_hvost;
public:
	spisok(): u_golova(NULL), u_hvost(NULL) {}
	//Создаём новый узел списка
	void push(int znach)
	{
		uzel* u_NovUzel = new uzel;
		u_NovUzel->dannye = znach;
		if (u_golova != NULL) u_golova->u_pred = u_NovUzel;
		u_NovUzel->u_pred = NULL;
		u_NovUzel->u_sled = u_golova;
		if (u_NovUzel->u_sled == NULL) u_hvost = u_NovUzel;
		u_golova = u_NovUzel;
	}
	//Вывод списка начиная с головы
	void print()
	{
		uzel* u_TekUzel = u_golova;
		while (u_TekUzel)
		{
			cout << u_TekUzel->dannye << endl;
			u_TekUzel = u_TekUzel->u_sled;
		}
	}
	//Инверсия списка
	void invert()
	{
		uzel* u_TekUzel = u_golova;
		int KolVoUzlov = NULL;
		while (u_TekUzel)
		{
			++KolVoUzlov;
			u_TekUzel = u_TekUzel->u_sled;
		}
		u_TekUzel = u_golova;
		uzel* u_PredUzel = u_hvost;
		while (KolVoUzlov > 1)
		{
			int a = NULL;
			a = u_TekUzel->dannye;
			u_TekUzel->dannye = u_PredUzel->dannye;
			u_PredUzel->dannye = a;
			u_TekUzel = u_TekUzel->u_sled;
			u_PredUzel = u_PredUzel->u_pred;
			KolVoUzlov -= 2;
		}	
	}
	//Удаление узлов с заданным содержимым
	void del(int znach)
	{
		uzel* u_TekUzel = u_golova;
		while (u_TekUzel) //Удаление серединных узлов
		{
			if (u_TekUzel->dannye == znach)
			{
				uzel* u_SledZam = u_TekUzel->u_sled;
				uzel* u_PredZam = u_TekUzel->u_pred;
				if (u_TekUzel->u_sled != NULL && u_TekUzel->u_pred != NULL)
				{
					u_TekUzel->u_pred->u_sled = u_TekUzel->u_sled;
					u_TekUzel->u_sled->u_pred = u_TekUzel->u_pred;
					delete u_TekUzel;
					u_TekUzel = u_PredZam;
				}
			}
			u_TekUzel = u_TekUzel->u_sled;
		}
		u_TekUzel = u_golova; //Возврат указателя головы списка к началу
		if (u_TekUzel->dannye == znach && u_golova != u_hvost) //Удаление первого элемента
		{
			u_TekUzel->u_sled->u_pred = NULL;
			u_golova = u_TekUzel->u_sled;
			delete u_TekUzel;
		}
		u_TekUzel = u_hvost; //Берём указатель на хвост
		if (u_TekUzel->dannye == znach && u_golova != u_hvost)
		{
			u_TekUzel->u_pred->u_sled = NULL;
			u_hvost = u_TekUzel->u_pred;
			delete u_TekUzel;
			u_TekUzel = u_hvost;
		}
		if (u_TekUzel->dannye == znach && u_golova == u_hvost)
		{
			delete u_TekUzel;
			u_golova = NULL;
			u_hvost == NULL;
		}

	}
	~spisok(){}
};
int main()
{
	spisok stek;
	string vvod = "&";
	setlocale(LC_ALL, "Russian");
	cout << "push [значение] — ввод целого числа в список. Не вводите символы, в том числе пробел!" << endl;
	cout << "del [значение] — удалить узлы списка с заданным значением" << endl;
	cout << "print — вывести список на экран" << endl;
	cout << "invert — инвертировать список" << endl << endl;
	while (vvod != "exit")
	{
		int znach;
		cin >> vvod;
		if (vvod == "push") { cin >> znach; stek.push(znach); }
		if (vvod == "print") stek.print();
		if (vvod == "invert") stek.invert();
		if (vvod == "del") { cin >> znach; stek.del(znach); }

	}
}