Commit 0d231da9 authored by Enzo Bonggio's avatar Enzo Bonggio
Browse files

string_map + esqueleto

parent e6aec85b
......@@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -ggdb3 -g")
# Leemos todos los archivos fuentes en ./src
file(GLOB SOURCE_FILES src/*.cpp src/*.h)
file(GLOB SOURCE_FILES src/*.cpp src/*.h src/*.hpp)
# Leemos todos los archivos de test en ./tests
file(GLOB TEST_SOURCES tests/*.cpp)
......
......@@ -3,140 +3,175 @@
#include <tuple>
#include <algorithm>
BaseDeDatos::BaseDeDatos(){};
BaseDeDatos::BaseDeDatos() {};
void BaseDeDatos::crearTabla(const string &nombre,
void BaseDeDatos::crearTabla(const string &nombre,
const linear_set<string> &claves,
const vector<string> &campos,
const vector<Dato> &tipos) {
_nombres_tablas.fast_insert(nombre);
_tablas.fast_insert(make_pair(nombre, Tabla(claves, campos, tipos)));
_nombres_tablas.fast_insert(nombre);
_tablas.fast_insert(make_pair(nombre, Tabla(claves, campos, tipos)));
}
void BaseDeDatos::agregarRegistro(const Registro &r, const string &nombre) {
Tabla &t = _tablas.at(nombre);
t.agregarRegistro(r);
Tabla &t = _tablas.at(nombre);
t.agregarRegistro(r);
}
const linear_set<string> &BaseDeDatos::tablas() const { return _nombres_tablas; }
const Tabla &BaseDeDatos::dameTabla(const string &nombre) const {
return _tablas.at(nombre);
return _tablas.at(nombre);
}
int BaseDeDatos::uso_criterio(const BaseDeDatos::Criterio &criterio) const {
if (_uso_criterios.count(criterio)) {
return _uso_criterios.at(criterio);
} else {
return 0;
}
if (_uso_criterios.count(criterio)) {
return _uso_criterios.at(criterio);
} else {
return 0;
}
}
bool BaseDeDatos::registroValido(const Registro &r,
const string &nombre) const {
const Tabla &t = _tablas.at(nombre);
const Tabla &t = _tablas.at(nombre);
return (t.campos() == r.campos() and _mismos_tipos(r, t) and
_no_repite(r, t));
return (t.campos() == r.campos() and _mismos_tipos(r, t) and
_no_repite(r, t));
}
bool BaseDeDatos::_mismos_tipos(const Registro &r, const Tabla &t) const {
for (auto c : t.campos()) {
if (r.dato(c).esNat() != t.tipoCampo(c).esNat()) {
return false;
for (auto c : t.campos()) {
if (r.dato(c).esNat() != t.tipoCampo(c).esNat()) {
return false;
}
}
}
return true;
return true;
}
bool BaseDeDatos::_no_repite(const Registro &r, const Tabla &t) const {
list<Registro> filtrados(t.registros().begin(), t.registros().end());
for (auto clave : t.claves()) {
_filtrar_registros(clave, r.dato(clave), filtrados);
}
return filtrados.empty();
list<Registro> filtrados(t.registros().begin(), t.registros().end());
for (auto clave : t.claves()) {
_filtrar_registros(clave, r.dato(clave), filtrados);
}
return filtrados.empty();
}
list<Registro> &
BaseDeDatos::_filtrar_registros(const string &campo, const Dato &valor,
list<Registro> &registros) const {
return _filtrar_registros(campo, valor, registros, true);
return _filtrar_registros(campo, valor, registros, true);
}
list<Registro> &BaseDeDatos::_filtrar_registros(const string &campo,
const Dato &valor,
list<Registro> &registros,
bool igualdad) const {
auto iter = registros.begin();
while ( iter != registros.end()) {
auto now = iter;
iter++;
if ((not igualdad) xor now->dato(campo) != valor) {
registros.erase(now);
auto iter = registros.begin();
while (iter != registros.end()) {
auto now = iter;
iter++;
if ((not igualdad) xor now->dato(campo) != valor) {
registros.erase(now);
}
}
}
return registros;
return registros;
}
pair<vector<string>, vector<Dato> > BaseDeDatos::_tipos_tabla(const Tabla &t) {
vector<string> res_campos;
vector<Dato> res_tipos;
for (auto c : t.campos()) {
res_campos.push_back(c);
res_tipos.push_back(t.tipoCampo(c));
}
return make_pair(res_campos, res_tipos);
vector<string> res_campos;
vector<Dato> res_tipos;
for (auto c : t.campos()) {
res_campos.push_back(c);
res_tipos.push_back(t.tipoCampo(c));
}
return make_pair(res_campos, res_tipos);
}
bool BaseDeDatos::criterioValido(const Criterio &c,
const string &nombre) const {
const Tabla &t = _tablas.at(nombre);
for (auto restriccion : c) {
if (not t.campos().count(restriccion.campo())) {
return false;
}
if (t.tipoCampo(restriccion.campo()).esNat() !=
restriccion.dato().esNat()) {
return false;
const Tabla &t = _tablas.at(nombre);
for (auto restriccion : c) {
if (not t.campos().count(restriccion.campo())) {
return false;
}
if (t.tipoCampo(restriccion.campo()).esNat() !=
restriccion.dato().esNat()) {
return false;
}
}
}
return true;
return true;
}
Tabla BaseDeDatos::busqueda(const BaseDeDatos::Criterio &c,
const string &nombre) {
if (_uso_criterios.count(c)) {
_uso_criterios.at(c)++;
} else {
_uso_criterios.fast_insert(make_pair(c, 1));
}
const Tabla &ref = dameTabla(nombre);
auto campos_datos = _tipos_tabla(ref);
Tabla res(ref.claves(), campos_datos.first, campos_datos.second);
list<Registro> regs(ref.registros().begin(), ref.registros().end());
for (auto restriccion : c) {
_filtrar_registros(restriccion.campo(), restriccion.dato(),
regs, restriccion.igual());
}
for (auto r : regs) {
res.agregarRegistro(r);
}
return res;
if (_uso_criterios.count(c)) {
_uso_criterios.at(c)++;
} else {
_uso_criterios.fast_insert(make_pair(c, 1));
}
const Tabla &ref = dameTabla(nombre);
auto campos_datos = _tipos_tabla(ref);
Tabla res(ref.claves(), campos_datos.first, campos_datos.second);
list<Registro> regs(ref.registros().begin(), ref.registros().end());
for (auto restriccion : c) {
_filtrar_registros(restriccion.campo(), restriccion.dato(),
regs, restriccion.igual());
}
for (auto r : regs) {
res.agregarRegistro(r);
}
return res;
}
linear_set<BaseDeDatos::Criterio> BaseDeDatos::top_criterios() const {
linear_set<Criterio> ret;
int max = 0;
for (auto crit_count : _uso_criterios) {
if (crit_count.second >= max) {
if (crit_count.second > max) {
ret = linear_set<Criterio>();
max = crit_count.second;
}
ret.fast_insert(crit_count.first);
linear_set<Criterio> ret;
int max = 0;
for (auto crit_count : _uso_criterios) {
if (crit_count.second >= max) {
if (crit_count.second > max) {
ret = linear_set<Criterio>();
max = crit_count.second;
}
ret.fast_insert(crit_count.first);
}
}
}
return ret;
return ret;
}
void BaseDeDatos::crearIndice(const string tabla, const string columna) {
}
BaseDeDatos::joinIterator BaseDeDatos::join(string tabla1, string tabla2, string campo) {
// Tabla t1 = _tablas.at(tabla1);
// Tabla t2 = _tablas.at(tabla2);
//
// linear_set<string> resultClaves;
// vector<string> campos;
// vector<Dato> tipos;
//
// for(auto &c:t1.campos()) {
// campos.push_back(c);
// tipos.push_back(t1.tipoCampo(c));
// }
// for(auto &c:t2.campos()) {
// campos.push_back(c);
// tipos.push_back(t2.tipoCampo(c));
// }
//
// Tabla *joinTabla = new Tabla(resultClaves, campos, tipos);
//
// for (auto it = t1.registros_begin(); it != it.; ++it) {
//
// }
return *(new BaseDeDatos::joinIterator());
}
BaseDeDatos::joinIterator BaseDeDatos::join_end() {
return *(new BaseDeDatos::joinIterator());
}
......@@ -27,143 +27,151 @@ using namespace std;
class BaseDeDatos {
public:
/** @brief Criterio de búsqueda para una base de datos */
typedef linear_set<Restriccion> Criterio;
/**
* @brief Inicializa una base de datos sin tablas.
*
* \pre true
* \post \P{this} = nuevaDB
*
* \complexity{\O(1)}
*/
BaseDeDatos();
/**
* @brief Crea una nueva tabla en la base de datos.
*
* @param nombre Nombre identificador de la tabla
* @param claves Claves de la tabla a crear
* @param campos Campos de la tabla a crear
* @param tipos Tipos para los campos de la tabla a crear
*
* \pre db = \P{this} \LAND
* \LNOT (nombre \IN tablas(\P{this})) \LAND
* \LAND \LNOT \EMPTYSET?(claves) \LAND
* \FORALL (c: campo) c \IN claves \IMPLICA c \IN campos \LAND
* long(campos) = long(tipos) \LAND sinRepetidos(campos)
* \post \P{this} = agregarTabla(nuevaTabla(claves, nuevoRegistro(campos, tipos)), db)
*
* \complexity{\O(C)}
*/
void crearTabla(const string &nombre, const linear_set<string> &claves,
const vector<string> &campos, const vector<Dato> &tipos);
/**
* @brief Agrega un registro a la tabla parámetro
*
* @param r Registro a agregar
* @param nombre Nombre de la tabla donde se agrega el registro
*
* \pre db = \P{this} \LAND nombre \IN tablas(\P{this}) \LAND
* puedoInsertar?(r, dameTabla(\P{this}))
* \post \P{this} = insertarEntrada(r, nombre, db)
*
* \complexity{\O(T + copy(reg))}
*/
void agregarRegistro(const Registro &r, const string &nombre);
/**
* @brief Devuelve el conjunto de tablas existentes en la base.
*
* El conjunto de nombres se devuelve por referencia no-modificable.
*
* \pre true
* \post \P{res} = tablas(\P{this})
*
* \complexity{\O(1)}
*/
const linear_set<string> &tablas() const;
/**
* @brief Devuelve la tabla asociada al nombre.
*
* La tabla se devuelve por referencia no modificable.
*
* @param nombre Nombre de la tabla buscada.
*
* \pre nombre \IN tablas(\P{this})
* \post \P{res} = dameTabla(nombre, \P{this})
*
* \complexity{O(T)}
*/
const Tabla &dameTabla(const string &nombre) const;
/**
* @brief Devuelve la cantidad de usos que tiene un criterio
*
* @param criterio Criterio por el cual se consulta.
*
* \pre nombre \IN tablas(\P{this})
* \post \P{res} = usoCriterio(criterio, \P{this})
*
* \complexity{\O(#cs * cmp(Criterio))}
*/
int uso_criterio(const Criterio &criterio) const;
/**
* @brief Evalúa si un registro puede ingresarse en la tabla parámetro.
*
* @param r Registro a ingresar en la tabla.
* @param nombre Nombre de la tabla.
*
* \pre nombre \IN tablas(\P{this})
* \post \P{res} = puedoInsertar?(r, dameTabla(nombre, \P{this}))
*
* \complexity{\O(T + C^2 + (c * C + c * n * (C + L)))}
*/
bool registroValido(const Registro &r, const string &nombre) const;
/**
* @brief Evalúa si un criterio puede aplicarse en la tabla parámetro.
*
* @param c Criterio a utilizar.
* @param nombre Nombre de la tabla.
*
* \pre tabla \IN tablas(\P{this})
* \post \P{res} = criterioValido(c, nombre, \P{this})
*
* \complexity{\O(T + cr * C)}
*/
bool criterioValido(const Criterio &c, const string &nombre) const;
/**
* @brief Devuelve el resultado de buscar en una tabla con un criterio.
*
* @param c Criterio de búsqueda utilizado.
* @param nombre Nombre de la tabla.
*
* \pre nombre \IN tablas(\P{this}) \LAND criterioValido(c, nombre, \P{this})
* \post \P{res} = buscar(c, nombre, \P{this})
*
* \complexity{\O(T + cs * cmp(Criterio) + cr * n * (C + L + copy(reg)))}
*/
Tabla busqueda(const Criterio &c, const string &nombre);
/**
* @brief Devuelve los criterios de máximo uso.
*
* \pre true
* \post \FORALL (c : Criterio) [c \IN \P{res} \IFF
* \FORALL (c' : Criterio) usoCriterio(c, db) >= usoCriterio(c', db)]
*
* \complexity{\O(cs * copy(Criterio))}
*/
linear_set<Criterio> top_criterios() const;
/** @brief Criterio de búsqueda para una base de datos */
typedef linear_set<Restriccion> Criterio;
class joinIterator;
/**
* @brief Inicializa una base de datos sin tablas.
*
* \pre true
* \post \P{this} = nuevaDB
*
* \complexity{\O(1)}
*/
BaseDeDatos();
/**
* @brief Crea una nueva tabla en la base de datos.
*
* @param nombre Nombre identificador de la tabla
* @param claves Claves de la tabla a crear
* @param campos Campos de la tabla a crear
* @param tipos Tipos para los campos de la tabla a crear
*
* \pre db = \P{this} \LAND
* \LNOT (nombre \IN tablas(\P{this})) \LAND
* \LAND \LNOT \EMPTYSET?(claves) \LAND
* \FORALL (c: campo) c \IN claves \IMPLICA c \IN campos \LAND
* long(campos) = long(tipos) \LAND sinRepetidos(campos)
* \post \P{this} = agregarTabla(nuevaTabla(claves, nuevoRegistro(campos, tipos)), db)
*
* \complexity{\O(C)}
*/
void crearTabla(const string &nombre, const linear_set<string> &claves,
const vector<string> &campos, const vector<Dato> &tipos);
/**
* @brief Agrega un registro a la tabla parámetro
*
* @param r Registro a agregar
* @param nombre Nombre de la tabla donde se agrega el registro
*
* \pre db = \P{this} \LAND nombre \IN tablas(\P{this}) \LAND
* puedoInsertar?(r, dameTabla(\P{this}))
* \post \P{this} = insertarEntrada(r, nombre, db)
*
* \complexity{\O(T + copy(reg))}
*/
void agregarRegistro(const Registro &r, const string &nombre);
/**
* @brief Devuelve el conjunto de tablas existentes en la base.
*
* El conjunto de nombres se devuelve por referencia no-modificable.
*
* \pre true
* \post \P{res} = tablas(\P{this})
*
* \complexity{\O(1)}
*/
const linear_set<string> &tablas() const;
/**
* @brief Devuelve la tabla asociada al nombre.
*
* La tabla se devuelve por referencia no modificable.
*
* @param nombre Nombre de la tabla buscada.
*
* \pre nombre \IN tablas(\P{this})
* \post \P{res} = dameTabla(nombre, \P{this})
*
* \complexity{O(T)}
*/
const Tabla &dameTabla(const string &nombre) const;
/**
* @brief Devuelve la cantidad de usos que tiene un criterio
*
* @param criterio Criterio por el cual se consulta.
*
* \pre nombre \IN tablas(\P{this})
* \post \P{res} = usoCriterio(criterio, \P{this})
*
* \complexity{\O(#cs * cmp(Criterio))}
*/
int uso_criterio(const Criterio &criterio) const;
/**
* @brief Evalúa si un registro puede ingresarse en la tabla parámetro.
*
* @param r Registro a ingresar en la tabla.
* @param nombre Nombre de la tabla.
*
* \pre nombre \IN tablas(\P{this})
* \post \P{res} = puedoInsertar?(r, dameTabla(nombre, \P{this}))
*
* \complexity{\O(T + C^2 + (c * C + c * n * (C + L)))}
*/
bool registroValido(const Registro &r, const string &nombre) const;
/**
* @brief Evalúa si un criterio puede aplicarse en la tabla parámetro.
*
* @param c Criterio a utilizar.
* @param nombre Nombre de la tabla.
*
* \pre tabla \IN tablas(\P{this})
* \post \P{res} = criterioValido(c, nombre, \P{this})
*
* \complexity{\O(T + cr * C)}
*/
bool criterioValido(const Criterio &c, const string &nombre) const;
/**
* @brief Devuelve el resultado de buscar en una tabla con un criterio.
*
* @param c Criterio de búsqueda utilizado.
* @param nombre Nombre de la tabla.
*
* \pre nombre \IN tablas(\P{this}) \LAND criterioValido(c, nombre, \P{this})
* \post \P{res} = buscar(c, nombre, \P{this})
*
* \complexity{\O(T + cs * cmp(Criterio) + cr * n * (C + L + copy(reg)))}
*/
Tabla busqueda(const Criterio &c, const string &nombre);
/**
* @brief Devuelve los criterios de máximo uso.
*
* \pre true
* \post \FORALL (c : Criterio) [c \IN \P{res} \IFF
* \FORALL (c' : Criterio) usoCriterio(c, db) >= usoCriterio(c', db)]
*
* \complexity{\O(cs * copy(Criterio))}
*/
linear_set<Criterio> top_criterios() const;
void crearIndice(string tabla, string columna);
joinIterator join(string tabla1, string tabla2, string columna);
joinIterator join_end();
private:
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
/** \name Representación
* rep: basededatos \TO bool\n
* rep(bd) \EQUIV
......@@ -226,8 +234,8 @@ private:
* nueva(campo, valor, igualdad), registros)
*/
list<Registro> &_filtrar_registros(const string &campo, const Dato &valor,
list<Registro> &registros,
bool igualdad) const;
list<Registro> &registros,
bool igualdad) const;
/**
* @brief Filtra la lista de registros parametro según el criterio.
......@@ -253,6 +261,48 @@ private:
*/
pair<vector<string>, vector<Dato> > _tipos_tabla(const Tabla &t);
/** @} */
public:
class joinIterator {
public:
joinIterator() {
}
joinIterator operator++(int n) {
return (*this);
}
joinIterator &operator++() {
return (*this);
}
Registro &operator*() const {
return *(new Registro({"NONE"}, {datoStr("NOT IMPLEMENTED")}));
}
Registro *operator->() const {
return (new Registro({"NONE"}, {datoStr("NOT IMPLEMENTED")}));
}
friend std::ostream &operator<<(std::ostream &stream, const joinIterator &it) {
stream << "NOT IMPLEMENTED YET";
}
bool operator==(const joinIterator &other) const {
return true;
}
bool operator!=(const joinIterator &otro) const {
return !(*this == otro);
}
friend class string_map;
private:
};
};
#endif
......@@ -4,6 +4,7 @@
#include <cassert>
#include <string>
#include <vector>
#include <ostream>
using std::string;
using std::vector;
......@@ -16,7 +17,7 @@ using std::pair;
* - tiene operador == (con complejidad cmp(T))
* - solo permite utilizar el operator[] si T tiene constructor por defecto
*/
template < typename T >
template<typename T>
class string_map {
public:
typedef string key_type;
......@@ -26,52 +27,118 @@ public:
class iterator;
class const_iterator;
/** @brief Construye mapa vacio
*
* \complexity{\O(1)}
*/
string_map();
string_map() {
root = new Nodo();
cantKeys = 0;
}
/** @brief Destruye mapa
*
* \complexity{\O(sn * S)}
*/
~string_map();
~string_map() {
clear();
delete (root);
}
/** @brief Constructor por copia
*
* \complexity{\O(sn * S * copy(T))}
*/
string_map(const string_map &);
string_map(const string_map &toCopy) {
root = new Nodo;
cantKeys = 0;
for (const_iterator it = toCopy.begin();it != toCopy.end(); ++it) {
insert((*it));
}
}
void printAll() {
for (auto it = begin(); it != end(); ++it) {
auto element = (*it);
std::cout << element.first << std::endl;
}
}
/** @brief Operador de asignacion
*
* \complexity{\O(sn * S * copy(T))}
*/
string_map& operator=(const string_map &);
string_map &operator=(const string_map &toCopy) {
root = new Nodo;
cantKeys = 0;
for (const_iterator it = toCopy.begin();it != toCopy.end(); ++it) {
insert((*it));
}
return (*this);
}
/** @brief Operadores de comparacion
*
* \complexity{\O(sn * S * cmp(T))}
*/
bool operator==(const string_map& otro) const;
bool operator!=(const string_map& otro) const {return !(*this == otro);}
bool operator==(const string_map &other) const {
if (cantKeys == other.cantKeys) {
const_iterator it = begin();
const_iterator itOther = other.begin();
key_type first, firstOther;
mapped_type second, secondOther;
while(it != end()) {
first = it->first;
firstOther = itOther->first;
second = it->second;
secondOther = itOther->second;
if (first.compare(firstOther) != 0 || second != secondOther) return false;
++it;
++itOther;
}
return true;
}
return false;
}
bool operator!=(const string_map &otro) const { return !(*this == otro); }
/** @brief Cantidad de apariciones de la clave (0 o 1)
* @param key clave a buscar
*
* \complexity{\O(S)}
*/
size_type count(const key_type &key) const;
size_type count(const key_type &key) const {
auto tmp = root;
for (auto it:key) {
if (tmp->children[it - FIRST_CHAR] == NULL) {
return 0;
}
tmp = tmp->children[it - FIRST_CHAR];
}
return static_cast<size_type>(tmp->isEndOfWord);
}
/** @brief Devuelve cantidad de claves definidas */
size_t size() const;
size_t size() const {
return cantKeys;
}
/** @brief devuelve true si size() == 0 */
bool empty() const;
bool empty() const {
return size() == 0;
}
/** @brief Acceso / definición de pares clave/valor
......@@ -79,11 +146,28 @@ public:
* @returns una referencia a la definicion.
*
* \complexity{
* * \O(S) si la clave esta definida
* * \O(S) si la clave esta definida
* * \O(S) + copy(T) sino
* }
*/
mapped_type &operator[](const key_type &key);
mapped_type &operator[](const key_type &key) {
auto tmp = root;
for (auto it:key) {
auto letterPosition = static_cast<size_type>(it - FIRST_CHAR);
if (tmp->children[letterPosition] == NULL) {
tmp->children[letterPosition] = new Nodo();
tmp->children[letterPosition]->parent = tmp;
}
tmp = tmp->children[letterPosition];
}
if (!(tmp->isEndOfWord)) {
tmp->isEndOfWord = true;
tmp->value = new mapped_type();
++cantKeys;
}
return *(tmp->value);
}
/** @brief Acceso a una clave sin modificar mapa
* @param key clave a acceder que debe existir previamente
......@@ -91,18 +175,42 @@ public:
*
* \complexity{\O(S)}
*/
mapped_type& at(const key_type& key);
mapped_type &at(const key_type &key) {
auto tmp = root;
for (auto it:key) {
tmp = tmp->children[it - FIRST_CHAR];
}
return *(tmp->value);
}
/** @brief Acceso a una clave sin modificar mapa
* @param key clave a acceder que debe existir previamente
* @returns una referencia const a la definicion.
*
* \complexity{\O(S)}
*/
const mapped_type& at(const key_type& key) const;
*/
const mapped_type &at(const key_type &key) const {
auto tmp = root;
for (auto it:key) {
tmp = tmp->children[it - FIRST_CHAR];
}
return *(tmp->value);
}
/** @brief Vacia el mapa */
void clear();
void clear() {
auto tmp = begin();
for (; tmp != end();) {
std::cout << "VOY A BORRAR " << tmp << std::endl;
tmp = erase(tmp);
}
if (root->isEndOfWord) {
root->isEndOfWord = false;
--cantKeys;
}
}
// Accesos con iteradores
......@@ -111,19 +219,34 @@ public:
*
* \complexity{\O(S)}
*/
iterator begin();
iterator begin() {
return iterator(this->root);
}
/* @brief iterador al fin de la coleccion
*
* \complexity{\O(S)}
*/
iterator end();
iterator end() {
return iterator(this->root, "");
}
/// Versiones const de begin/end
const_iterator begin() const;
const_iterator end() const;
const_iterator cbegin() const;
const_iterator cend() const;
const_iterator begin() const {
return const_iterator(this->root);
}
const_iterator end() const {
return const_iterator(this->root, "");
}
const_iterator cbegin() const {
return const_iterator(this->root);
}
const_iterator cend() const {
return const_iterator(NULL);
}
/** @brief busca una clave
* @param key clave a buscar
......@@ -131,7 +254,14 @@ public:
*
* \complexity{\O(S)}
*/
iterator find(const key_type &key);
iterator find(const key_type &key) {
auto tmp = root;
for (auto it:key) {
tmp = tmp->children[it - FIRST_CHAR];
}
return iterator(tmp, key);
}
/** @brief busca una clave
* @param key clave a buscar
......@@ -139,7 +269,14 @@ public:
*
* \complexity{\O(S)}
*/
const_iterator find(const key_type &key) const;
const_iterator find(const key_type &key) const {
auto tmp = root;
for (auto it:key) {
tmp = tmp->children[it - FIRST_CHAR];
}
return const_iterator(tmp, key);
}
/** @brief insercion
*
......@@ -150,7 +287,28 @@ public:
*
* \complexity{\O(S + copy(T))}
*/
pair<iterator, bool> insert(const value_type &value);
pair<iterator, bool> insert(const value_type &value) {
auto tmp = root;
bool isInserted = false;
for (auto it:value.first) {
if (tmp->children[it - FIRST_CHAR] == NULL) {
tmp->children[it - FIRST_CHAR] = new Nodo();
tmp->children[it - FIRST_CHAR]->parent = tmp;
}
tmp = tmp->children[it - FIRST_CHAR];
}
if (!(tmp->isEndOfWord)) {
tmp->isEndOfWord = true;
++cantKeys;
isInserted = true;
}
tmp->value = new mapped_type(value.second);
iterator it = iterator(tmp, value.first);
return pair<iterator, bool>(it, isInserted);
};
/** @brief eliminar una clave
* @param key clave a eliminar
......@@ -158,7 +316,14 @@ public:
*
* \complexity{\O(S)}
*/
size_type erase(const key_type& key);
size_type erase(const key_type &key) {
if (count(key)) {
find(key).erase();
--cantKeys;
return 1;
}
return 0;
}
/** @brief eliminar una clave mediante irerador
* @param pos iterador apuntando a clave a eliminar
......@@ -166,9 +331,340 @@ public:
*
* \complexity{\O(S)}
*/
iterator erase(iterator pos);
iterator erase(iterator pos) {
--cantKeys;
return pos.erase();
}
private:
static const int ALPHABET_SIZE = 94;
static const char FIRST_CHAR = ' ';
unsigned int cantKeys;
struct Nodo {
Nodo *children[ALPHABET_SIZE];
Nodo *parent;
T *value;
bool isEndOfWord;
Nodo() {
isEndOfWord = false;
parent = NULL;
for (int i = 0; i < ALPHABET_SIZE; i++) {
children[i] = NULL;
}
value = NULL;
}
};
Nodo *root;
public:
class const_iterator {
public:
const_iterator(Nodo *root) {
auto tmp = root;
actual = findLeftestWord(tmp);
}
const_iterator(Nodo *root, key_type str) {
actual = root;
printUtilVector = std::vector<char>(str.begin(), str.end());
}
const_iterator &operator=(const const_iterator &other) {
this->printUtilVector = other.printUtilVector;
this->actual = other.actual;
return (*this);
}
bool operator==(const const_iterator &other) const {
bool isSameActual = this->actual == other.actual;
bool isSamePrintUtilVector = this->printUtilVector == other.printUtilVector;
return isSameActual && isSamePrintUtilVector;
}
bool operator!=(const const_iterator &otro) const {
return !(*this == otro);
}
const const_iterator &operator++() {
if (actual->parent == NULL) {
return (*this);
}
actual = actual->parent;
char last;
last = printUtilVector.back();
printUtilVector.pop_back();
int leftOne = leftestOne(actual, static_cast<char>(last + 1));
if (leftOne == -1) {
if (actual->isEndOfWord) {
return (*this);
}
// recursion
return ++(*this);
}
printUtilVector.push_back(FIRST_CHAR + leftOne);
actual = findLeftestWord(actual->children[leftOne]);
return (*this);
}
const const_iterator operator++(int n) {
const_iterator final = NULL;
for (int i = 0; i < n; i++) {
final = ++(*this);
}
return final;
}
const_iterator erase() {
if (leftestOne(actual, FIRST_CHAR) != -1) {
actual->isEndOfWord = false;
return ++(*this);
}
char last;
Nodo *tmp;
while (true) {
tmp = actual->parent;
// llegue al final
if (tmp == NULL) {
return (*this);
}
//borro y me quedo con el ultimo char y cambio actual y popeo
last = printUtilVector.back();
printUtilVector.pop_back();
delete (actual);
actual = tmp;
actual->children[last - FIRST_CHAR] = NULL;
if (actual->isEndOfWord) {
return (*this);
}
auto leftOne = leftestOne(actual, last);
if (leftOne != -1) {
actual = actual->children[leftOne];
printUtilVector.push_back(leftOne + FIRST_CHAR);
return findLeftestWord(actual);
}
}
}
value_type &operator*() const {
key_type key = key_type(printUtilVector.begin(), printUtilVector.end());
mapped_type value = *(actual->value);
auto *pair = new value_type(key, value);
return *pair;
}
value_type *operator->() const {
key_type key = key_type(printUtilVector.begin(), printUtilVector.end());
mapped_type value = *(actual->value);
auto *pair = new value_type(key, value);
return pair;
}
friend std::ostream &operator<<(std::ostream &stream, const const_iterator &it) {
if (it.actual->parent != NULL) {
stream << "primero: " << it->first;
} else stream << "es el fin";
return stream;
}
friend class string_map;
private:
Nodo *actual;
std::vector<char> printUtilVector;
Nodo *findLeftestWord(Nodo *tmp) {
int leftOne = 0;
while (tmp != NULL && leftOne != -1) {
leftOne = leftestOne(tmp, FIRST_CHAR);
if (leftOne != -1) {
printUtilVector.push_back(static_cast<char &&>(FIRST_CHAR + leftOne));
tmp = tmp->children[leftOne];
}
}
return tmp;
}
int leftestOne(Nodo *tmp, char last) {
for (int i = last - FIRST_CHAR; i < ALPHABET_SIZE; i++) {
if ((tmp->children[i]) != NULL) return i;
}
return -1;
}
};
class iterator {
public:
iterator(Nodo *root) {
auto tmp = root;
actual = findLeftestWord(tmp);
}
iterator(Nodo *root, key_type str) {
actual = root;
printUtilVector = std::vector<char>(str.begin(), str.end());
}
iterator &operator=(const iterator &other) {
this->printUtilVector = other.printUtilVector;
this->actual = other.actual;
return (*this);
}
bool operator==(const iterator &other) const {
bool isSameActual = this->actual == other.actual;
bool isSamePrintUtilVector = this->printUtilVector == other.printUtilVector;
return isSameActual && isSamePrintUtilVector;
}
bool operator!=(const iterator &otro) const {
return !(*this == otro);
}
iterator &operator++() {
if (actual->parent == NULL) {
return (*this);
}
actual = actual->parent;
char last;
last = printUtilVector.back();
printUtilVector.pop_back();
int leftOne = leftestOne(actual, static_cast<char>(last + 1));
if (leftOne == -1) {
if (actual->isEndOfWord) {
return (*this);
}
// recursion
return ++(*this);
}
printUtilVector.push_back(FIRST_CHAR + leftOne);
actual = findLeftestWord(actual->children[leftOne]);
return (*this);
}
iterator operator++(int n) {
iterator final = NULL;
for (int i = 0; i < n; i++) {
final = ++(*this);
}
return final;
}
iterator erase() {
if (leftestOne(actual, FIRST_CHAR) != -1) {
actual->isEndOfWord = false;
return ++(*this);
}
char last;
Nodo *tmp;
while (true) {
tmp = actual->parent;
// llegue al final
if (tmp == NULL) {
return (*this);
}
//borro y me quedo con el ultimo char y cambio actual y popeo
last = printUtilVector.back();
printUtilVector.pop_back();
delete(actual->value);
delete (actual);
actual = tmp;
actual->children[last - FIRST_CHAR] = NULL;
if (actual->isEndOfWord) {
return (*this);
}
auto leftOne = leftestOne(actual, last);
if (leftOne != -1) {
actual = actual->children[leftOne];
printUtilVector.push_back(leftOne + FIRST_CHAR);
actual = findLeftestWord(actual);
return (*this);
}
}
}
value_type &operator*() const {
key_type key = key_type(printUtilVector.begin(), printUtilVector.end());
mapped_type value = *(actual->value);
auto *pair = new value_type(key, value);
return *pair;
}
value_type *operator->() const {
key_type key = key_type(printUtilVector.begin(), printUtilVector.end());
mapped_type value = *(actual->value);
auto *pair = new value_type(key, value);
return pair;
}
friend std::ostream &operator<<(std::ostream &stream, const iterator &it) {
if (it.actual->parent != NULL) {
stream << "primero: " << it->first;
} else stream << "es el fin";
return stream;
}
friend class string_map;
private:
Nodo *actual;
std::vector<char> printUtilVector;
Nodo *findLeftestWord(Nodo *tmp) {
int leftOne = 0;
while (tmp != NULL && leftOne != -1) {
leftOne = leftestOne(tmp, FIRST_CHAR);
if (leftOne != -1) {
printUtilVector.push_back(static_cast<char &&>(FIRST_CHAR + leftOne));
tmp = tmp->children[leftOne];
}
}
return tmp;
}
int leftestOne(Nodo *tmp, char last) {
for (int i = last - FIRST_CHAR; i < ALPHABET_SIZE; i++) {
if ((tmp->children[i]) != NULL) return i;
}
return -1;
}
};
};
......
......@@ -693,7 +693,7 @@ TEST_F(DBAlumnos, crit_doble_otro_bool) {
TEST_F(DBAlumnos, join_vacio) {
db.crearIndice("alumnos", "LU");
auto begin = db.join("alumnos", "ex_alumnos", "LU");
auto end = db.join_end();
auto end = db.join_end();
EXPECT_EQ(begin, end);
}
......@@ -756,15 +756,15 @@ TEST_F(DBAlumnos, join_repetidos_ambos) {
db2.agregarRegistro(Registro({"Y", "Z"}, {Dato(1), Dato("B")}), "T2");
db2.agregarRegistro(Registro({"Y", "Z"}, {Dato(2), Dato("C")}), "T2");
Tabla t_join = Tabla({"X", "Y", "Z"}, {"X", "Y", "Z"},
Tabla t_join = Tabla({"X", "Y", "Z"}, {"X", "Y", "Z"},
{tipoNat, tipoNat, tipoStr});
t_join.agregarRegistro(Registro({"X", "Y", "Z"},
t_join.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(1), Dato(1), Dato("A")}));
t_join.agregarRegistro(Registro({"X", "Y", "Z"},
t_join.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(1), Dato(1), Dato("B")}));
t_join.agregarRegistro(Registro({"X", "Y", "Z"},
t_join.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(2), Dato(2), Dato("C")}));
t_join.agregarRegistro(Registro({"X", "Y", "Z"},
t_join.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(3), Dato(2), Dato("C")}));
db2.crearIndice("T1", "Y");
......@@ -784,44 +784,44 @@ TEST_F(DBAlumnos, join_repetidos_ambos) {
TEST_F(DBAlumnos, join_campos_repetidos) {
BaseDeDatos db2;
db2.crearTabla("T1", {"X", "Y"}, {"X", "Y"}, {tipoNat, tipoNat});
db2.crearTabla("T2", {"X", "Y", "Z"}, {"X", "Y", "Z"},
db2.crearTabla("T2", {"X", "Y", "Z"}, {"X", "Y", "Z"},
{tipoNat, tipoNat, tipoStr});
/*
* T1 T2
* | X | Y | | X | Y | Z |
* | X | Y | | X | Y | Z |
* | 1 | 1 | | 1 | 1 | A |
* | 2 | 2 | | 3 | 2 | C |
* | 2 | 2 | | 3 | 2 | C |
*
* T1 ~ T2 (Y)
* | X | Y | Z |
* | 1 | 1 | A |
* | 2 | 2 | C |
*
*
* T2 ~ T1 (Y)
* | X | Y | Z |
* | 1 | 1 | A |
* | 3 | 2 | C |
*
*
*/
db2.agregarRegistro(Registro({"X", "Y"}, {Dato(1), Dato(1)}), "T1");
db2.agregarRegistro(Registro({"X", "Y"}, {Dato(2), Dato(2)}), "T1");
db2.agregarRegistro(Registro({"X", "Y", "Z"},
db2.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(1), Dato(1), Dato("A")}), "T2");
db2.agregarRegistro(Registro({"X", "Y", "Z"},
db2.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(3), Dato(2), Dato("C")}), "T2");
Tabla t_join_a = Tabla({"X", "Y", "Z"}, {"X", "Y", "Z"},
Tabla t_join_a = Tabla({"X", "Y", "Z"}, {"X", "Y", "Z"},
{tipoNat, tipoNat, tipoStr});
t_join_a.agregarRegistro(Registro({"X", "Y", "Z"},
t_join_a.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(1), Dato(1), Dato("A")}));
t_join_a.agregarRegistro(Registro({"X", "Y", "Z"},
t_join_a.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(2), Dato(2), Dato("C")}));
Tabla t_join_b = Tabla({"X", "Y", "Z"}, {"X", "Y", "Z"},
Tabla t_join_b = Tabla({"X", "Y", "Z"}, {"X", "Y", "Z"},
{tipoNat, tipoNat, tipoStr});
t_join_b.agregarRegistro(Registro({"X", "Y", "Z"},
t_join_b.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(1), Dato(1), Dato("A")}));
t_join_b.agregarRegistro(Registro({"X", "Y", "Z"},
t_join_b.agregarRegistro(Registro({"X", "Y", "Z"},
{Dato(3), Dato(2), Dato("C")}));
db2.crearIndice("T1", "X");
......@@ -832,7 +832,7 @@ TEST_F(DBAlumnos, join_campos_repetidos) {
linear_set<Registro> join(begin, end);
EXPECT_EQ(join, t_join_a.registros());
begin = db2.join("T2", "T1", "Y");
end = db2.join_end();
......
......@@ -69,6 +69,7 @@ TEST(string_map_test, test_comparar) {
EXPECT_FALSE(m1==m2);
}
TEST(string_map_test, test_copiar) {
string_map<int> m1;
m1["hola"] = 123;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment