#include <iostream>
#include <cassert>
using namespace std;
enum tipo_numero { PARI, DISPARI };
class ListaNumeri {
friend ostream& operator<<(ostream&, const ListaNumeri&);
class Lista {
struct elem {
int num;
elem* prox;
};
elem *testa;
void copia(const Lista&);
void elimina();
public:
Lista() { testa = NULL; }
Lista(const Lista& src) { copia(src); }
Lista& operator=(const Lista&);
void inserisci(int);
int estrai(int&);
int somma() const;
int operator!() const;
~Lista() { elimina(); }
};
// Crea due sottoliste: una per i numeri pari, una per i numeri dispari.
Lista liste[2];
public:
ListaNumeri() {}
ListaNumeri(const ListaNumeri&);
ListaNumeri& operator=(const ListaNumeri&);
int inserisci(int);
int estrai(tipo_numero, int&);
int operator!() const;
int operator%(tipo_numero) const;
int operator[](tipo_numero) const;
};
//
// Classe Lista
//
void ListaNumeri::Lista::copia(const ListaNumeri::Lista& src)
{
testa = NULL;
if (src.testa != NULL) {
testa = new elem;
testa->num = src.testa->num;
elem *temp = testa, *aux = src.testa;
while (temp != NULL) {
temp->prox = new elem;
temp = temp->prox;
temp->num = aux->num;
aux = aux->prox;
}
temp->prox = NULL;
}
}
void ListaNumeri::Lista::elimina()
{
elem *temp = testa;
while (temp != NULL) {
testa = testa->prox;
delete temp;
temp = testa;
}
}
ListaNumeri::Lista& ListaNumeri::Lista::operator=(const Lista& src)
{
if (this != &src) {
elimina();
copia(src);
}
return *this;
}
// Inserzione in coda.
void ListaNumeri::Lista::inserisci(int n)
{
elem *temp = new elem;
temp->num = n;
temp->prox = NULL;
if (testa == NULL) {
testa = temp;
} else {
elem *ultimo = testa;
while (ultimo->prox != NULL)
ultimo = ultimo->prox;
ultimo->prox = temp;
}
}
// Estrazione in testa.
int ListaNumeri::Lista::estrai(int& num_estratto)
{
if (testa != NULL) {
elem *temp = testa;
testa = testa->prox;
num_estratto = temp->num;
delete temp;
return 1;
}
return 0;
}
// Restituisce il numero di elementi presenti in una lista.
int ListaNumeri::Lista::operator!() const
{
int conta = 0;
for (elem *temp = testa; temp != NULL; temp = temp->prox)
conta++;
return conta;
}
// Restituisce la somma di tutti i valori memorizzati nella lista.
int ListaNumeri::Lista::somma() const
{
int somma = 0;
elem *aux = testa;
while (aux != NULL) {
somma += aux->num;
aux = aux->prox;
}
return somma;
}
//
// Classe ListaNumeri
//
int ListaNumeri::inserisci(int n)
{
#ifndef ZERO_OP
if (n == 0) return 0;
#endif
if (n % 2)
liste[DISPARI].inserisci(n);
else
liste[PARI].inserisci(n);
return 1;
}
inline int ListaNumeri::estrai(tipo_numero tn, int& num_estratto)
{
return liste[tn].estrai(num_estratto);
}
// Restituisce il numero di elementi contenuti in una determinata sottolista.
inline int ListaNumeri::operator%(tipo_numero tn) const
{
return !(liste[tn]);
}
// Restituisce la somma dei valori degli elementi contenuti in una
// delle due sottoliste.
inline int ListaNumeri::operator[](tipo_numero tn) const
{
return liste[tn].somma();
}
// Restituisce il numero totale di elementi contenuti nella lista di numeri.
inline int ListaNumeri::operator!() const
{
return ((!liste[PARI]) + (!liste[DISPARI]));
}
ostream& operator<<(ostream& os, const ListaNumeri& src)
{
os << '<' << src % PARI << ", " << src % DISPARI << '>';
return os;
}
int main() {
ListaNumeri l1;
l1.inserisci(1);
l1.inserisci(2);
l1.inserisci(3);
l1.inserisci(4);
l1.inserisci(5);
l1.inserisci(6);
cout << l1 << endl;
assert(l1[PARI] == 12);
assert(l1[DISPARI] == 9);
ListaNumeri &l2 = l1;
assert(l1[PARI] == 12);
assert(l1[DISPARI] == 9);
assert(l2[PARI] == 12);
assert(l2[DISPARI] == 9);
assert(l1 % PARI == 3);
int inta;
l1.estrai(PARI, inta);
assert(inta == 2);
assert(l1 % PARI == 2);
// ListaNumeri::Lista(); privato
}