#include <iostream>

using namespace std;

class Lista
{
public:
	class Element
	{
	public:
		int	Vrednost() const
			{ return _Vrednost;}
			
		const Element* Sledeci() const
			{ return _Sledeci; }
	
	private:
		Element( int v  )
			: _Vrednost(v),
			  _Sledeci(0)
			{}

		Element( int v, Element* s )
			: _Vrednost(v),
			  _Sledeci(s)
			{}
	
		int			_Vrednost;
		Element*	_Sledeci;
			
		friend class Lista;		
	};
	
	Lista()
		: _Pocetak(0),
		  _Kraj(0),
		  _Velicina(0)
		{}
		
	~Lista()
		{ deinit(); }
		
	Lista( const Lista& l )
		{ init( l ); }
		
	Lista& operator = ( const Lista& l )
		{
		if( &l != this ){
			deinit(); 
			init( l ); 
			}
		return *this;
		}
		
	void DodajNaPocetak( int n )
		{ 
		_Pocetak = new Element( n, _Pocetak );
		if( !_Kraj )
			_Kraj = _Pocetak;
		_Velicina++;
		}
		
	void DodajNaKraj( int n )
		{
		Element* novi = new Element( n );
		if( !_Pocetak )
			_Kraj = _Pocetak = novi;
		else{
			_Kraj->_Sledeci = novi;
			_Kraj = novi;
			}
		_Velicina++;
		}
		
	int operator [] ( unsigned n ) const
		{
		const Element* p = _Pocetak;
		for( unsigned i=0; i<n && p; i++ )
			p = p->Sledeci();
		return p ? p->Vrednost() : 0;
		}
		
	const Element* Pocetak() const
		{ return _Pocetak; }
		
	bool Prazna() const
		{ return !_Pocetak; }
		
	unsigned Velicina() const
		{ return _Velicina; }
		
	void ObrisiPrviElement()
		{
		if( _Pocetak ){
			Element* p = _Pocetak->_Sledeci;
			delete _Pocetak;
			_Pocetak = p;
			if( !_Pocetak )
				_Kraj = 0;
			_Velicina--;
			}
		}

	void ObrisiPoslednjiElement()
		{
		if( _Velicina >=2 ){
			Element* p = _Pocetak;
			while( p->Sledeci() != _Kraj )
				p = p->_Sledeci;
			delete p->Sledeci();
			p->_Sledeci = 0;
			_Kraj = p;
			}
		else if( _Velicina == 1 ){
			delete _Pocetak;
			_Pocetak = _Kraj = 0;
			}
		_Velicina--;
		}
		
private:
/*
ovako se moze izbeci pisanje 
konstruktora kopije i operatora dodeljivanja
	Lista( const Lista& l );
	Lista& operator = ( const Lista& l );
*/

	void init( const Lista& l )
		{
		const Element* stari = l._Pocetak;
		Element** novi = &_Pocetak;
		_Kraj = 0;
		while( stari ){
			_Kraj = (*novi) = new Element( stari->Vrednost() );
			stari = stari->Sledeci();
			novi = &_Kraj->_Sledeci;
			}
		*novi = 0;
		_Velicina = l._Velicina;
		}
		
	void deinit()
		{
		for( Element* p = _Pocetak; p; ){
			Element* pl = p->_Sledeci;
			delete p;
			p = pl;
			}
		}

	Element*	_Pocetak;
	Element* 	_Kraj;
	unsigned	_Velicina;
};


class Skup
{
public:
	void Dodaj( int n )
		{
		if( !Sadrzi(n) )
			Elementi.DodajNaKraj(n);
		}
		
	bool Sadrzi( int n ) const
		{
		for( const Lista::Element* p=Elementi.Pocetak(); p; p = p->Sledeci() )
			if( p->Vrednost() == n )
				return true;
		return false;
		}
		
private:
	Lista Elementi;
};


main()
{
	Skup s;
	for( int i=0; i<20; i+=2 )
		s.Dodaj(i);
		
	for( int i=0; i<20; i++ )
		cout << "Skup " << (s.Sadrzi(i) ? "" : "ne ") << "sadrzi element " << i << endl;
		
	Skup s2(s);
	s.Dodaj(123);
	cout << "Skup s " << (s.Sadrzi(123) ? "" : "ne ") << "sadrzi element " << 123 << endl;
	cout << "Skup s2 " << (s2.Sadrzi(123) ? "" : "ne ") << "sadrzi element " << 123 << endl;
		
	return 0;
}




