TProcura
Biblioteca em C++ para testes paramétricos de algoritmos, e coleção de algoritmos de procura e otimização
Loading...
Searching...
No Matches
CListaNo.cpp
Go to the documentation of this file.
1#include "CListaNo.h"
2
4 // não libertar o primeiro elemento
5 for (int i = 1; i < indice.Count(); i++)
6 if (indice[i].estado != NULL)
7 delete indice[i].estado;
8}
9
10// retorna o índice onde foi inserido
11int CListaNo::NovoElemento(TNo elemento) {
12 int id = -1;
13 if (limite == 0 || indice.Count() < 2 * limite) {
14 // adicionar, há espaço
15 indice.Add({ elemento, 1, 1 });
16 id = indice.Count() - 1;
17 }
18 else {
19 // limite de estados atingido, gerar o espaço
20 if (livre.Count() == 0)
21 // não há livres, libertar metade
22 LibertarLista();
23
24 // utilizar o primeiro livre
25 indice[id = livre.Pop()] = { elemento, 1, 1 };
26 }
27 return id;
28}
29
30void CListaNo::LibertarLista() {
31 bool jaProcessados = false; // libertar primeiro estados já processados (anteriores a atual)
32 // parar assim que existam "limite" estados livres
33 completa = false;
34 while (livre.Count() < limite) {
35 if (!jaProcessados) {
36 jaProcessados = true;
37 // apagar elementos após o estado inicial
38 while (livre.Count() < limite && Proximo(0) != atual)
39 LibertarSeguinte(0);
40 }
41 else {
42 int anteriorID = -1, piorID = -1;
43 for (int i = atual; ProximoDistinto(i) != 1; i = ProximoDistinto(i)) {
44 piorID = ProximoDistinto(i);
45 anteriorID = i;
46 }
47 if (piorID < 0) {
48 // valores todos iguais após atual, apagar o seguinte ao atual
49 while (livre.Count() < limite)
50 LibertarSeguinte(atual);
51 }
52 else {
53 // começar por libertar todos após o primeiro elemento com o pior ID
54 while (livre.Count() < limite && Proximo(piorID) != 1)
55 LibertarSeguinte(piorID);
56 if (livre.Count() < limite) {
57 // tem de se eliminar o primeiro elemento com o pior valor
58 // o que implica atualizar o proxDistinto de todos os anteriores
59 while (Proximo(anteriorID) != piorID) {
60 indice[anteriorID].proxDistinto = 1; // último elemento
61 anteriorID = Proximo(anteriorID);
62 }
63 LibertarSeguinte(anteriorID);
64 }
65 // tudo liberto com este valor, se ainda não é suficiente, seguir para o próximo
66 }
67 }
68 }
69}
70
71void CListaNo::LibertarSeguinte(int id) {
72 int i = Proximo(id);
73 livre.Push(i);
74 if (indice[i].estado != NULL) {
75 delete indice[i].estado;
76 indice[i].estado = NULL;
77 }
78 indice[id].prox = indice[i].prox;
79 indice[id].proxDistinto = indice[i].proxDistinto;
80}
81
82// insere por ordem de LB
83int CListaNo::Inserir(TNo elemento, int id) {
84 int valor, valorI;
85 int idNovo = NovoElemento(elemento);
86 if (idNovo == 0) {
87 // primeiro elemento, inserir um elemento final
88 indice.Add({ NULL,-1,-1 });
89 return 0;
90 }
91 valor = Valor(idNovo);
92 // atualizar índice
93 for (int i = id, j = -1; i >= 0; i = ProximoDistinto(i)) {
94 valorI = Valor(i);
95 if (valorI == valor) {
96 // inserir logo a seguir, já que assim nada mais altera
97 indice[idNovo].prox = Proximo(i);
98 indice[idNovo].proxDistinto = ProximoDistinto(i);
99 indice[i].prox = idNovo;
100 return i;
101 }
102 else if (valorI < valor)
103 j = i; // mantem o primeiro elemento anterior
104 else { // valor atual já é superior, valor novo
105 if (j < 0) {
106 // heurística não consistente,
107 // e agora está a gerar um estado com menor valor que o pai
108 // i, novo, i.prox, ...
109 // o i fica com o próximo distinto em novo, o que não é verdade mas mais vale assim
110 indice[idNovo].prox = Proximo(i);
111 indice[idNovo].proxDistinto = Proximo(i);
112 indice[i].prox = idNovo;
113 indice[i].proxDistinto = idNovo;
114 return idNovo;
115 }
116 else {
117 // utilizar o índice de j, anterior, colocando antes de i
118 // j, ... , novo, i
119 // atualizar o proxDistinto de j, passa a novo
120 indice[idNovo].prox = i;
121 indice[idNovo].proxDistinto = i;
122 while (j != idNovo) {
123 indice[j].proxDistinto = idNovo;
124 if (Proximo(j) == i || Proximo(j) == j)
125 indice[j].prox = idNovo;
126 j = Proximo(j);
127 }
128 return idNovo;
129 }
130 }
131 }
132 return 0;
133}
134
135// inserir todos os elementos por ordem
137 TVector<int> lbElementos, idElementos;
138 int id = atual;
139
140 // 1. Ordenar elementos, complexidaded O(N log(N))
141 for (int j = 0; j < elementos.Count(); j++)
142 lbElementos.Add(elementos[j]->LowerBound());
143 lbElementos.Sort(&idElementos);
144
145 // 2. inserir por ordem, tirando partido do local onde já está o último elemento
146 for (int j = 0; j < idElementos.Count(); j++)
147 id = Inserir(elementos[idElementos[j]], id);
148
149}
int atual
Índice do elemento atual a processar.
Definition CListaNo.h:42
int Inserir(TNo elemento, int id=0)
Insere um novo estado na lista, por ordem de LowerBound.
Definition CListaNo.cpp:83
~CListaNo()
Definition CListaNo.cpp:3
int ProximoDistinto(int i=-1)
Retorna o próximo elemento com custo distinto.
Definition CListaNo.h:80
int Proximo(int i=-1)
Retorna o próximo elemento na lista.
Definition CListaNo.h:67
int Valor(int i)
Retorna o valor (LowerBound) de um elemento.
Definition CListaNo.h:55
Representa um estado no espaço de estados.
Item & Pop()
Definition TVector.h:127
TVector< Item > & Sort(TVector< int > *idxvect=nullptr)
Ordena todo o vetor, opcionalmente devolvendo índices ordenados.
Definition TVector.h:539
TVector< Item > & Add(Item a)
Definition TVector.h:115
int Count() const
Definition TVector.h:160
TVector< Item > & Push(Item a)
Definition TVector.h:124