diff --git a/.gitignore b/.gitignore index 7063ce7..b9663b7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ # Config files /**/*.iml +# Data files +/**/*.dat + # Output/Cache files /**/out/ /**/__pycache__/ diff --git a/2ano/1semestre/aed/aula01/AED_Guiao_01.pdf b/2ano/1semestre/aed/praticas/aula01/AED_Guiao_01.pdf similarity index 100% rename from 2ano/1semestre/aed/aula01/AED_Guiao_01.pdf rename to 2ano/1semestre/aed/praticas/aula01/AED_Guiao_01.pdf diff --git a/2ano/1semestre/aed/aula01/ProgA.c b/2ano/1semestre/aed/praticas/aula01/ProgA.c similarity index 100% rename from 2ano/1semestre/aed/aula01/ProgA.c rename to 2ano/1semestre/aed/praticas/aula01/ProgA.c diff --git a/2ano/1semestre/aed/aula01/ProgA.java b/2ano/1semestre/aed/praticas/aula01/ProgA.java similarity index 100% rename from 2ano/1semestre/aed/aula01/ProgA.java rename to 2ano/1semestre/aed/praticas/aula01/ProgA.java diff --git a/2ano/1semestre/aed/aula01/hello_x.c b/2ano/1semestre/aed/praticas/aula01/hello_x.c similarity index 100% rename from 2ano/1semestre/aed/aula01/hello_x.c rename to 2ano/1semestre/aed/praticas/aula01/hello_x.c diff --git a/2ano/1semestre/aed/aula01/prim_types.c b/2ano/1semestre/aed/praticas/aula01/prim_types.c similarity index 100% rename from 2ano/1semestre/aed/aula01/prim_types.c rename to 2ano/1semestre/aed/praticas/aula01/prim_types.c diff --git a/2ano/1semestre/aed/aula01/simplest_1.c b/2ano/1semestre/aed/praticas/aula01/simplest_1.c similarity index 100% rename from 2ano/1semestre/aed/aula01/simplest_1.c rename to 2ano/1semestre/aed/praticas/aula01/simplest_1.c diff --git a/2ano/1semestre/aed/aula01/table1.c b/2ano/1semestre/aed/praticas/aula01/table1.c similarity index 100% rename from 2ano/1semestre/aed/aula01/table1.c rename to 2ano/1semestre/aed/praticas/aula01/table1.c diff --git a/2ano/1semestre/aed/aula01/table2.c b/2ano/1semestre/aed/praticas/aula01/table2.c similarity index 100% rename from 2ano/1semestre/aed/aula01/table2.c rename to 2ano/1semestre/aed/praticas/aula01/table2.c diff --git a/2ano/1semestre/aed/aula02/AED_Guiao_02.pdf b/2ano/1semestre/aed/praticas/aula02/AED_Guiao_02.pdf similarity index 100% rename from 2ano/1semestre/aed/aula02/AED_Guiao_02.pdf rename to 2ano/1semestre/aed/praticas/aula02/AED_Guiao_02.pdf diff --git a/2ano/1semestre/aed/aula02/arrays.c b/2ano/1semestre/aed/praticas/aula02/arrays.c similarity index 100% rename from 2ano/1semestre/aed/aula02/arrays.c rename to 2ano/1semestre/aed/praticas/aula02/arrays.c diff --git a/2ano/1semestre/aed/aula02/binary_search.c b/2ano/1semestre/aed/praticas/aula02/binary_search.c similarity index 100% rename from 2ano/1semestre/aed/aula02/binary_search.c rename to 2ano/1semestre/aed/praticas/aula02/binary_search.c diff --git a/2ano/1semestre/aed/aula02/integer_arithmetic_pitfalls.c b/2ano/1semestre/aed/praticas/aula02/integer_arithmetic_pitfalls.c similarity index 100% rename from 2ano/1semestre/aed/aula02/integer_arithmetic_pitfalls.c rename to 2ano/1semestre/aed/praticas/aula02/integer_arithmetic_pitfalls.c diff --git a/2ano/1semestre/aed/aula02/permute.c b/2ano/1semestre/aed/praticas/aula02/permute.c similarity index 100% rename from 2ano/1semestre/aed/aula02/permute.c rename to 2ano/1semestre/aed/praticas/aula02/permute.c diff --git a/2ano/1semestre/aed/aula02/polynomial.c b/2ano/1semestre/aed/praticas/aula02/polynomial.c similarity index 100% rename from 2ano/1semestre/aed/aula02/polynomial.c rename to 2ano/1semestre/aed/praticas/aula02/polynomial.c diff --git a/2ano/1semestre/aed/aula02/primes.c b/2ano/1semestre/aed/praticas/aula02/primes.c similarity index 100% rename from 2ano/1semestre/aed/aula02/primes.c rename to 2ano/1semestre/aed/praticas/aula02/primes.c diff --git a/2ano/1semestre/aed/aula02/strings_example.c b/2ano/1semestre/aed/praticas/aula02/strings_example.c similarity index 100% rename from 2ano/1semestre/aed/aula02/strings_example.c rename to 2ano/1semestre/aed/praticas/aula02/strings_example.c diff --git a/2ano/1semestre/aed/slides/00_AED_Apresentacao.pdf b/2ano/1semestre/aed/slides/00_AED_Apresentacao.pdf deleted file mode 100644 index f55c275..0000000 Binary files a/2ano/1semestre/aed/slides/00_AED_Apresentacao.pdf and /dev/null differ diff --git a/2ano/1semestre/aed/teoricas/README.md b/2ano/1semestre/aed/teoricas/README.md new file mode 100644 index 0000000..a6bc33e --- /dev/null +++ b/2ano/1semestre/aed/teoricas/README.md @@ -0,0 +1,19 @@ +# Algoritmos e Estruturas de Dados - Aulas Teóricas +### Projetos + resoluções de exercícios organizados por aulas +### Linguagem usada: C + +## Índice + +| Tema nº | Tópico | +|----------------------------------------------------------------------------------------------|-----------------------------------| +| [01](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema01) | Linguagem C | +| [02](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema02) | Complexidade de Algoritmos | +| [03](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema03) | Algoritmos de Procura e Ordenação | +| [04](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema04) | Algoritmos Recursivos | +| [05](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema05) | Programação Dinâmica | +| [06](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema06) | Tipos Abstratos | +| [07](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema07) | Listas Ligadas | +| [08](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema08) | Árvores Binárias | + +--- +*Pode conter erros, caso encontre algum, crie um* [*ticket*](https://github.com/TiagoRG/uaveiro-leci/issues/new) diff --git a/2ano/1semestre/aed/slides/01_AED_Linguagem_C_I.pdf b/2ano/1semestre/aed/teoricas/tema01/01_AED_Linguagem_C_I.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/01_AED_Linguagem_C_I.pdf rename to 2ano/1semestre/aed/teoricas/tema01/01_AED_Linguagem_C_I.pdf diff --git a/2ano/1semestre/aed/slides/02_AED_Linguagem_C_II.pdf b/2ano/1semestre/aed/teoricas/tema01/02_AED_Linguagem_C_II.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/02_AED_Linguagem_C_II.pdf rename to 2ano/1semestre/aed/teoricas/tema01/02_AED_Linguagem_C_II.pdf diff --git a/2ano/1semestre/aed/slides/03_AED_Complexidade_de_Algoritmos_I.pdf b/2ano/1semestre/aed/teoricas/tema02/03_AED_Complexidade_de_Algoritmos_I.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/03_AED_Complexidade_de_Algoritmos_I.pdf rename to 2ano/1semestre/aed/teoricas/tema02/03_AED_Complexidade_de_Algoritmos_I.pdf diff --git a/2ano/1semestre/aed/slides/04_AED_Complexidade_de_Algoritmos_II.pdf b/2ano/1semestre/aed/teoricas/tema02/04_AED_Complexidade_de_Algoritmos_II.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/04_AED_Complexidade_de_Algoritmos_II.pdf rename to 2ano/1semestre/aed/teoricas/tema02/04_AED_Complexidade_de_Algoritmos_II.pdf diff --git a/2ano/1semestre/aed/slides/05_AED_Algs_Procura_e_Ordenacao_I.pdf b/2ano/1semestre/aed/teoricas/tema03/05_AED_Algs_Procura_e_Ordenacao_I.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/05_AED_Algs_Procura_e_Ordenacao_I.pdf rename to 2ano/1semestre/aed/teoricas/tema03/05_AED_Algs_Procura_e_Ordenacao_I.pdf diff --git a/2ano/1semestre/aed/slides/06_AED_Algs_Procura_e_Ordenacao_II.pdf b/2ano/1semestre/aed/teoricas/tema03/06_AED_Algs_Procura_e_Ordenacao_II.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/06_AED_Algs_Procura_e_Ordenacao_II.pdf rename to 2ano/1semestre/aed/teoricas/tema03/06_AED_Algs_Procura_e_Ordenacao_II.pdf diff --git a/2ano/1semestre/aed/slides/07_AED_Algs_Procura_e_Ordenacao_III.pdf b/2ano/1semestre/aed/teoricas/tema03/07_AED_Algs_Procura_e_Ordenacao_III.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/07_AED_Algs_Procura_e_Ordenacao_III.pdf rename to 2ano/1semestre/aed/teoricas/tema03/07_AED_Algs_Procura_e_Ordenacao_III.pdf diff --git a/2ano/1semestre/aed/slides/08_AED_Algoritmos_Recursivos_I.pdf b/2ano/1semestre/aed/teoricas/tema04/08_AED_Algoritmos_Recursivos_I.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/08_AED_Algoritmos_Recursivos_I.pdf rename to 2ano/1semestre/aed/teoricas/tema04/08_AED_Algoritmos_Recursivos_I.pdf diff --git a/2ano/1semestre/aed/slides/09_AED_Algoritmos_Recursivos_II.pdf b/2ano/1semestre/aed/teoricas/tema04/09_AED_Algoritmos_Recursivos_II.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/09_AED_Algoritmos_Recursivos_II.pdf rename to 2ano/1semestre/aed/teoricas/tema04/09_AED_Algoritmos_Recursivos_II.pdf diff --git a/2ano/1semestre/aed/slides/10_AED_Programacao_Dinamica.pdf b/2ano/1semestre/aed/teoricas/tema05/10_AED_Programacao_Dinamica.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/10_AED_Programacao_Dinamica.pdf rename to 2ano/1semestre/aed/teoricas/tema05/10_AED_Programacao_Dinamica.pdf diff --git a/2ano/1semestre/aed/slides/11_AED_Tipos_Abstratos_I.pdf b/2ano/1semestre/aed/teoricas/tema06/11_AED_Tipos_Abstratos_I.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/11_AED_Tipos_Abstratos_I.pdf rename to 2ano/1semestre/aed/teoricas/tema06/11_AED_Tipos_Abstratos_I.pdf diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/Point2D.h b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/Point2D.h new file mode 100644 index 0000000..ff95cfa --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/Point2D.h @@ -0,0 +1,33 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - Outubro 2023 +// + +#ifndef _POINT2D_H_ +#define _POINT2D_H_ + +typedef struct _Point2D Point2D; + +Point2D* Point2D_CreateXY(double x, double y); +Point2D* Point2D_CreatePolar(double radius, double angle_deg); + +void Point2D_Destroy(Point2D** p); + +double Point2D_GetX(const Point2D* p); +double Point2D_GetY(const Point2D* p); + +double Point2D_GetRadius(const Point2D* p); +double Point2D_GetAngleDegrees(const Point2D* p); + +int Point2D_IsEqual(const Point2D* p1, const Point2D* p2); +int Point2D_IsDifferent(const Point2D* p1, const Point2D* p2); + +void Point2D_DisplayXY(const Point2D* p); +void Point2D_DisplayPolar(const Point2D* p); + +double Point2D_Distance(const Point2D* p1, const Point2D* p2); + +Point2D* Point2D_MidPoint(const Point2D* p1, const Point2D* p2); + +#endif diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/Point2D_Polar.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/Point2D_Polar.c new file mode 100644 index 0000000..54e25ee --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/Point2D_Polar.c @@ -0,0 +1,137 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - Outubro 2023 +// + +#include +#include +#include +#include + +#include "Point2D.h" + +// Conversion factors +#define RAD_TO_DEG 57.2957795 +#define DEG_TO_RAD 0.0174532925 + +// PI +#define PI 3.1415926536 + +// radius >= 0 +// angle in range [0, 2 * PI[ +struct _Point2D { + double radius; + double angle; +}; + +Point2D* Point2D_CreateXY(double x, double y) { + Point2D* p = malloc(sizeof(Point2D)); + assert(p != NULL); + + p->radius = sqrt(x * x + y * y); + + if (y == 0.0) { + if (x >= 0.0) { + p->angle = 0.0; + } else { + p->angle = PI; + } + } else if (x == 0.0) { + if (y > 0.0) { + p->angle = PI / 2.0; + } else { + p->angle = 3.0 * PI / 4.0; + } + } else { + // In range ]-PI,PI[ + double angle = atan2(y, x); + p->angle = (angle >= 0.0) ? angle : angle + PI; + } + + return p; +} + +Point2D* Point2D_CreatePolar(double radius, double angle_deg) { + assert(radius >= 0.0); + assert((angle_deg >= 0.0) && (angle_deg < 360.0)); + + Point2D* p = malloc(sizeof(Point2D)); + assert(p != NULL); + p->radius = radius; + p->angle = angle_deg * DEG_TO_RAD; + + return p; +} + +void Point2D_Destroy(Point2D** p) { + assert(*p != NULL); + free(*p); + *p = NULL; +} + +double Point2D_GetX(const Point2D* p) { + assert(p != NULL); + return p->radius * cos(p->angle); +} + +double Point2D_GetY(const Point2D* p) { + assert(p != NULL); + return p->radius * sin(p->angle); +} + +double Point2D_GetRadius(const Point2D* p) { + assert(p != NULL); + + return p->radius; +} + +double Point2D_GetAngleDegrees(const Point2D* p) { + assert(p != NULL); + + return p->angle * RAD_TO_DEG; +} + +int Point2D_IsEqual(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + return (p1->radius == p2->radius) && (p1->angle == p2->angle); +} + +int Point2D_IsDifferent(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + return (p1->radius != p2->radius) || (p1->angle != p2->angle); +} + +void Point2D_DisplayXY(const Point2D* p) { + assert(p != NULL); + + printf("( %.3f, %.3f )", Point2D_GetX(p), Point2D_GetY(p)); +} + +void Point2D_DisplayPolar(const Point2D* p) { + assert(p != NULL); + + printf("( %.3f, %.3f )", p->radius, p->angle); +} + +double Point2D_Distance(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + double deltaX = Point2D_GetX(p2) - Point2D_GetX(p1); + double deltaY = Point2D_GetY(p2) - Point2D_GetY(p1); + + return sqrt(deltaX * deltaX + deltaY * deltaY); +} + +Point2D* Point2D_MidPoint(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + double new_X = (Point2D_GetX(p1) + Point2D_GetX(p2)) / 2.0; + double new_Y = (Point2D_GetY(p1) + Point2D_GetY(p2)) / 2.0; + + Point2D* mid_point = Point2D_CreateXY(new_X, new_Y); + + return mid_point; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/Point2D_XY.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/Point2D_XY.c new file mode 100644 index 0000000..e34e678 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/Point2D_XY.c @@ -0,0 +1,125 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - Outubro 2023 +// + +#include +#include +#include +#include + +#include "Point2D.h" + +// Conversion factors +#define RAD_TO_DEG 57.2957795 +#define DEG_TO_RAD 0.0174532925 + +struct _Point2D { + double x; + double y; +}; + +Point2D* Point2D_CreateXY(double x, double y) { + Point2D* p = malloc(sizeof(Point2D)); + assert(p != NULL); + p->x = x; + p->y = y; + + return p; +} + +Point2D* Point2D_CreatePolar(double radius, double angle_deg) { + assert(radius >= 0.0); + assert((angle_deg >= 0.0) && (angle_deg < 360.0)); + + double angle_radians = angle_deg * DEG_TO_RAD; + + Point2D* p = malloc(sizeof(Point2D)); + assert(p != NULL); + p->x = radius * cos(angle_radians); + p->y = radius * sin(angle_radians); + + return p; +} + +void Point2D_Destroy(Point2D** p) { + assert(*p != NULL); + free(*p); + *p = NULL; +} + +double Point2D_GetX(const Point2D* p) { + assert(p != NULL); + return p->x; +} + +double Point2D_GetY(const Point2D* p) { + assert(p != NULL); + return p->y; +} + +double Point2D_GetRadius(const Point2D* p) { + assert(p != NULL); + + return sqrt(p->x * p->x + p->y * p->y); +} + +// Returns angle in range [0, 360[ degrees +double Point2D_GetAngleDegrees(const Point2D* p) { + assert(p != NULL); + + // In range [-180, 180] + double angle = atan2(p->y, p->x) * RAD_TO_DEG; + + // In range [0, 360] + angle = (angle >= 0) ? angle : angle + 360.0; + + if (angle == 360.0) { + angle = 0.0; + } + + return angle; +} + +int Point2D_IsEqual(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + return (p1->x == p2->x) && (p1->y == p2->y); +} + +int Point2D_IsDifferent(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + return (p1->x != p2->x) || (p1->y != p2->y); +} + +void Point2D_DisplayXY(const Point2D* p) { + assert(p != NULL); + + printf("( %.3f, %.3f )", p->x, p->y); +} + +void Point2D_DisplayPolar(const Point2D* p) { + assert(p != NULL); + + printf("( %.3f, %.3f )", Point2D_GetRadius(p), Point2D_GetAngleDegrees(p)); +} + +double Point2D_Distance(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + double deltaX = p2->x - p1->x; + double deltaY = p2->y - p1->y; + + return sqrt(deltaX * deltaX + deltaY * deltaY); +} + +Point2D* Point2D_MidPoint(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + double mid_point_x = (p1->x + p2->x) / 2.0; + double mid_point_y = (p1->y + p2->y) / 2.0; + + return Point2D_CreateXY(mid_point_x, mid_point_y); +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/README.txt b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/README.txt new file mode 100644 index 0000000..8a5d967 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/README.txt @@ -0,0 +1,10 @@ + +Two different internal representations for the Point2D abstract type. + +BUT, just one Point2D.h header file and one testing_Point2D.c file. + +Compile with + +gcc -Wall -Wextra testing_Point2D.c Point2D_XY.c -o testing_Point2D_XY + +gcc -Wall -Wextra testing_Point2D.c Point2D_Polar.c -o testing_Point2D_Polar \ No newline at end of file diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/testing_Point2D.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/testing_Point2D.c new file mode 100644 index 0000000..ff9929b --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/01_2DPoint/testing_Point2D.c @@ -0,0 +1,61 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - Outubro 2023 +// + +#include +#include + +#include "Point2D.h" + +int main(void) { + // Some vey simple tests + // TO DO : more thorough tests + // TO DO : check for floating point precision errors, when comparing for + // equality + + // XY (0,0) + Point2D* point_1 = Point2D_CreateXY(0.0, 0.0); + assert(Point2D_GetX(point_1) == 0.0); + assert(Point2D_GetY(point_1) == 0.0); + assert(Point2D_GetRadius(point_1) == 0.0); + assert(Point2D_GetAngleDegrees(point_1) == 0.0); + + // XY (1,0) + Point2D* point_2 = Point2D_CreateXY(1.0, 0.0); + assert(Point2D_GetX(point_2) == 1.0); + assert(Point2D_GetY(point_2) == 0.0); + assert(Point2D_GetRadius(point_2) == 1.0); + assert(Point2D_GetAngleDegrees(point_2) == 0.0); + + // Polar: radius = 2.0 and angle = 0 degrees + Point2D* point_3 = Point2D_CreatePolar(2.0, 0.0); + assert(Point2D_GetX(point_3) == 2.0); + assert(Point2D_GetY(point_3) == 0.0); + assert(Point2D_GetRadius(point_3) == 2.0); + assert(Point2D_GetAngleDegrees(point_3) == 0.0); + + // Comparing + assert(Point2D_IsEqual(point_2, point_2)); + assert(!Point2D_IsEqual(point_2, point_3)); + assert(!Point2D_IsDifferent(point_2, point_2)); + assert(Point2D_IsDifferent(point_2, point_3)); + + // Distance + assert(Point2D_Distance(point_1, point_2) == 1.0); + + // Mid-point + Point2D* midpoint = Point2D_MidPoint(point_1, point_2); + assert(Point2D_GetX(midpoint) == 0.5); + assert(Point2D_GetY(midpoint) == 0.0); + + // Destroy points + Point2D_Destroy(&point_1); + assert(point_1 == NULL); + Point2D_Destroy(&point_2); + Point2D_Destroy(&point_3); + Point2D_Destroy(&midpoint); + + return 0; +} \ No newline at end of file diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/01_example_IntegersSTACK.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/01_example_IntegersSTACK.c new file mode 100644 index 0000000..457142c --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/01_example_IntegersSTACK.c @@ -0,0 +1,67 @@ + +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - April 2020 +// +// Writing the digits of a decimal number in reverse order +// +// Integers STACK : usage example +// + +#include + +#include "IntegersStack.h" + +int main(void) { + int number; + + printf("Write a positive integer value:\n"); + + scanf("%d", &number); + + // Creating an empty STACK for integers + + Stack* s1 = StackCreate(20); + + // Get each digit and push it into the stack + // LS digit to MS digit + + while (number != 0) { + int digit = number % 10; + + StackPush(s1, digit); + + number /= 10; + } + + // Get the reversed order using a second stack + + Stack* s2 = StackCreate(20); + + while (!StackIsEmpty(s1)) { + int digit = StackPop(s1); + + StackPush(s2, digit); + } + + // Destroy the empty stack + + StackDestroy(&s1); + + // Pop from the stack and print + + printf("The reversed number:\n"); + + while (!StackIsEmpty(s2)) { + int digit; + + digit = StackPop(s2); + + printf("%d", digit); + } + + printf("\n"); + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/02_example_PointersSTACK.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/02_example_PointersSTACK.c new file mode 100644 index 0000000..2586d17 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/02_example_PointersSTACK.c @@ -0,0 +1,76 @@ + +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - April 2020 +// +// Writing the digits of a decimal number in reverse order +// +// Pointers STACK : usage example +// + +#include +#include + +#include "PointersStack.h" + +int main(void) { + int number; + + printf("Write a positive integer value:\n"); + + scanf("%d", &number); + + // Creating an empty STACK for integers + + Stack* s1 = StackCreate(20); + + // Get each digit and push it into the stack + // LS digit to MS digit + + while (number != 0) { + int* p = malloc(sizeof(int)); + + *p = number % 10; + + StackPush(s1, p); + + number /= 10; + } + + // Get the reversed order using a second stack + + Stack* s2 = StackCreate(20); + + while (!StackIsEmpty(s1)) { + int* p = (int*)StackPop(s1); + + StackPush(s2, p); + } + + // Destroy the empty stack + + StackDestroy(&s1); + + // Pop from the stack and print + + printf("The reversed number:\n"); + + while (!StackIsEmpty(s2)) { + int* p; + + p = (int*)StackPop(s2); + + printf("%d", *p); + + free(p); + } + + printf("\n"); + + // Destroy the empty stack + + StackDestroy(&s2); + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/03_example_STACK_Point2D.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/03_example_STACK_Point2D.c new file mode 100644 index 0000000..dd13e43 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/03_example_STACK_Point2D.c @@ -0,0 +1,47 @@ + +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - October 2023 +// +// Creating a STACK of 2D Points using the Point2D abstract type +// +// Pointers STACK : usage example +// + +#include +#include + +#include "Point2D.h" +#include "PointersStack.h" + +int main(void) { + // Some 2D points + Point2D* point_1 = Point2D_CreateXY(0.0, 0.0); + Point2D* point_2 = Point2D_CreateXY(1.0, 0.0); + Point2D* point_3 = Point2D_CreatePolar(2.0, 0.0); + + // Creating an empty STACK + Stack* s = StackCreate(20); + + // Pushing the points onto the STACK + StackPush(s, point_1); + StackPush(s, point_2); + StackPush(s, point_3); + + while (!StackIsEmpty(s)) { + Point2D* p = (Point2D*)StackPop(s); + Point2D_DisplayXY(p); + printf("\n"); + } + + // Destroy the empty stack + StackDestroy(&s); + + // Destroy the points + Point2D_Destroy(&point_1); + Point2D_Destroy(&point_2); + Point2D_Destroy(&point_3); + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/IntegersStack.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/IntegersStack.c new file mode 100644 index 0000000..2b83e3b --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/IntegersStack.c @@ -0,0 +1,65 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Integers stack (First In Last Out) implementation based on an array +// + +#include "IntegersStack.h" + +#include +#include + +struct _IntStack { + int max_size; // maximum stack size + int cur_size; // current stack size + int* data; // the stack data (stored in an array) +}; + +Stack* StackCreate(int size) { + assert(size >= 10 && size <= 1000000); + Stack* s = (Stack*)malloc(sizeof(Stack)); + if (s == NULL) return NULL; + s->max_size = size; + s->cur_size = 0; + s->data = (int*)malloc(size * sizeof(int)); + if (s->data == NULL) { + free(s); + return NULL; + } + return s; +} + +void StackDestroy(Stack** p) { + assert(*p != NULL); + Stack* s = *p; + free(s->data); + free(s); + *p = NULL; +} + +void StackClear(Stack* s) { s->cur_size = 0; } + +int StackSize(const Stack* s) { return s->cur_size; } + +int StackIsFull(const Stack* s) { return (s->cur_size == s->max_size) ? 1 : 0; } + +int StackIsEmpty(const Stack* s) { return (s->cur_size == 0) ? 1 : 0; } + +int StackPeek(const Stack* s) { + assert(s->cur_size > 0); + return s->data[s->cur_size - 1]; +} + +void StackPush(Stack* s, int i) { + assert(s->cur_size < s->max_size); + s->data[s->cur_size++] = i; +} + +int StackPop(Stack* s) { + assert(s->cur_size > 0); + return s->data[--(s->cur_size)]; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/IntegersStack.h b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/IntegersStack.h new file mode 100644 index 0000000..c31b08e --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/IntegersStack.h @@ -0,0 +1,34 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Integers stack (First In Last Out) implementation based on an array +// + +#ifndef _INTEGERS_STACK_ +#define _INTEGERS_STACK_ + +typedef struct _IntStack Stack; + +Stack* StackCreate(int size); + +void StackDestroy(Stack** p); + +void StackClear(Stack* s); + +int StackSize(const Stack* s); + +int StackIsFull(const Stack* s); + +int StackIsEmpty(const Stack* s); + +int StackPeek(const Stack* s); + +void StackPush(Stack* s, int i); + +int StackPop(Stack* s); + +#endif // _INTEGERS_STACK_ diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/Point2D.h b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/Point2D.h new file mode 100644 index 0000000..ff95cfa --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/Point2D.h @@ -0,0 +1,33 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - Outubro 2023 +// + +#ifndef _POINT2D_H_ +#define _POINT2D_H_ + +typedef struct _Point2D Point2D; + +Point2D* Point2D_CreateXY(double x, double y); +Point2D* Point2D_CreatePolar(double radius, double angle_deg); + +void Point2D_Destroy(Point2D** p); + +double Point2D_GetX(const Point2D* p); +double Point2D_GetY(const Point2D* p); + +double Point2D_GetRadius(const Point2D* p); +double Point2D_GetAngleDegrees(const Point2D* p); + +int Point2D_IsEqual(const Point2D* p1, const Point2D* p2); +int Point2D_IsDifferent(const Point2D* p1, const Point2D* p2); + +void Point2D_DisplayXY(const Point2D* p); +void Point2D_DisplayPolar(const Point2D* p); + +double Point2D_Distance(const Point2D* p1, const Point2D* p2); + +Point2D* Point2D_MidPoint(const Point2D* p1, const Point2D* p2); + +#endif diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/Point2D_Polar.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/Point2D_Polar.c new file mode 100644 index 0000000..54e25ee --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/Point2D_Polar.c @@ -0,0 +1,137 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - Outubro 2023 +// + +#include +#include +#include +#include + +#include "Point2D.h" + +// Conversion factors +#define RAD_TO_DEG 57.2957795 +#define DEG_TO_RAD 0.0174532925 + +// PI +#define PI 3.1415926536 + +// radius >= 0 +// angle in range [0, 2 * PI[ +struct _Point2D { + double radius; + double angle; +}; + +Point2D* Point2D_CreateXY(double x, double y) { + Point2D* p = malloc(sizeof(Point2D)); + assert(p != NULL); + + p->radius = sqrt(x * x + y * y); + + if (y == 0.0) { + if (x >= 0.0) { + p->angle = 0.0; + } else { + p->angle = PI; + } + } else if (x == 0.0) { + if (y > 0.0) { + p->angle = PI / 2.0; + } else { + p->angle = 3.0 * PI / 4.0; + } + } else { + // In range ]-PI,PI[ + double angle = atan2(y, x); + p->angle = (angle >= 0.0) ? angle : angle + PI; + } + + return p; +} + +Point2D* Point2D_CreatePolar(double radius, double angle_deg) { + assert(radius >= 0.0); + assert((angle_deg >= 0.0) && (angle_deg < 360.0)); + + Point2D* p = malloc(sizeof(Point2D)); + assert(p != NULL); + p->radius = radius; + p->angle = angle_deg * DEG_TO_RAD; + + return p; +} + +void Point2D_Destroy(Point2D** p) { + assert(*p != NULL); + free(*p); + *p = NULL; +} + +double Point2D_GetX(const Point2D* p) { + assert(p != NULL); + return p->radius * cos(p->angle); +} + +double Point2D_GetY(const Point2D* p) { + assert(p != NULL); + return p->radius * sin(p->angle); +} + +double Point2D_GetRadius(const Point2D* p) { + assert(p != NULL); + + return p->radius; +} + +double Point2D_GetAngleDegrees(const Point2D* p) { + assert(p != NULL); + + return p->angle * RAD_TO_DEG; +} + +int Point2D_IsEqual(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + return (p1->radius == p2->radius) && (p1->angle == p2->angle); +} + +int Point2D_IsDifferent(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + return (p1->radius != p2->radius) || (p1->angle != p2->angle); +} + +void Point2D_DisplayXY(const Point2D* p) { + assert(p != NULL); + + printf("( %.3f, %.3f )", Point2D_GetX(p), Point2D_GetY(p)); +} + +void Point2D_DisplayPolar(const Point2D* p) { + assert(p != NULL); + + printf("( %.3f, %.3f )", p->radius, p->angle); +} + +double Point2D_Distance(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + double deltaX = Point2D_GetX(p2) - Point2D_GetX(p1); + double deltaY = Point2D_GetY(p2) - Point2D_GetY(p1); + + return sqrt(deltaX * deltaX + deltaY * deltaY); +} + +Point2D* Point2D_MidPoint(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + double new_X = (Point2D_GetX(p1) + Point2D_GetX(p2)) / 2.0; + double new_Y = (Point2D_GetY(p1) + Point2D_GetY(p2)) / 2.0; + + Point2D* mid_point = Point2D_CreateXY(new_X, new_Y); + + return mid_point; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/Point2D_XY.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/Point2D_XY.c new file mode 100644 index 0000000..e34e678 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/Point2D_XY.c @@ -0,0 +1,125 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - Outubro 2023 +// + +#include +#include +#include +#include + +#include "Point2D.h" + +// Conversion factors +#define RAD_TO_DEG 57.2957795 +#define DEG_TO_RAD 0.0174532925 + +struct _Point2D { + double x; + double y; +}; + +Point2D* Point2D_CreateXY(double x, double y) { + Point2D* p = malloc(sizeof(Point2D)); + assert(p != NULL); + p->x = x; + p->y = y; + + return p; +} + +Point2D* Point2D_CreatePolar(double radius, double angle_deg) { + assert(radius >= 0.0); + assert((angle_deg >= 0.0) && (angle_deg < 360.0)); + + double angle_radians = angle_deg * DEG_TO_RAD; + + Point2D* p = malloc(sizeof(Point2D)); + assert(p != NULL); + p->x = radius * cos(angle_radians); + p->y = radius * sin(angle_radians); + + return p; +} + +void Point2D_Destroy(Point2D** p) { + assert(*p != NULL); + free(*p); + *p = NULL; +} + +double Point2D_GetX(const Point2D* p) { + assert(p != NULL); + return p->x; +} + +double Point2D_GetY(const Point2D* p) { + assert(p != NULL); + return p->y; +} + +double Point2D_GetRadius(const Point2D* p) { + assert(p != NULL); + + return sqrt(p->x * p->x + p->y * p->y); +} + +// Returns angle in range [0, 360[ degrees +double Point2D_GetAngleDegrees(const Point2D* p) { + assert(p != NULL); + + // In range [-180, 180] + double angle = atan2(p->y, p->x) * RAD_TO_DEG; + + // In range [0, 360] + angle = (angle >= 0) ? angle : angle + 360.0; + + if (angle == 360.0) { + angle = 0.0; + } + + return angle; +} + +int Point2D_IsEqual(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + return (p1->x == p2->x) && (p1->y == p2->y); +} + +int Point2D_IsDifferent(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + return (p1->x != p2->x) || (p1->y != p2->y); +} + +void Point2D_DisplayXY(const Point2D* p) { + assert(p != NULL); + + printf("( %.3f, %.3f )", p->x, p->y); +} + +void Point2D_DisplayPolar(const Point2D* p) { + assert(p != NULL); + + printf("( %.3f, %.3f )", Point2D_GetRadius(p), Point2D_GetAngleDegrees(p)); +} + +double Point2D_Distance(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + double deltaX = p2->x - p1->x; + double deltaY = p2->y - p1->y; + + return sqrt(deltaX * deltaX + deltaY * deltaY); +} + +Point2D* Point2D_MidPoint(const Point2D* p1, const Point2D* p2) { + assert((p1 != NULL) && (p2 != NULL)); + + double mid_point_x = (p1->x + p2->x) / 2.0; + double mid_point_y = (p1->y + p2->y) / 2.0; + + return Point2D_CreateXY(mid_point_x, mid_point_y); +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/PointersStack.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/PointersStack.c new file mode 100644 index 0000000..fec3a83 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/PointersStack.c @@ -0,0 +1,64 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - April 2020 +// +// Pointers stack (First In Last Out) implementation based on an array of +// pointers to void +// + +#include "PointersStack.h" + +#include +#include + +struct _PointersStack { + int max_size; // maximum stack size + int cur_size; // current stack size + void** data; // the stack data (pointers stored in an array) +}; + +Stack* StackCreate(int size) { + assert(size >= 10 && size <= 1000000); + Stack* s = (Stack*)malloc(sizeof(Stack)); + if (s == NULL) return NULL; + s->max_size = size; + s->cur_size = 0; + s->data = (void**)malloc(size * sizeof(void*)); + if (s->data == NULL) { + free(s); + return NULL; + } + return s; +} + +void StackDestroy(Stack** p) { + assert(*p != NULL); + Stack* s = *p; + free(s->data); + free(s); + *p = NULL; +} + +void StackClear(Stack* s) { s->cur_size = 0; } + +int StackSize(const Stack* s) { return s->cur_size; } + +int StackIsFull(const Stack* s) { return (s->cur_size == s->max_size) ? 1 : 0; } + +int StackIsEmpty(const Stack* s) { return (s->cur_size == 0) ? 1 : 0; } + +void* StackPeek(const Stack* s) { + assert(s->cur_size > 0); + return s->data[s->cur_size - 1]; +} + +void StackPush(Stack* s, void* p) { + assert(s->cur_size < s->max_size); + s->data[s->cur_size++] = p; +} + +void* StackPop(Stack* s) { + assert(s->cur_size > 0); + return s->data[--(s->cur_size)]; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/PointersStack.h b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/PointersStack.h new file mode 100644 index 0000000..0e097c5 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/PointersStack.h @@ -0,0 +1,33 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// J. Madeira - April 2020 +// +// Pointers stack (First In Last Out) implementation based on an array of +// pointers to void +// + +#ifndef _POINTERS_STACK_ +#define _POINTERS_STACK_ + +typedef struct _PointersStack Stack; + +Stack* StackCreate(int size); + +void StackDestroy(Stack** p); + +void StackClear(Stack* s); + +int StackSize(const Stack* s); + +int StackIsFull(const Stack* s); + +int StackIsEmpty(const Stack* s); + +void* StackPeek(const Stack* s); + +void StackPush(Stack* s, void* p); + +void* StackPop(Stack* s); + +#endif // _POINTERS_STACK_ diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/README.txt b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/README.txt new file mode 100644 index 0000000..b1f8a86 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/02_STACK_with_array/README.txt @@ -0,0 +1,11 @@ +Simple examples --- Compile with + +gcc -Wall -Wextra 01_example_IntegersSTACK.c IntegersStack.c -o 01_example_IntegersSTACK + +gcc -Wall -Wextra 02_example_PointersSTACK.c PointersStack.c -o 02_example_PointersSTACK + +STACK of pointers to 2D Points --- Compile with + +gcc -Wall -Wextra PointersStack.c Point2D_XY.c 03_example_STACK_Point2D.c -o 03_example_Point2D_STACK + +gcc -Wall -Wextra PointersStack.c Point2D_Polar.c 03_example_STACK_Point2D.c -o 03_example_Point2D_STACK diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/IntegersQueue.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/IntegersQueue.c new file mode 100644 index 0000000..df8d625 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/IntegersQueue.c @@ -0,0 +1,87 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// Joaquim Madeira, April 2020 +// João Manuel Rodrigues, May 2020 +// +// Integers queue (First In First Out) implementation based on a circular array + +#include "IntegersQueue.h" + +#include +#include + +struct _IntegersQueue { + int max_size; // maximum Queue size + int cur_size; // current Queue size + int head; + int tail; + int* data; // the Queue data (integers stored in an array) +}; + +// PRIVATE auxiliary function + +static int increment_index(const Queue* q, int i) { + return (i + 1 < q->max_size) ? i + 1 : 0; +} + +// PUBLIC functions + +Queue* QueueCreate(int size) { + assert(size >= 10 && size <= 1000000); + Queue* q = (Queue*)malloc(sizeof(Queue)); + if (q == NULL) return NULL; + + q->max_size = size; + q->cur_size = 0; + + q->head = 1; // cur_size = tail - head + 1 + q->tail = 0; + + q->data = (int*)malloc(size * sizeof(int)); + if (q->data == NULL) { + free(q); + return NULL; + } + return q; +} + +void QueueDestroy(Queue** p) { + assert(*p != NULL); + Queue* q = *p; + free(q->data); + free(q); + *p = NULL; +} + +void QueueClear(Queue* q) { + q->cur_size = 0; + q->head = 1; // cur_size = tail - head + 1 + q->tail = 0; +} + +int QueueSize(const Queue* q) { return q->cur_size; } + +int QueueIsFull(const Queue* q) { return (q->cur_size == q->max_size) ? 1 : 0; } + +int QueueIsEmpty(const Queue* q) { return (q->cur_size == 0) ? 1 : 0; } + +int QueuePeek(const Queue* q) { + assert(q->cur_size > 0); + return q->data[q->head]; +} + +void QueueEnqueue(Queue* q, int i) { + assert(q->cur_size < q->max_size); + q->tail = increment_index(q, q->tail); + q->data[q->tail] = i; + q->cur_size++; +} + +int QueueDequeue(Queue* q) { + assert(q->cur_size > 0); + int old_head = q->head; + q->head = increment_index(q, q->head); + q->cur_size--; + return q->data[old_head]; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/IntegersQueue.h b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/IntegersQueue.h new file mode 100644 index 0000000..477f6a9 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/IntegersQueue.h @@ -0,0 +1,33 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// Joaquim Madeira, May 2020 +// João Manuel Rodrigues, May 2020 +// +// Integers queue (First In First Out) implementation based on a circular array +// + +#ifndef _INTEGERS_QUEUE_ +#define _INTEGERS_QUEUE_ + +typedef struct _IntegersQueue Queue; + +Queue* QueueCreate(int size); + +void QueueDestroy(Queue** p); + +void QueueClear(Queue* q); + +int QueueSize(const Queue* q); + +int QueueIsFull(const Queue* q); + +int QueueIsEmpty(const Queue* q); + +int QueuePeek(const Queue* q); + +void QueueEnqueue(Queue* q, int i); + +int QueueDequeue(Queue* q); + +#endif // _INTEGERS_QUEUE_ diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/PointersQueue.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/PointersQueue.c new file mode 100644 index 0000000..e92f296 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/PointersQueue.c @@ -0,0 +1,88 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// Joaquim Madeira, April 2020 +// +// Pointers queue (First In First Out) implementation based on a circular +// array of pointers to void +// + +#include "PointersQueue.h" + +#include +#include + +struct _PointersQueue { + int max_size; // maximum Queue size + int cur_size; // current Queue size + int head; + int tail; + void** data; // the Queue data (pointers stored in an array) +}; + +// PRIVATE auxiliary function + +static int increment_index(const Queue* q, int i) { + return (i + 1 < q->max_size) ? i + 1 : 0; +} + +// PUBLIC functions + +Queue* QueueCreate(int size) { + assert(size >= 10 && size <= 1000000); + Queue* q = (Queue*)malloc(sizeof(Queue)); + if (q == NULL) return NULL; + + q->max_size = size; + q->cur_size = 0; + + q->head = 1; // cur_size = tail - head + 1 + q->tail = 0; + + q->data = (void**)malloc(size * sizeof(void*)); + if (q->data == NULL) { + free(q); + return NULL; + } + return q; +} + +void QueueDestroy(Queue** p) { + assert(*p != NULL); + Queue* q = *p; + free(q->data); + free(q); + *p = NULL; +} + +void QueueClear(Queue* q) { + q->cur_size = 0; + q->head = 1; // cur_size = tail - head + 1 + q->tail = 0; +} + +int QueueSize(const Queue* q) { return q->cur_size; } + +int QueueIsFull(const Queue* q) { return (q->cur_size == q->max_size) ? 1 : 0; } + +int QueueIsEmpty(const Queue* q) { return (q->cur_size == 0) ? 1 : 0; } + +void* QueuePeek(const Queue* q) { + assert(q->cur_size > 0); + return q->data[q->head]; +} + +void QueueEnqueue(Queue* q, void* p) { + assert(q->cur_size < q->max_size); + q->tail = increment_index(q, q->tail); + q->data[q->tail] = p; + q->cur_size++; +} + +void* QueueDequeue(Queue* q) { + assert(q->cur_size > 0); + int old_head = q->head; + q->head = increment_index(q, q->head); + q->cur_size--; + return q->data[old_head]; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/PointersQueue.h b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/PointersQueue.h new file mode 100644 index 0000000..b4a73f0 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/PointersQueue.h @@ -0,0 +1,33 @@ +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// Joaquim Madeira, April 2020 +// +// Pointers queue (First In First Out) implementation based on a circular array +// of pointers to void +// + +#ifndef _POINTERS_QUEUE_ +#define _POINTERS_QUEUE_ + +typedef struct _PointersQueue Queue; + +Queue* QueueCreate(int size); + +void QueueDestroy(Queue** p); + +void QueueClear(Queue* q); + +int QueueSize(const Queue* q); + +int QueueIsFull(const Queue* q); + +int QueueIsEmpty(const Queue* q); + +void* QueuePeek(const Queue* q); + +void QueueEnqueue(Queue* q, void* p); + +void* QueueDequeue(Queue* q); + +#endif // _POINTERS_QUEUE_ diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/README.txt b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/README.txt new file mode 100644 index 0000000..779e9b4 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/README.txt @@ -0,0 +1,10 @@ +Simple examples --- Compile with + +gcc -Wall -Wextra testing_IntegersQueue.c IntegersQueue.c -o testing_IntegersQueue + +gcc -Wall -Wextra testing_PointersQueue.c PointersQueue.c -o testing_PointersQueue + + +TASK --- Neew example + +Create a QUEUE of 2D points and test it !! diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/testing_IntegersQueue.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/testing_IntegersQueue.c new file mode 100644 index 0000000..3720680 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/testing_IntegersQueue.c @@ -0,0 +1,49 @@ + +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// Joaquim Madeira, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Integers queue (First In First Out) implementation based on an array +// +// TESTING the implementation +// + +#include +#include +#include + +#include "IntegersQueue.h" + +int main(void) { + Queue* Q = QueueCreate(100); + + int i = 0; + int o = 0; + + for (int n = 0; n < 2000000; n++) { + if (QueueSize(Q) == 0 || + (QueueSize(Q) < 20 && (rand() & 0x01000000) == 0)) { + QueueEnqueue(Q, i); + i++; + } else { + int aux = QueueDequeue(Q); + assert(aux == o); + o++; + } + if (QueueSize(Q) > 0) { + int aux = QueuePeek(Q); + assert(aux == o); + } + } + while (QueueSize(Q) > 0) { + int aux = QueueDequeue(Q); + printf("%d\n", aux); + } + + printf("All is well [i = %d, o = %d]\n", i, o); + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/testing_PointersQueue.c b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/testing_PointersQueue.c new file mode 100644 index 0000000..498e5ba --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/03_QUEUE_with_circular_array/testing_PointersQueue.c @@ -0,0 +1,54 @@ + +// +// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre +// +// Joaquim Madeira, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers queue (First In First Out) implementation based on an array +// of pointers to void +// +// TESTING the implementation +// + +#include +#include +#include + +#include "PointersQueue.h" + +int main(void) { + Queue* Q = QueueCreate(100); + + int i = 0; + int o = 0; + + for (int n = 0; n < 2000000; n++) { + if (QueueSize(Q) == 0 || + (QueueSize(Q) < 20 && (rand() & 0x01000000) == 0)) { + int* aux = malloc(sizeof(int)); + *aux = i; + QueueEnqueue(Q, aux); + i++; + } else { + int* aux = (int*)QueueDequeue(Q); + assert(*aux == o); + o++; + free(aux); + } + if (QueueSize(Q) > 0) { + int* aux = (int*)QueuePeek(Q); + assert(*aux == o); + } + } + while (QueueSize(Q) > 0) { + int* aux = (int*)QueueDequeue(Q); + printf("%d\n", *aux); + free(aux); + } + + printf("All is well [i = %d, o = %d]\n", i, o); + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/04_DEQUE_with_circular_array/README_TASKS.txt b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/04_DEQUE_with_circular_array/README_TASKS.txt new file mode 100644 index 0000000..c48c369 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema06/12_AED_TADs/04_DEQUE_with_circular_array/README_TASKS.txt @@ -0,0 +1,12 @@ + +TASKS + +1 - Specify the interface for the DEQUE abstract type - PointersDeque.h + +2 - Use a CIRCULAR ARRAY for the internal representation - PointersDeque.c + +3 - Implement the required functions + +4 - Test your code with different application examples + +SUGGESTION: use as a basis the QUEUE abstract type implemented with a CIRCULAR ARRAY \ No newline at end of file diff --git a/2ano/1semestre/aed/slides/12_AED_Tipos_Abstratos_II.pdf b/2ano/1semestre/aed/teoricas/tema06/12_AED_Tipos_Abstratos_II.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/12_AED_Tipos_Abstratos_II.pdf rename to 2ano/1semestre/aed/teoricas/tema06/12_AED_Tipos_Abstratos_II.pdf diff --git a/2ano/1semestre/aed/slides/13_AED_Listas_Ligadas_I.pdf b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I.pdf similarity index 100% rename from 2ano/1semestre/aed/slides/13_AED_Listas_Ligadas_I.pdf rename to 2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I.pdf diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/01_STACK_with_linked_list/01_exemplo_PointersSTACK.c b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/01_STACK_with_linked_list/01_exemplo_PointersSTACK.c new file mode 100644 index 0000000..d38fd31 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/01_STACK_with_linked_list/01_exemplo_PointersSTACK.c @@ -0,0 +1,97 @@ + +/***************************************************************************** + *** + *** Algoritmos e Complexidade + *** + *** Ano lectivo 2019/2020 --- 2o. Semestre + *** + *** DETI - Universidade de Aveiro + *** + ***************************************************************************** + *** + *** Ficheiro: 01_exemplo_PointersSTACK.c + *** Autor: Joaquim Madeira + *** Data: 22/04/2020 + *** Versao: 1.00 + *** + ***************************************************************************** + *** + *** Informacao: + *** + *** Escrever os algarismos de um numero pela ordem inversa. + *** + *** STACK generico de ponteiros: exemplo de utilizacao + *** + ***************************************************************************** + *** + *** Alteracoes: 0.0 22/04/2020 Autor + *** + *** Sem alteracoess. + *** + *****************************************************************************/ + +#include +#include + +#include "PointersStack.h" + +int main(void) { + int number; + + printf("Write a positive integer value:\n"); + + scanf("%d", &number); + + // Creating an empty STACK for integers + + Stack* s1 = StackCreate(); + + // Get each digit and push it into the stack + // LS digit to MS digit + + while (number != 0) { + int* p = malloc(sizeof(int)); + + *p = number % 10; + + StackPush(s1, p); + + number /= 10; + } + + // Get the reversed order using a second stack + + Stack* s2 = StackCreate(); + + while (!StackIsEmpty(s1)) { + int* p = (int*)StackPop(s1); + + StackPush(s2, p); + } + + // Destroy the empty stack + + StackDestroy(&s1); + + // Pop from the stack and print + + printf("The reversed number:\n"); + + while (!StackIsEmpty(s2)) { + int* p; + + p = (int*)StackPop(s2); + + printf("%d", *p); + + free(p); + } + + printf("\n"); + + // Destroy the empty stack + + StackDestroy(&s2); + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/01_STACK_with_linked_list/PointersStack.c b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/01_STACK_with_linked_list/PointersStack.c new file mode 100644 index 0000000..76f3dce --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/01_STACK_with_linked_list/PointersStack.c @@ -0,0 +1,102 @@ +// +// Joaquim Madeira, AlgC, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers stack (First In Last Out) implementation based on an array +// of pointers +// + +#include "PointersStack.h" + +#include +#include + +struct _PointersStackNode { + void* data; + struct _PointersStackNode* next; +}; + +struct _PointersStack { + int cur_size; // current stack size + struct _PointersStackNode* top; // the node on the top of the stack +}; + +Stack* StackCreate(void) { + Stack* s = (Stack*)malloc(sizeof(Stack)); + assert(s != NULL); + + s->cur_size = 0; + s->top = NULL; + return s; +} + +void StackDestroy(Stack** p) { + assert(*p != NULL); + Stack* s = *p; + + StackClear(s); + + free(s); + *p = NULL; +} + +void StackClear(Stack* s) { + assert(s != NULL); + + struct _PointersStackNode* p = s->top; + struct _PointersStackNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + s->cur_size = 0; + s->top = NULL; +} + +int StackSize(const Stack* s) { + assert(s != NULL); + return s->cur_size; +} + +int StackIsEmpty(const Stack* s) { + assert(s != NULL); + return (s->cur_size == 0) ? 1 : 0; +} + +void* StackPeek(const Stack* s) { + assert(s != NULL && s->cur_size > 0); + return s->top->data; +} + +void StackPush(Stack* s, void* p) { + assert(s != NULL); + + struct _PointersStackNode* aux; + aux = (struct _PointersStackNode*)malloc(sizeof(*aux)); + assert(aux != NULL); + + aux->data = p; + aux->next = s->top; + + s->top = aux; + + s->cur_size++; +} + +void* StackPop(Stack* s) { + assert(s != NULL && s->cur_size > 0); + + struct _PointersStackNode* aux = s->top; + s->top = aux->next; + s->cur_size--; + + void* p = aux->data; + + free(aux); + + return p; +} diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/01_STACK_with_linked_list/PointersStack.h b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/01_STACK_with_linked_list/PointersStack.h new file mode 100644 index 0000000..142f628 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/01_STACK_with_linked_list/PointersStack.h @@ -0,0 +1,28 @@ +// +// Joaquim Madeira, AlgC, April 2020 +// +// Pointers stack (First In Last Out) implementation based on a linked list +// + +#ifndef _POINTERS_STACK_ +#define _POINTERS_STACK_ + +typedef struct _PointersStack Stack; + +Stack* StackCreate(void); + +void StackDestroy(Stack** p); + +void StackClear(Stack* s); + +int StackSize(const Stack* s); + +int StackIsEmpty(const Stack* s); + +void* StackPeek(const Stack* s); + +void StackPush(Stack* s, void* p); + +void* StackPop(Stack* s); + +#endif // _POINTERS_STACK_ diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/02_QUEUE_with_linked_list/PointersQueue.c b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/02_QUEUE_with_linked_list/PointersQueue.c new file mode 100644 index 0000000..ca11672 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/02_QUEUE_with_linked_list/PointersQueue.c @@ -0,0 +1,117 @@ +// +// Joaquim Madeira, AlgC, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers queue (First In First Out) implementation based on an array +// of pointers +// + +#include "PointersQueue.h" + +#include +#include + +struct _PointersQueueNode { + void* data; + struct _PointersQueueNode* next; +}; + +struct _PointersQueue { + int size; // current Queue size + struct _PointersQueueNode* head; // the head of the Queue + struct _PointersQueueNode* tail; // the tail of the Queue +}; + +Queue* QueueCreate(void) { + Queue* q = (Queue*)malloc(sizeof(Queue)); + assert(q != NULL); + + q->size = 0; + q->head = NULL; + q->tail = NULL; + return q; +} + +void QueueDestroy(Queue** p) { + assert(*p != NULL); + Queue* q = *p; + + QueueClear(q); + + free(q); + *p = NULL; +} + +void QueueClear(Queue* q) { + assert(q != NULL); + + struct _PointersQueueNode* p = q->head; + struct _PointersQueueNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + q->size = 0; + q->head = NULL; + q->tail = NULL; +} + +int QueueSize(const Queue* q) { + assert(q != NULL); + return q->size; +} + +int QueueIsEmpty(const Queue* q) { + assert(q != NULL); + return (q->size == 0) ? 1 : 0; +} + +void* QueuePeek(const Queue* q) { + assert(q != NULL && q->size > 0); + return q->head->data; +} + +void QueueEnqueue(Queue* q, void* p) { + assert(q != NULL); + + struct _PointersQueueNode* aux; + aux = (struct _PointersQueueNode*)malloc(sizeof(*aux)); + assert(aux != NULL); + + aux->data = p; + aux->next = NULL; + + q->size++; + + if (q->size == 1) { + q->head = aux; + q->tail = aux; + } else { + q->tail->next = aux; + q->tail = aux; + } +} + +void* QueueDequeue(Queue* q) { + assert(q != NULL && q->size > 0); + + struct _PointersQueueNode* aux = q->head; + void* p = aux->data; + + q->size--; + + if (q->size == 0) { + q->head = NULL; + q->tail = NULL; + } else { + q->head = aux->next; + } + + free(aux); + + return p; +} diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/02_QUEUE_with_linked_list/PointersQueue.h b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/02_QUEUE_with_linked_list/PointersQueue.h new file mode 100644 index 0000000..b937a8e --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/02_QUEUE_with_linked_list/PointersQueue.h @@ -0,0 +1,29 @@ +// +// Joaquim Madeira, AlgC, April 2020 +// +// Pointers queue (First In First Out) implementation based on a linked list +// + +#ifndef _POINTERS_QUEUE_ + +#define _POINTERS_QUEUE_ + +typedef struct _PointersQueue Queue; + +Queue* QueueCreate(void); + +void QueueDestroy(Queue** p); + +void QueueClear(Queue* q); + +int QueueSize(const Queue* q); + +int QueueIsEmpty(const Queue* q); + +void* QueuePeek(const Queue* q); + +void QueueEnqueue(Queue* q, void* p); + +void* QueueDequeue(Queue* q); + +#endif // _POINTERS_QUEUE_ diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/02_QUEUE_with_linked_list/testing_PointersQueue.c b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/02_QUEUE_with_linked_list/testing_PointersQueue.c new file mode 100644 index 0000000..ac2c375 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/02_QUEUE_with_linked_list/testing_PointersQueue.c @@ -0,0 +1,52 @@ + +/// +// Joaquim Madeira, AlgC, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers queue (First In First Out) implementation based on an array +// of pointers +// +// TESTING the implementation +// + +#include +#include +#include + +#include "PointersQueue.h" + +int main(void) { + Queue* Q = QueueCreate(); + + int i = 0; + int o = 0; + + for (int n = 0; n < 2000000; n++) { + if (QueueSize(Q) == 0 || + (QueueSize(Q) < 20 && (rand() & 0x01000000) == 0)) { + int* aux = malloc(sizeof(int)); + *aux = i; + QueueEnqueue(Q, aux); + i++; + } else { + int* aux = (int*)QueueDequeue(Q); + assert(*aux == o); + o++; + free(aux); + } + if (QueueSize(Q) > 0) { + int* aux = (int*)QueuePeek(Q); + assert(*aux == o); + } + } + while (QueueSize(Q) > 0) { + int* aux = (int*)QueueDequeue(Q); + printf("%d\n", *aux); + free(aux); + } + + printf("All is well [i = %d, o = %d]\n", i, o); + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/03_LINKED_LIST/PointersList.c b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/03_LINKED_LIST/PointersList.c new file mode 100644 index 0000000..e0b9f70 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/03_LINKED_LIST/PointersList.c @@ -0,0 +1,160 @@ +// +// Joaquim Madeira, AlgC, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers LIST implementation based on an linked list +// + +// ***************** COMPLETAR AS FUNCOES !!! ******************* + +#include "PointersList.h" + +#include +#include + +struct _PointersListNode { + void* data; + struct _PointersListNode* next; +}; + +struct _PointersList { + int size; // current List size + struct _PointersListNode* head; // the head of the List + struct _PointersListNode* tail; // the tail of the List + struct _PointersListNode* current; // the current node + int currentPos; +}; + +List* ListCreate(void) { + List* l = (List*)malloc(sizeof(List)); + assert(l != NULL); + + l->size = 0; + l->head = NULL; + l->tail = NULL; + l->current = NULL; + l->currentPos = -1; // Default: before the head of the list + return l; +} + +void ListDestroy(List** p) { + assert(*p != NULL); + List* l = *p; + + ListClear(l); + + free(l); + *p = NULL; +} + +void ListClear(List* l) { + assert(l != NULL); + + struct _PointersListNode* p = l->head; + struct _PointersListNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + l->size = 0; + l->head = NULL; + l->tail = NULL; + l->current = NULL; + l->currentPos = -1; // Default: before the head of the list +} + +int ListGetSize(const List* l) { + assert(l != NULL); + return l->size; +} + +int ListIsEmpty(const List* l) { + assert(l != NULL); + return (l->size == 0) ? 1 : 0; +} + +// Current node functions + +int ListGetCurrentIndex(const List* l) { + assert(l != NULL); + return l->currentPos; +} + +void* ListGetCurrentValue(const List* l) { + assert(l != NULL && l->current != NULL); + return l->current->data; +} + +void ListModifyCurrentValue(const List* l, void* p) {} + +// The move and search functions return 0 on success and -1 on failure (on +// success the current node is changed, on failure it is not changed) + +// Search + +int ListSearchFromCurrent(const List* l, void* p) { return -1; } + +// Move to functions + +int ListMove(List* l, int newPos) { return -1; } + +int ListMoveToNext(List* l) { return -1; } + +int ListMoveToPrevious(List* l) { return -1; } + +int ListMoveToHead(List* l) { return -1; } + +int ListMoveToTail(List* l) { return -1; } + +// Insert functions + +void ListInsertBeforeHead(List* l, void* p) {} + +void ListInsertAfterTail(List* l, void* p) {} + +void ListInsertAfterCurrent(List* l, void* p) {} + +void ListInsertBeforeCurrent(List* l, void* p) {} + +// Remove functions + +void ListRemoveHead(List* l) { + assert(l != NULL && l->size > 0); + + struct _PointersListNode* aux = l->head; + + if (l->current == l->head) { + l->current = l->head->next; + if (l->current == NULL) { + l->currentPos = -1; + } else { + l->currentPos++; + } + } + + l->size--; + + if (l->size == 0) { + l->head = NULL; + l->tail = NULL; + } else { + struct _PointersListNode* next = l->head->next; + l->head = next; + } + + free(aux); +} + +void ListRemoveTail(List* l) {} + +void ListRemoveCurrent(List* l) {} + +void ListRemoveNext(List* l) {} + +// Tests + +void ListTestInvariants(const List* l) {} diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/03_LINKED_LIST/PointersList.h b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/03_LINKED_LIST/PointersList.h new file mode 100644 index 0000000..9bac075 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/03_LINKED_LIST/PointersList.h @@ -0,0 +1,74 @@ +// +// Joaquim Madeira, AlgC, April 2020 +// +// Pointers LIST implementation based on a linked list +// + +#ifndef _POINTERS_LIST_ + +#define _POINTERS_LIST_ + +typedef struct _PointersList List; + +List* ListCreate(void); + +void ListDestroy(List** p); + +void ListClear(List* l); + +int ListGetSize(const List* l); + +int ListIsEmpty(const List* l); + +// Current node functions + +int ListGetCurrentIndex(const List* l); + +void* ListGetCurrentValue(const List* l); + +void ListModifyCurrentValue(const List* l, void* p); + +// The move and search functions return 0 on success and -1 on failure (on +// success the current node is changed, on failure it is not changed) + +// Search + +int ListSearchFromCurrent(const List* l, void* p); + +// Move to functions + +int ListMove(List* l, int newPos); + +int ListMoveToNext(List* l); + +int ListMoveToPrevious(List* l); + +int ListMoveToHead(List* l); + +int ListMoveToTail(List* l); + +// Insert functions + +void ListInsertBeforeHead(List* l, void* p); + +void ListInsertAfterTail(List* l, void* p); + +void ListInsertAfterCurrent(List* l, void* p); + +void ListInsertBeforeCurrent(List* l, void* p); + +// Remove functions + +void ListRemoveHead(List* l); + +void ListRemoveTail(List* l); + +void ListRemoveCurrent(List* l); + +void ListRemoveNext(List* l); + +// Tests + +void ListTestInvariants(const List* l); + +#endif // _POINTERS_LIST_ \ No newline at end of file diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/03_LINKED_LIST/README_TASKS.txt b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/03_LINKED_LIST/README_TASKS.txt new file mode 100644 index 0000000..e8fd776 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/03_LINKED_LIST/README_TASKS.txt @@ -0,0 +1,4 @@ + +1 - Complete the missing functions on the .c file + +2 - Redo the previous application examples !! \ No newline at end of file diff --git a/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/08_DEQUE_with_linked_list/README_TASKS.txt b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/08_DEQUE_with_linked_list/README_TASKS.txt new file mode 100644 index 0000000..38cb1dc --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/13_AED_Listas_Ligadas_I/08_DEQUE_with_linked_list/README_TASKS.txt @@ -0,0 +1,11 @@ + +*** Use ADT POINTERS LIST as a basis for ADT POINTERS DEQUE *** + +1 - Establish the interface of ADT POPINTERS DEQUE, without any reference to the ADT POINTERS LIST - PointersDeque.h + +2 - Establish the internal representation using ADT POINTERS LIST - PointersDeque.c + +3 - Implement the required DEQUE functions, using the corresponding POINTERS LIST functions + +4 - Test with new application examples + diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II.pdf b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II.pdf new file mode 100644 index 0000000..b78c7f2 Binary files /dev/null and b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II.pdf differ diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/01_LINKED_LIST/PointersList.c b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/01_LINKED_LIST/PointersList.c new file mode 100644 index 0000000..708c4ad --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/01_LINKED_LIST/PointersList.c @@ -0,0 +1,160 @@ +// +// Joaquim Madeira, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers LIST implementation based on a linked list +// + +// ***************** COMPLETAR AS FUNCOES !!! ******************* + +#include "PointersList.h" + +#include +#include + +struct _PointersListNode { + void* data; + struct _PointersListNode* next; +}; + +struct _PointersList { + int size; // current List size + struct _PointersListNode* head; // the head of the List + struct _PointersListNode* tail; // the tail of the List + struct _PointersListNode* current; // the current node + int currentPos; +}; + +List* ListCreate(void) { + List* l = (List*)malloc(sizeof(List)); + assert(l != NULL); + + l->size = 0; + l->head = NULL; + l->tail = NULL; + l->current = NULL; + l->currentPos = -1; // Default: before the head of the list + return l; +} + +void ListDestroy(List** p) { + assert(*p != NULL); + List* l = *p; + + ListClear(l); + + free(l); + *p = NULL; +} + +void ListClear(List* l) { + assert(l != NULL); + + struct _PointersListNode* p = l->head; + struct _PointersListNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + l->size = 0; + l->head = NULL; + l->tail = NULL; + l->current = NULL; + l->currentPos = -1; // Default: before the head of the list +} + +int ListGetSize(const List* l) { + assert(l != NULL); + return l->size; +} + +int ListIsEmpty(const List* l) { + assert(l != NULL); + return (l->size == 0) ? 1 : 0; +} + +// Current node functions + +int ListGetCurrentIndex(const List* l) { + assert(l != NULL); + return l->currentPos; +} + +void* ListGetCurrentValue(const List* l) { + assert(l != NULL && l->current != NULL); + return l->current->data; +} + +void ListModifyCurrentValue(const List* l, void* p) {} + +// The move and search functions return 0 on success and -1 on failure (on +// success the current node is changed, on failure it is not changed) + +// Search + +int ListSearchFromCurrent(const List* l, void* p) { return -1; } + +// Move to functions + +int ListMove(List* l, int newPos) { return -1; } + +int ListMoveToNext(List* l) { return -1; } + +int ListMoveToPrevious(List* l) { return -1; } + +int ListMoveToHead(List* l) { return -1; } + +int ListMoveToTail(List* l) { return -1; } + +// Insert functions + +void ListInsertBeforeHead(List* l, void* p) {} + +void ListInsertAfterTail(List* l, void* p) {} + +void ListInsertAfterCurrent(List* l, void* p) {} + +void ListInsertBeforeCurrent(List* l, void* p) {} + +// Remove functions + +void ListRemoveHead(List* l) { + assert(l != NULL && l->size > 0); + + struct _PointersListNode* aux = l->head; + + if (l->current == l->head) { + l->current = l->head->next; + if (l->current == NULL) { + l->currentPos = -1; + } else { + l->currentPos++; + } + } + + l->size--; + + if (l->size == 0) { + l->head = NULL; + l->tail = NULL; + } else { + struct _PointersListNode* next = l->head->next; + l->head = next; + } + + free(aux); +} + +void ListRemoveTail(List* l) {} + +void ListRemoveCurrent(List* l) {} + +void ListRemoveNext(List* l) {} + +// Tests + +void ListTestInvariants(const List* l) {} diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/01_LINKED_LIST/PointersList.h b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/01_LINKED_LIST/PointersList.h new file mode 100644 index 0000000..53c7ed0 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/01_LINKED_LIST/PointersList.h @@ -0,0 +1,74 @@ +// +// Joaquim Madeira, April 2020 +// +// Pointers LIST implementation based on a linked list +// + +#ifndef _POINTERS_LIST_ + +#define _POINTERS_LIST_ + +typedef struct _PointersList List; + +List* ListCreate(void); + +void ListDestroy(List** p); + +void ListClear(List* l); + +int ListGetSize(const List* l); + +int ListIsEmpty(const List* l); + +// Current node functions + +int ListGetCurrentIndex(const List* l); + +void* ListGetCurrentValue(const List* l); + +void ListModifyCurrentValue(const List* l, void* p); + +// The move and search functions return 0 on success and -1 on failure (on +// success the current node is changed, on failure it is not changed) + +// Search + +int ListSearchFromCurrent(const List* l, void* p); + +// Move to functions + +int ListMove(List* l, int newPos); + +int ListMoveToNext(List* l); + +int ListMoveToPrevious(List* l); + +int ListMoveToHead(List* l); + +int ListMoveToTail(List* l); + +// Insert functions + +void ListInsertBeforeHead(List* l, void* p); + +void ListInsertAfterTail(List* l, void* p); + +void ListInsertAfterCurrent(List* l, void* p); + +void ListInsertBeforeCurrent(List* l, void* p); + +// Remove functions + +void ListRemoveHead(List* l); + +void ListRemoveTail(List* l); + +void ListRemoveCurrent(List* l); + +void ListRemoveNext(List* l); + +// Tests + +void ListTestInvariants(const List* l); + +#endif // _POINTERS_LIST_ \ No newline at end of file diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/01_LINKED_LIST/README_TASKS.txt b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/01_LINKED_LIST/README_TASKS.txt new file mode 100644 index 0000000..93dae66 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/01_LINKED_LIST/README_TASKS.txt @@ -0,0 +1,3 @@ + +Complete the missing functions on the .c file + diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/01_testing_SortedList.c b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/01_testing_SortedList.c new file mode 100644 index 0000000..5f54e66 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/01_testing_SortedList.c @@ -0,0 +1,76 @@ + +/// +// Joaquim Madeira, April 2020 +// +// TESTING the TAD SORTED LIST implementation +// + +#include +#include +#include + +#include "SortedList.h" + +// Storing pointers to integers + +// The comparator + +int comparator(const void* p1, const void* p2) { + int d = *(int*)p1 - *(int*)p2; + return (d > 0) - (d < 0); +} + +int main(void) { + List* list = ListCreate(comparator); + + printf("INSERTING\n"); + + for (int i = 1; i < 10; i += 2) { + int* aux = (int*)malloc(sizeof(int)); + *aux = i; + ListInsert(list, aux); + ListTestInvariants(list); + } + + for (int i = 0; i < 11; i += 2) { + int* aux = (int*)malloc(sizeof(int)); + *aux = i; + ListInsert(list, aux); + ListTestInvariants(list); + } + + printf("%d elements\n", ListGetSize(list)); + + int i = 0; + int size = ListGetSize(list); + ListMove(list, 0); + while (i < size) { + int* p = (int*)ListGetCurrentItem(list); + printf("%d ", *p); + ListMoveToNext(list); + i++; + ListTestInvariants(list); + } + + printf("\nREMOVING\n"); + + ListMoveToHead(list); + for (int i = 0; i < 6; i++) { + int* aux = ListRemoveCurrent(list); + free(aux); + ListMoveToNext(list); + ListTestInvariants(list); + } + + i = 0; + size = ListGetSize(list); + ListMove(list, 0); + while (i < size) { + int* p = (int*)ListGetCurrentItem(list); + printf("%d ", *p); + ListMoveToNext(list); + i++; + } + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/02_testing_SortedList.c b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/02_testing_SortedList.c new file mode 100644 index 0000000..00445fd --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/02_testing_SortedList.c @@ -0,0 +1,74 @@ + +/// +// Joaquim Madeira, April 2020 +// +// TESTING the TAD SORTED LIST implementation +// + +#include +#include +#include + +#include "Date.h" +#include "SortedList.h" + +// Storing pointers to integers + +// The comparator + +int comparatorForDates(const void* p1, const void* p2) { + return DateCompare((Date*)p1, (Date*)p2); +} + +int main(void) { + List* list = ListCreate(comparatorForDates); + + printf("INSERTING\n"); + + for (int i = 2; i < 13; i += 2) { + Date* aux = DateCreate(2020, 01, i); + ListInsert(list, aux); + ListTestInvariants(list); + } + + for (int i = 1; i < 15; i += 2) { + Date* aux = DateCreate(2020, 01, i); + ListInsert(list, aux); + ListTestInvariants(list); + } + + printf("%d elements\n", ListGetSize(list)); + + int i = 0; + int size = ListGetSize(list); + ListMove(list, 0); + while (i < size) { + Date* p = (Date*)ListGetCurrentItem(list); + printf("%s\n", DateFormat(p, DMY)); + ListMoveToNext(list); + i++; + ListTestInvariants(list); + } + + printf("\nREMOVING\n"); + + ListMoveToHead(list); + for (int i = 0; i < 7; i++) { + Date* aux = ListRemoveCurrent(list); + free(aux); + ListMoveToNext(list); + ListTestInvariants(list); + } + + i = 0; + size = ListGetSize(list); + ListMove(list, 0); + while (i < size) { + Date* p = (Date*)ListGetCurrentItem(list); + printf("%s\n", DateFormat(p, DMY)); + ListMoveToNext(list); + i++; + } + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/Date.c b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/Date.c new file mode 100644 index 0000000..d373fa5 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/Date.c @@ -0,0 +1,139 @@ +#include "Date.h" + +#include +#include +#include + +const Date DateMIN = {0, 1, 1}; +const Date DateMAX = {9999, 12, 31}; + +// Check if a yy,mm,dd tuple forms a valid date. +// (This would be a public static method in Java.) +int DateIsValid(int yy, int mm, int dd) { + return (DateMIN.year) <= yy && yy <= (DateMAX.year) && 1 <= mm && mm <= 12 && + 1 <= dd && dd <= DateDaysInMonth(yy, mm); +} + +// Function to test desired internal invariant for valid Date values: +// the Date should contain valid year,month,day fields. +static int invariant(Date* d) { return DateIsValid(d->year, d->month, d->day); } + +// Alocate and store a date given by yy, mm, dd integers. +// (yy, mm, dd) are required to form a valid date. +// Returns the pointer to the new date structure, +// or NULL if allocation fails. +Date* DateCreate(int yy, int mm, int dd) { + assert(DateIsValid(yy, mm, dd)); + Date* d = (Date*)malloc(sizeof(*d)); + if (d == NULL) return d; + d->year = (uint16_t)yy; + d->month = (uint8_t)mm; + d->day = (uint8_t)dd; + assert(invariant(d)); // check invariant + return d; +} + +// Free the memory pointed to by *pd and invalidate *pd contents. +// Precondition: *pd must not be NULL. +// Postcondition: *pd is set to NULL. +void DateDestroy(Date** pd) { + assert(*pd != NULL); + free(*pd); + *pd = NULL; +} + +// table of month lengths in common and leap years +static const uint8_t monthLength[][12] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; + +int DateDaysInMonth(int yy, int mm) { + int isLeap = DateIsLeapYear(yy); + return monthLength[isLeap][mm - 1]; +} + +int DateIsLeapYear(int yy) { + return (yy % 4 == 0 && yy % 100 != 0) || yy % 400 == 0; +} + +// Compare dates a and b. +// Return an integer >0 if a>b, 0 if a==b and <0 if ayear - (int)b->year; + if (r != 0) return r; + r = (int)a->month - (int)b->month; + if (r != 0) return r; + r = (int)a->day - (int)b->day; + return r; +} + +// Increment date. +// Precondition: d must precede DateMAX. +void DateIncr(Date* d) { + assert(DateCompare(d, &DateMAX) < 0); // d must precede MAX! + if ((int)d->day < DateDaysInMonth((int)(d->year), (int)(d->month))) { + d->day++; + } else { + d->day = 1; + if ((int)d->month < 12) { + d->month++; + } else { + d->month = 1; + d->year++; + } + } + assert(invariant(d)); // check invariant +} + +// Decrement date. +// Precondition: d must succeed DateMIN. +void DateDecr(Date* d) { + assert(DateCompare(d, &DateMIN) > 0); // d must succeed MIN! + if ((int)d->day > 1) { + d->day--; + } else { + // decrMonth + if ((int)d->month > 1) { + d->month--; + } else { + d->year--; + d->month = (uint8_t)12; + } + d->day = DateDaysInMonth((int)(d->year), (int)(d->month)); + } + assert(invariant(d)); // check invariant +} + +// static char* monthNames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", +// "Aug", "Sep", "Oct", "Nov", "Dec"}; +static char strBuffer[64]; + +static char* fmts[] = { + (char*)"%04d-%02d-%02d", // YMD + (char*)"%3$02d/%2$02d/%1$04d", // DMY + (char*)"%2$02d/%3$02d/%1$04d", // MDY +}; + +// Return a formatted string representation of date d. +// Careful: the string buffer will be overwritten by the next call. +// You should strcpy or strdup the result if you need persistence! +char* DateFormat(const Date* d, int FMT) { + if (d == NULL) + snprintf(strBuffer, sizeof(strBuffer), "NULL"); + else + snprintf(strBuffer, sizeof(strBuffer), fmts[FMT], d->year, d->month, + d->day); + return strBuffer; +} + +// Parse str acording to format and return NEW Date, +// or NULL if invalid or memory error. +Date* DateParse(const char* str, int FMT) { + int yy, mm, dd; + int n = sscanf(str, fmts[FMT], &yy, &mm, &dd); + Date* d = NULL; + if (n == 3 && DateIsValid(yy, mm, dd)) { + d = DateCreate(yy, mm, dd); + } + return d; +} diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/Date.h b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/Date.h new file mode 100644 index 0000000..9421d2f --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/Date.h @@ -0,0 +1,36 @@ +#ifndef _DATE_ +#define _DATE_ + +#include + +struct _date { + uint16_t year; + uint8_t month; + uint8_t day; +}; + +// The Date type. (To be used in clients.) +typedef struct _date Date; + +// Constants +extern const Date DateMIN; +extern const Date DateMAX; + +// Macros to select date format +#define YMD 0 +#define DMY 1 +#define MDY 2 + + +Date* DateCreate(int yy, int mm, int dd) ; +void DateDestroy(Date* *pd) ; +int DateIsValid(int yy, int mm, int dd) ; +int DateDaysInMonth(int yy, int mm) ; +int DateIsLeapYear(int yy) ; +int DateCompare(const Date* a, const Date* b) ; +void DateIncr(Date* d) ; +void DateDecr(Date* d) ; +char* DateFormat(const Date* d, int FMT) ; +Date* DateParse(const char* str, int FMT) ; + +#endif //_DATE_ diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/SortedList.c b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/SortedList.c new file mode 100644 index 0000000..49d8c37 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/SortedList.c @@ -0,0 +1,338 @@ +// +// Joaquim Madeira, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// SORTED LIST implementation based on a linked list +// + +// ***************** COMPLETAR AS FUNCOES !!! ******************* + +#include "SortedList.h" + +#include +#include + +struct _ListNode { + void* item; + struct _ListNode* next; +}; + +struct _SortedList { + int size; // current List size + struct _ListNode* head; // the head of the List + struct _ListNode* tail; // the tail of the List + struct _ListNode* current; // the current node + int currentPos; // the current node index + compFunc compare; +}; + +List* ListCreate(compFunc compF) { + List* l = (List*)malloc(sizeof(List)); + assert(l != NULL); + + l->size = 0; + l->head = NULL; + l->tail = NULL; + l->current = NULL; + l->currentPos = -1; // Default: before the head of the list + l->compare = compF; + return l; +} + +void ListDestroy(List** p) { + assert(*p != NULL); + List* l = *p; + + ListClear(l); + + free(l); + *p = NULL; +} + +void ListClear(List* l) { + assert(l != NULL); + + struct _ListNode* p = l->head; + struct _ListNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + l->size = 0; + l->head = NULL; + l->tail = NULL; + l->current = NULL; + l->currentPos = -1; // Default: before the head of the list +} + +int ListGetSize(const List* l) { + assert(l != NULL); + return l->size; +} + +int ListIsEmpty(const List* l) { + assert(l != NULL); + return (l->size == 0) ? 1 : 0; +} + +// Current node functions + +int ListGetCurrentIndex(const List* l) { + assert(l != NULL); + return l->currentPos; +} + +void* ListGetCurrentItem(const List* l) { + assert(l != NULL && l->current != NULL); + return l->current->item; +} + +void ListModifyCurrentValue(const List* l, void* p) { + assert(l != NULL && l->current != NULL); + l->current->item = p; +} + +// The move and search functions return 0 on success and -1 on failure (on +// success the current node is changed, on failure it is not changed) + +// Search +// +// starting at the current node, search for the first node with a value of *p +// on failure the current node is not changed +// +int ListSearch(List* l, const void* p) { + int i = (l->currentPos < 0) ? 0 : l->currentPos; + + struct _ListNode* sn = (l->currentPos < 0) ? l->head : l->current; + + while (i < l->size && l->compare(p, sn->item) > 0) { + i++; + sn = sn->next; + } + + if (i == l->size) { + return -1; + } // failure + + if (l->compare(p, sn->item) < 0) { + return -1; + } // failure + + l->current = sn; + l->currentPos = i; + + return 0; // success +} + +// Move to functions + +int ListMove(List* l, int newPos) { + if (newPos < -1 || newPos > l->size) { + return -1; + } // failure + + if (newPos == -1 || newPos == l->size) { + l->current = NULL; + } else if (newPos == 0) { + l->current = l->head; + } else if (newPos == l->size - 1) { + l->current = l->tail; + } else { + if (l->currentPos == -1 || l->currentPos == l->size || + newPos < l->currentPos) { + l->current = l->head; + l->currentPos = 0; + } + + for (int i = l->currentPos; i < newPos; i++) { + l->current = l->current->next; + } + } + l->currentPos = newPos; + + return 0; // success +} + +int ListMoveToNext(List* l) { return ListMove(l, l->currentPos + 1); } + +int ListMoveToPrevious(List* l) { return ListMove(l, l->currentPos - 1); } + +int ListMoveToHead(List* l) { return ListMove(l, 0); } + +int ListMoveToTail(List* l) { return ListMove(l, l->size - 1); } + +// Insert function + +// +// insert a node +// the current node is not changed +// return 0 on success +// return -1 on failure +// +int ListInsert(List* l, void* p) { + struct _ListNode* sn = (struct _ListNode*)malloc(sizeof(struct _ListNode)); + assert(sn != NULL); + sn->item = p; + sn->next = NULL; + + // Empty list + if (l->size == 0) { + l->head = l->tail = sn; + l->size = 1; + return 0; + } + + // Search + + int i = 0; + struct _ListNode* prev = NULL; + struct _ListNode* aux = l->head; + + while (i < l->size && l->compare(p, aux->item) > 0) { + i++; + prev = aux; + aux = aux->next; + } + + if (i == l->size) { // Append at the tail + l->tail->next = sn; + l->tail = sn; + l->size++; + return 0; + } + + if (l->compare(p, aux->item) == 0) { // Already exists !! + free(sn); + return -1; + } // failure + + if (i == 0) { // Append at the head + sn->next = l->head; + l->head = sn; + l->size++; + if (l->currentPos >= 0) { + l->currentPos++; + } + return 0; + } + + sn->next = aux; + prev->next = sn; + l->size++; + if (l->currentPos >= i) { + l->currentPos++; + } + + return 0; +} + +// Remove functions + +// +// remove the head of the list and make its next node the new head +// if the current node is the head, it is replaced by its next node +// +void* ListRemoveHead(List* l) { + assert(l->size > 0); + if (l->current == l->head) { + l->current = l->head->next; + l->currentPos++; + } + if (l->size == 1) { + void* p = l->head->item; + free(l->head); + l->head = NULL; + l->tail = NULL; + l->size = 0; + if (l->currentPos > 0) l->currentPos = 0; + return p; + } else { + struct _ListNode* sn = l->head->next; + void* p = l->head->item; + free(l->head); + l->head = sn; + if (l->currentPos > 0) l->currentPos--; + l->size--; + return p; + } +} + +// +// remove the tail of the list and make its previous node the new tail +// if the current node is the tail, it is replaced by it by its next node +// +void* ListRemoveTail(List* l) { + assert(l->size > 0); + if (l->current == l->tail) { + l->current = NULL; + l->currentPos++; + } + if (l->size == 1) { + void* p = l->head->item; + free(l->head); + l->head = NULL; + l->tail = NULL; + l->current = NULL; + if (l->currentPos > 0) l->currentPos = 0; + l->size = 0; + return p; + } else { + struct _ListNode* sn = l->head; + while (sn->next != l->tail) sn = sn->next; + sn->next = NULL; + void* p = l->tail->item; + free(l->tail); + l->tail = sn; + if (l->currentPos == l->size) l->currentPos--; + l->size--; + return p; + } +} + +// +// remove the current node and make its next node the current node +// +void* ListRemoveCurrent(List* l) { + assert(l->currentPos >= 0 && l->currentPos < l->size); + if (l->currentPos == 0) + return ListRemoveHead(l); + else if (l->currentPos == l->size - 1) + return ListRemoveTail(l); + else { + struct _ListNode* sn = l->head; + while (sn->next != l->current) sn = sn->next; + sn->next = l->current->next; + void* p = l->current->item; + free(l->current); + l->current = sn->next; + l->size--; + return p; + } +} + +// Tests + +void ListTestInvariants(const List* l) { + assert(l->size >= 0); + if (l->size == 0) + assert(l->head == NULL && l->tail == NULL); + else + assert(l->head != NULL && l->tail != NULL); + if (l->size == 1) assert(l->head == l->tail); + assert(-1 <= l->currentPos && l->currentPos <= l->size); + if (l->currentPos == -1 || l->currentPos == l->size) + assert(l->current == NULL); + struct _ListNode* sn = l->head; + for (int i = 0; i < l->size; i++) { + if (i == l->size - 1) + assert(sn == l->tail && sn->next == NULL); + else + assert(sn->next != NULL); + if (i == l->currentPos) assert(sn == l->current); + sn = sn->next; + } +} diff --git a/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/SortedList.h b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/SortedList.h new file mode 100644 index 0000000..00909ff --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema07/14_AED_Listas_Ligadas_II/02_SORTEDLIST_with_comparison_function/SortedList.h @@ -0,0 +1,68 @@ +// +// Joaquim Madeira, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// SORTED LIST implementation based on a linked list +// + +#ifndef _SORTED_LIST_ +#define _SORTED_LIST_ + +typedef struct _SortedList List; +typedef int (*compFunc)(const void* p1, const void* p2); + +List* ListCreate(compFunc compF); + +void ListDestroy(List** p); + +void ListClear(List* l); + +int ListGetSize(const List* l); + +int ListIsEmpty(const List* l); + +// Current node functions + +int ListGetCurrentIndex(const List* l); + +void* ListGetCurrentItem(const List* l); + +void ListModifyCurrentItem(const List* l, void* p); + +// The move and search functions return 0 on success and -1 on failure (on +// success the current node is changed, on failure it is not changed) + +// Search + +int ListSearch(List* l, const void* p); + +// Move to + +int ListMove(List* l, int newPos); + +int ListMoveToNext(List* l); + +int ListMoveToPrevious(List* l); + +int ListMoveToHead(List* l); + +int ListMoveToTail(List* l); + +// Insert + +int ListInsert(List* l, void* p); + +// Remove + +void* ListRemoveHead(List* l); + +void* ListRemoveTail(List* l); + +void* ListRemoveCurrent(List* l); + +// Tests + +void ListTestInvariants(const List* l); + +#endif // _SORTED_LIST_ \ No newline at end of file diff --git a/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias/01_IntegersBinTree_V_1/01_example.c b/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias/01_IntegersBinTree_V_1/01_example.c new file mode 100644 index 0000000..b5ac854 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias/01_IntegersBinTree_V_1/01_example.c @@ -0,0 +1,92 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Integers Binary Tree --- FIRST VERSION --- Test Code +// +// SOME FUNCTIONS ARE INCOMPLETE on IntegersBinTree.c +// + +#include +#include + +#include "IntegersBinTree.h" + +void printInteger(int* p) { printf("%d ", *p); } + +void multiplyIntegerBy2(int* p) { *p *= 2; } + +int main(void) { + Tree* tree = createExampleTree(); + + printf("Created an example tree\n"); + + if (TreeIsEmpty(tree)) { + printf("The created tree is EMPTY\n"); + } else { + printf("The created tree is OK\n"); + } + + printf("Number of nodes = %d\n", TreeGetNumberOfNodes(tree)); + + printf("Height = %d\n", TreeGetHeight(tree)); + + printf("PRE-Order traversal : "); + + TreeTraverseInPREOrder(tree, printInteger); + + printf("\n"); + + printf("IN-Order traversal : "); + + TreeTraverseINOrder(tree, printInteger); + + printf("\n"); + + printf("POST-Order traversal : "); + + TreeTraverseInPOSTOrder(tree, printInteger); + + printf("\n"); + + for (int i = 0; i < 16; i++) { + if (TreeContains(tree, i)) { + printf("The tree contains %d\n", i); + } else { + printf("The tree DOES NOT CONTAIN %d\n", i); + } + } + + printf("Multiply each value by 2\n"); + + TreeTraverseInPREOrder(tree, multiplyIntegerBy2); + + printf("PRE-Order traversal : "); + + TreeTraverseInPREOrder(tree, printInteger); + + printf("\n"); + + if (TreeEquals(tree, tree)) { + printf("The tree EQUALS ITSELF\n"); + } else { + printf("Something WRONG happened!!\n"); + } + + if (TreeMirrors(tree, tree)) { + printf("Something WRONG happened!!\n"); + } else { + printf("The tree DOES NOT MIRROR ITSELF\n"); + } + + TreeDestroy(&tree); + + printf("The tree was DESTROYED\n"); + + if (TreeIsEmpty(tree)) { + printf("The tree is NOW EMPTY\n"); + } else { + printf("Something WRONG happened!!\n"); + } + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias/01_IntegersBinTree_V_1/IntegersBinTree.c b/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias/01_IntegersBinTree_V_1/IntegersBinTree.c new file mode 100644 index 0000000..794f9d7 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias/01_IntegersBinTree_V_1/IntegersBinTree.c @@ -0,0 +1,106 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from an old example (2003, 2020) +// +// Integers Binary Tree --- FIRST VERSION --- INCOMPLETE +// + +#include "IntegersBinTree.h" + +#include +#include + +struct _TreeNode { + ItemType item; + struct _TreeNode* left; + struct _TreeNode* right; +}; + +Tree* TreeCreate(void) { return NULL; } + +void TreeDestroy(Tree** pRoot) { + // ... +} + +int TreeIsEmpty(const Tree* root) { return root == NULL; } + +int TreeEquals(const Tree* root1, const Tree* root2) { + // ... + return 0; +} + +int TreeMirrors(const Tree* root1, const Tree* root2) { + // ... + return 0; +} + +int TreeGetNumberOfNodes(const Tree* root) { + // ... + return 0; +} + +int TreeGetHeight(const Tree* root) { + // ... + return 0; +} + +void TreeTraverseInPREOrder(Tree* root, void (*function)(ItemType* p)) { + // ... +} + +void TreeTraverseINOrder(Tree* root, void (*function)(ItemType* p)) { + // ... +} + +void TreeTraverseInPOSTOrder(Tree* root, void (*function)(ItemType* p)) { + // ... +} + +// ... + +int TreeContains(const Tree* root, const ItemType item) { + // ... + return 0; +} + +int TreeAdd(Tree** pRoot, const ItemType item) { + // ... + return 0; +} + +int TreeRemove(Tree** pRoot, const ItemType item) { + // ... + return 0; +} + +// ... + +// JUST FOR RUNNING EXAMPLES - REMOVE FROM THE INTERFACE + +Tree* createExampleTree(void) { + // SHOULD NEVER BE DONE LIKE THIS !!!???!!! + + int numNodes = 8; + + Tree* nodes[numNodes]; + + for (int i = 0; i < numNodes; i++) { + nodes[i] = (Tree*)malloc(sizeof(Tree)); + nodes[i]->item = i + 1; + nodes[i]->left = nodes[i]->right = NULL; + } + + nodes[3]->left = nodes[7]; + + nodes[1]->left = nodes[3]; + nodes[1]->right = nodes[4]; + + nodes[2]->left = nodes[5]; + nodes[2]->right = nodes[6]; + + nodes[0]->left = nodes[1]; + nodes[0]->right = nodes[2]; + + return nodes[0]; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias/01_IntegersBinTree_V_1/IntegersBinTree.h b/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias/01_IntegersBinTree_V_1/IntegersBinTree.h new file mode 100644 index 0000000..c0f508c --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias/01_IntegersBinTree_V_1/IntegersBinTree.h @@ -0,0 +1,71 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from an old example (2003, 2020) +// +// Integers Binary Tree --- FIRST VERSION --- INCOMPLETE +// + +#ifndef _INTEGERS_BINTREE_ +#define _INTEGERS_BINTREE_ + +// JUST storing integers +typedef int ItemType; + +typedef struct _TreeNode Tree; + +Tree* TreeCreate(void); + +void TreeDestroy(Tree** pRoot); + +// Tree properties + +int TreeIsEmpty(const Tree* root); + +int TreeEquals(const Tree* root1, const Tree* root2); + +int TreeMirrors(const Tree* root1, const Tree* root2); + +// ... + +// Getters + +int TreeGetNumberOfNodes(const Tree* root); + +int TreeGetHeight(const Tree* root); + +ItemType TreeGetMin(const Tree* root); + +ItemType TreeGetMax(const Tree* root); + +Tree* TreeGetPointerToMinNode(const Tree* root); + +Tree* TreeGetPointerToMaxNode(const Tree* root); + +// ... + +// Traversals + +void TreeTraverseInPREOrder(Tree* root, void (*function)(ItemType* p)); + +void TreeTraverseINOrder(Tree* root, void (*function)(ItemType* p)); + +void TreeTraverseInPOSTOrder(Tree* root, void (*function)(ItemType* p)); + +// ... + +// Operations with items + +int TreeContains(const Tree* root, const ItemType item); + +int TreeAdd(Tree** pRoot, const ItemType item); + +int TreeRemove(Tree** pRoot, const ItemType item); + +// ... + +// JUST FOR RUNNING EXAMPLES - REMOVE FROM THE INTERFACE + +Tree* createExampleTree(void); + +#endif // _INTEGERS_BINTREE_ diff --git a/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias_I.pdf b/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias_I.pdf new file mode 100644 index 0000000..6b886f3 Binary files /dev/null and b/2ano/1semestre/aed/teoricas/tema08/15_AED_Arvores_Binarias_I.pdf differ diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II.pdf b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II.pdf new file mode 100644 index 0000000..79a5d98 Binary files /dev/null and b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II.pdf differ diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/02_example.c b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/02_example.c new file mode 100644 index 0000000..1fced5d --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/02_example.c @@ -0,0 +1,128 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Integers Binary Tree --- SECOND VERSION --- INCOMPLETE +// + +#include +#include + +#include "IntegersBinTree.h" + +void printInteger(int* p) { printf("%d ", *p); } + +void multiplyIntegerBy2(int* p) { *p *= 2; } + +int main(void) { + Tree* tree = createExampleTree(); + + printf("Created an example tree\n"); + + if (TreeIsEmpty(tree)) { + printf("The created tree is EMPTY\n"); + } else { + printf("The created tree is OK\n"); + } + + printf("Number of nodes = %d\n", TreeGetNumberOfNodes(tree)); + + printf("Height = %d\n", TreeGetHeight(tree)); + + printf("SMALLEST value = %d\n", TreeGetMin(tree)); + + printf("LARGEST value = %d\n", TreeGetMax(tree)); + + printf("PRE-Order traversal : "); + + TreeTraverseInPREOrder(tree, printInteger); + + printf("\n"); + + printf("IN-Order traversal : "); + + TreeTraverseINOrder(tree, printInteger); + + printf("\n"); + + printf("POST-Order traversal : "); + + TreeTraverseInPOSTOrder(tree, printInteger); + + printf("\n"); + + printf("LEVEL-by-LEVEL traversal using a QUEUE: "); + + TreeTraverseLevelByLevelWithQUEUE(tree, printInteger); + + printf("\n"); + + printf("PRE-Order traversal using a STACK : "); + + TreeTraverseInPREOrderWithSTACK(tree, printInteger); + + printf("\n"); + + printf("IN-Order traversal using a STACK: "); + + TreeTraverseINOrderWithSTACK(tree, printInteger); + + printf("\n"); + + for (int i = 0; i < 16; i++) { + if (TreeContains(tree, i)) { + printf("The tree contains %d\n", i); + } else { + printf("The tree DOES NOT CONTAIN %d\n", i); + } + } + + printf("Multiply each value by 2\n"); + + TreeTraverseInPREOrder(tree, multiplyIntegerBy2); + + printf("PRE-Order traversal : "); + + TreeTraverseInPREOrder(tree, printInteger); + + printf("\n"); + + if (TreeEquals(tree, tree)) { + printf("The tree EQUALS ITSELF\n"); + } else { + printf("Something WRONG happened!!\n"); + } + + if (TreeMirrors(tree, tree)) { + printf("Something WRONG happened!!\n"); + } else { + printf("The tree DOES NOT MIRROR ITSELF\n"); + } + + printf("STORING in a file\n"); + + TreeStoreInFile(tree, "arvore1.txt", 1); + + printf("READING from a file\n"); + + Tree* treeFromFile = TreeGetFromFile("arvore1.txt", 1); + + printf("FINISHED READING from a file\n"); + + if (TreeEquals(tree, treeFromFile)) { + printf("The tree EQUALS the one read from file\n"); + } else { + printf("Something WRONG happened!!\n"); + } + + TreeDestroy(&tree); + + printf("The tree was DESTROYED\n"); + + if (TreeIsEmpty(tree)) { + printf("The tree is NOW EMPTY\n"); + } else { + printf("Something WRONG happened!!\n"); + } + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/IntegersBinTree.c b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/IntegersBinTree.c new file mode 100644 index 0000000..0e53308 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/IntegersBinTree.c @@ -0,0 +1,237 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from an old example... +// +// Integers Binary Tree --- SECOND VERSION --- INCOMPLETE +// + +#include "IntegersBinTree.h" + +#include +#include +#include + +#include "PointersQueue.h" +#include "PointersStack.h" + +struct _TreeNode { + ItemType item; + struct _TreeNode* left; + struct _TreeNode* right; +}; + +Tree* TreeCreate(void) { return NULL; } + +void TreeDestroy(Tree** pRoot) { + // ... +} + +int TreeIsEmpty(const Tree* root) { return root == NULL; } + +int TreeEquals(const Tree* root1, const Tree* root2) { + // ... + return 0; +} + +int TreeMirrors(const Tree* root1, const Tree* root2) { + // ... + return 0; +} + +int TreeGetNumberOfNodes(const Tree* root) { + // ... + return 0; +} + +int TreeGetHeight(const Tree* root) { + // ... + return 0; +} + +int TreeGetMin(const Tree* root) { + // ... + return 0; +} + +int TreeGetMax(const Tree* root) { + // ... + return 0; +} + +void TreeTraverseInPREOrder(Tree* root, void (*function)(ItemType* p)) { + // ... +} + +void TreeTraverseINOrder(Tree* root, void (*function)(ItemType* p)) { + // ... +} + +void TreeTraverseInPOSTOrder(Tree* root, void (*function)(ItemType* p)) { + // ... +} + +void TreeTraverseLevelByLevelWithQUEUE(Tree* root, + void (*function)(ItemType* p)) { + if (root == NULL) { + return; + } + + // Not checking for queue errors !! + // Create the QUEUE for storing POINTERS + + Queue* queue = QueueCreate(); + + QueueEnqueue(queue, root); + + while (QueueIsEmpty(queue) == 0) { + Tree* p = QueueDequeue(queue); + + function(&(p->item)); + + if (p->left != NULL) { + QueueEnqueue(queue, p->left); + } + if (p->right != NULL) { + QueueEnqueue(queue, p->right); + } + } + + QueueDestroy(&queue); +} + +void TreeTraverseInPREOrderWithSTACK(Tree* root, + void (*function)(ItemType* p)) {} + +void TreeTraverseINOrderWithSTACK(Tree* root, void (*function)(ItemType* p)) {} + +// ... + +int TreeContains(const Tree* root, const ItemType item) { + // ... + return 0; +} + +int TreeAdd(Tree** pRoot, const ItemType item) { + // ... + return 0; +} + +int TreeRemove(Tree** pRoot, const ItemType item) { + // ... + return 0; +} + +// ... + +// Storing and reading from a FILE + +struct _fileNode { + ItemType item; + int emptyLeftSubTree; + int emptyRightSubTree; +}; + +static void _storeInFile(const Tree* root, FILE* f, int fileType) { + if (root == NULL) { + return; + } + + struct _fileNode r; + r.item = root->item; + r.emptyLeftSubTree = (root->left == NULL); + r.emptyRightSubTree = (root->right == NULL); + + if (fileType == 1) { + fprintf(f, "%d %d %d ", r.item, r.emptyLeftSubTree, r.emptyRightSubTree); + } else { + fwrite(&r, sizeof(struct _fileNode), 1, f); + } + + _storeInFile(root->left, f, fileType); + _storeInFile(root->right, f, fileType); +} + +static void _getFromFile(Tree** pRoot, FILE* f, int fileType) { + struct _fileNode r; + + if (fileType == 1) { + fscanf(f, "%d", &r.item); + fscanf(f, "%d", &r.emptyLeftSubTree); + fscanf(f, "%d", &r.emptyRightSubTree); + } else { + fread(&r, sizeof(struct _fileNode), 1, f); + } + + Tree* newNode = (Tree*)malloc(sizeof(struct _TreeNode)); + + newNode->item = r.item; + + if (r.emptyLeftSubTree) { + newNode->left = NULL; + } else { + _getFromFile(&(newNode->left), f, fileType); + } + + if (r.emptyRightSubTree) { + newNode->right = NULL; + } else { + _getFromFile(&(newNode->right), f, fileType); + } + + *pRoot = newNode; +} + +int TreeStoreInFile(const Tree* root, char* fileName, int fileType) { + FILE* f = fopen(fileName, "w"); + if (f == NULL) { + return 0; + } + + _storeInFile(root, f, fileType); + + fclose(f); + return 1; +} + +Tree* TreeGetFromFile(char* fileName, int fileType) { + FILE* f = fopen(fileName, "r"); + if (f == NULL) { + return NULL; + } + + Tree* root; + _getFromFile(&root, f, fileType); + + fclose(f); + return root; +} + +// JUST FOR RUNNING EXAMPLES - REMOVE FROM THE INTERFACE + +Tree* createExampleTree(void) { + // SHOULD NEVER BE DONE LIKE THIS !!!???!!! + + int numNodes = 8; + + Tree* nodes[numNodes]; + + for (int i = 0; i < numNodes; i++) { + nodes[i] = (Tree*)malloc(sizeof(Tree)); + nodes[i]->item = i + 1; + nodes[i]->left = nodes[i]->right = NULL; + } + + nodes[3]->left = nodes[7]; + + nodes[1]->left = nodes[3]; + nodes[1]->right = nodes[4]; + + nodes[2]->left = nodes[5]; + nodes[2]->right = nodes[6]; + + nodes[0]->left = nodes[1]; + nodes[0]->right = nodes[2]; + + return nodes[0]; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/IntegersBinTree.h b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/IntegersBinTree.h new file mode 100644 index 0000000..f100726 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/IntegersBinTree.h @@ -0,0 +1,90 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from an old example... +// +// Integers Binary Tree --- SECOND VERSION --- INCOMPLETE +// + +#ifndef _INTEGERS_BINTREE_ +#define _INTEGERS_BINTREE_ + +// JUST storing integers +typedef int ItemType; + +static int NO_ITEM = -999; + +typedef struct _TreeNode Tree; + +Tree* TreeCreate(void); + +void TreeDestroy(Tree** pRoot); + +// Tree properties + +int TreeIsEmpty(const Tree* root); + +int TreeEquals(const Tree* root1, const Tree* root2); + +int TreeMirrors(const Tree* root1, const Tree* root2); + +// ... + +// Getters + +int TreeGetNumberOfNodes(const Tree* root); + +int TreeGetHeight(const Tree* root); + +ItemType TreeGetMin(const Tree* root); + +ItemType TreeGetMax(const Tree* root); + +Tree* TreeGetPointerToMinNode(const Tree* root); + +Tree* TreeGetPointerToMaxNode(const Tree* root); + +// ... + +// Recursive Traversals + +void TreeTraverseInPREOrder(Tree* root, void (*function)(ItemType* p)); + +void TreeTraverseINOrder(Tree* root, void (*function)(ItemType* p)); + +void TreeTraverseInPOSTOrder(Tree* root, void (*function)(ItemType* p)); + +// Traversals using a QUEUE or STACK + +void TreeTraverseLevelByLevelWithQUEUE(Tree* root, + void (*function)(ItemType* p)); + +void TreeTraverseInPREOrderWithSTACK(Tree* root, void (*function)(ItemType* p)); + +void TreeTraverseINOrderWithSTACK(Tree* root, void (*function)(ItemType* p)); + +// ... + +// Operations with items + +int TreeContains(const Tree* root, const ItemType item); + +int TreeAdd(Tree** pRoot, const ItemType item); + +int TreeRemove(Tree** pRoot, const ItemType item); + +// ... + +// Storing and reading from a FILE + +int TreeStoreInFile(const Tree* root, char* fileName, int fileType); + +Tree* TreeGetFromFile(char* fileName, int fileType); + +// JUST FOR RUNNING EXAMPLES - REMOVE FROM THE INTERFACE + +Tree* createExampleTree(void); + +Tree* createAnotherExampleTree(void); + +#endif // _INTEGERS_BINTREE_ diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersQueue.c b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersQueue.c new file mode 100644 index 0000000..9158b8f --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersQueue.c @@ -0,0 +1,117 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers queue (First In First Out) implementation based on an array +// of pointers +// + +#include "PointersQueue.h" + +#include +#include + +struct _PointersQueueNode { + void* data; + struct _PointersQueueNode* next; +}; + +struct _PointersQueue { + int size; // current Queue size + struct _PointersQueueNode* head; // the head of the Queue + struct _PointersQueueNode* tail; // the tail of the Queue +}; + +Queue* QueueCreate(void) { + Queue* q = (Queue*)malloc(sizeof(Queue)); + assert(q != NULL); + + q->size = 0; + q->head = NULL; + q->tail = NULL; + return q; +} + +void QueueDestroy(Queue** p) { + assert(*p != NULL); + Queue* q = *p; + + QueueClear(q); + + free(q); + *p = NULL; +} + +void QueueClear(Queue* q) { + assert(q != NULL); + + struct _PointersQueueNode* p = q->head; + struct _PointersQueueNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + q->size = 0; + q->head = NULL; + q->tail = NULL; +} + +int QueueSize(const Queue* q) { + assert(q != NULL); + return q->size; +} + +int QueueIsEmpty(const Queue* q) { + assert(q != NULL); + return (q->size == 0) ? 1 : 0; +} + +void* QueuePeek(const Queue* q) { + assert(q != NULL && q->size > 0); + return q->head->data; +} + +void QueueEnqueue(Queue* q, void* p) { + assert(q != NULL); + + struct _PointersQueueNode* aux; + aux = (struct _PointersQueueNode*)malloc(sizeof(*aux)); + assert(aux != NULL); + + aux->data = p; + aux->next = NULL; + + q->size++; + + if (q->size == 1) { + q->head = aux; + q->tail = aux; + } else { + q->tail->next = aux; + q->tail = aux; + } +} + +void* QueueDequeue(Queue* q) { + assert(q != NULL && q->size > 0); + + struct _PointersQueueNode* aux = q->head; + void* p = aux->data; + + q->size--; + + if (q->size == 0) { + q->head = NULL; + q->tail = NULL; + } else { + q->head = aux->next; + } + + free(aux); + + return p; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersQueue.h b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersQueue.h new file mode 100644 index 0000000..bfc3a6c --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersQueue.h @@ -0,0 +1,29 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Pointers queue (First In First Out) implementation based on a linked list +// + +#ifndef _POINTERS_QUEUE_ + +#define _POINTERS_QUEUE_ + +typedef struct _PointersQueue Queue; + +Queue* QueueCreate(void); + +void QueueDestroy(Queue** p); + +void QueueClear(Queue* q); + +int QueueSize(const Queue* q); + +int QueueIsEmpty(const Queue* q); + +void* QueuePeek(const Queue* q); + +void QueueEnqueue(Queue* q, void* p); + +void* QueueDequeue(Queue* q); + +#endif // _POINTERS_QUEUE_ diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersStack.c b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersStack.c new file mode 100644 index 0000000..2f3555b --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersStack.c @@ -0,0 +1,102 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers stack (First In Last Out) implementation based on an array +// of pointers +// + +#include "PointersStack.h" + +#include +#include + +struct _PointersStackNode { + void* data; + struct _PointersStackNode* next; +}; + +struct _PointersStack { + int cur_size; // current stack size + struct _PointersStackNode* top; // the node on the top of the stack +}; + +Stack* StackCreate(void) { + Stack* s = (Stack*)malloc(sizeof(Stack)); + assert(s != NULL); + + s->cur_size = 0; + s->top = NULL; + return s; +} + +void StackDestroy(Stack** p) { + assert(*p != NULL); + Stack* s = *p; + + StackClear(s); + + free(s); + *p = NULL; +} + +void StackClear(Stack* s) { + assert(s != NULL); + + struct _PointersStackNode* p = s->top; + struct _PointersStackNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + s->cur_size = 0; + s->top = NULL; +} + +int StackSize(const Stack* s) { + assert(s != NULL); + return s->cur_size; +} + +int StackIsEmpty(const Stack* s) { + assert(s != NULL); + return (s->cur_size == 0) ? 1 : 0; +} + +void* StackPeek(const Stack* s) { + assert(s != NULL && s->cur_size > 0); + return s->top->data; +} + +void StackPush(Stack* s, void* p) { + assert(s != NULL); + + struct _PointersStackNode* aux; + aux = (struct _PointersStackNode*)malloc(sizeof(*aux)); + assert(aux != NULL); + + aux->data = p; + aux->next = s->top; + + s->top = aux; + + s->cur_size++; +} + +void* StackPop(Stack* s) { + assert(s != NULL && s->cur_size > 0); + + struct _PointersStackNode* aux = s->top; + s->top = aux->next; + s->cur_size--; + + void* p = aux->data; + + free(aux); + + return p; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersStack.h b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersStack.h new file mode 100644 index 0000000..bfb78f0 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/02_IntegersBinTree_V_2/PointersStack.h @@ -0,0 +1,28 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Pointers stack (First In Last Out) implementation based on a linked list +// + +#ifndef _POINTERS_STACK_ +#define _POINTERS_STACK_ + +typedef struct _PointersStack Stack; + +Stack* StackCreate(void); + +void StackDestroy(Stack** p); + +void StackClear(Stack* s); + +int StackSize(const Stack* s); + +int StackIsEmpty(const Stack* s); + +void* StackPeek(const Stack* s); + +void StackPush(Stack* s, void* p); + +void* StackPop(Stack* s); + +#endif // _POINTERS_STACK_ diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/01_example.c b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/01_example.c new file mode 100644 index 0000000..b233803 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/01_example.c @@ -0,0 +1,104 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Integers Binary Search Tree --- INCOMPLETE +// + +#include +#include + +#include "BinarySearchTree.h" + +void printInteger(int* p) { printf("%d ", *p); } + +void multiplyIntegerBy2(int* p) { *p *= 2; } + +int main(void) { + BSTree* tree = createExampleBSTree(16); + + if (BSTreeIsBST(tree)) { + printf("Created an example BSTree\n"); + } else { + printf("The created BSTree is NOT OK\n"); + } + + if (BSTreeIsEmpty(tree)) { + printf("The created BSTree is EMPTY\n"); + } else { + printf("The created BSTree is OK\n"); + } + + printf("Number of nodes = %d\n", BSTreeGetNumberOfNodes(tree)); + + printf("Height = %d\n", BSTreeGetHeight(tree)); + + printf("SMALLEST value = %d\n", BSTreeGetMin(tree)); + + printf("LARGEST value = %d\n", BSTreeGetMax(tree)); + + printf("PRE-Order traversal : "); + + BSTreeTraverseInPREOrder(tree, printInteger); + + printf("\n"); + + printf("IN-Order traversal : "); + + BSTreeTraverseINOrder(tree, printInteger); + + printf("\n"); + + printf("POST-Order traversal : "); + + BSTreeTraverseInPOSTOrder(tree, printInteger); + + printf("\n"); + + printf("LEVEL-by-LEVEL traversal using a QUEUE: "); + + BSTreeTraverseLevelByLevelWithQUEUE(tree, printInteger); + + printf("\n"); + + printf("REMOVING some elements\n"); + + for (int i = 0; i < 25; i++) { + BSTreeRemove(&tree, i); + } + + printf("PRE-Order traversal : "); + + BSTreeTraverseInPREOrder(tree, printInteger); + + printf("\n"); + + printf("IN-Order traversal : "); + + BSTreeTraverseINOrder(tree, printInteger); + + printf("\n"); + + printf("POST-Order traversal : "); + + BSTreeTraverseInPOSTOrder(tree, printInteger); + + printf("\n"); + + printf("LEVEL-by-LEVEL traversal using a QUEUE: "); + + BSTreeTraverseLevelByLevelWithQUEUE(tree, printInteger); + + printf("\n"); + + BSTreeDestroy(&tree); + + printf("The BSTree was DESTROYED\n"); + + if (BSTreeIsEmpty(tree)) { + printf("The BSTree is NOW EMPTY\n"); + } else { + printf("Something WRONG happened!!\n"); + } + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/BinarySearchTree.c b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/BinarySearchTree.c new file mode 100644 index 0000000..165829f --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/BinarySearchTree.c @@ -0,0 +1,375 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from an old example... +// +// Integers Binary Search Tree --- INCOMPLETE +// + +#include "BinarySearchTree.h" + +#include +#include +#include + +#include "PointersQueue.h" +#include "PointersStack.h" + +struct _BSTreeNode { + ItemType item; + struct _BSTreeNode* left; + struct _BSTreeNode* right; +}; + +BSTree* BSTreeCreate(void) { return NULL; } + +void BSTreeDestroy(BSTree** pRoot) { + // ... +} + +int BSTreeIsEmpty(const BSTree* root) { return root == NULL; } + +// +// NEW - Adapted from +// https://www.geeksforgeeks.org/check-if-a-binary-tree-is-bst-simple-and-efficient-approach/ +// +int _isBST(const BSTree* root, ItemType* prevItem) { + if (root == NULL) { + return 1; + } + // IN_ORDER TRAVERSAL + if (_isBST(root->left, prevItem) == 0) { + return 0; + } + // Allow only distinct valued nodes + if (root->item <= *prevItem) { + return 0; + } + // Update prevValue to current + *prevItem = root->item; + + return _isBST(root->right, prevItem); +} +// +// NEW +// +int BSTreeIsBST(const BSTree* root) { + int prevItem = MIN_POSSIBLE; + + return _isBST(root, &prevItem); +} + +int BSTreeEquals(const BSTree* root1, const BSTree* root2) { + // ... + return 0; +} + +int BSTreeMirrors(const BSTree* root1, const BSTree* root2) { + // ... + return 0; +} + +int BSTreeGetNumberOfNodes(const BSTree* root) { + // ... + return 0; +} + +int BSTreeGetHeight(const BSTree* root) { + // ... + return 0; +} + +int BSTreeGetMin(const BSTree* root) { + // ... + return 0; +} + +int BSTreeGetMax(const BSTree* root) { + // ... + return 0; +} + +void BSTreeTraverseInPREOrder(BSTree* root, void (*function)(ItemType* p)) { + // ... +} + +void BSTreeTraverseINOrder(BSTree* root, void (*function)(ItemType* p)) { + // ... +} + +void BSTreeTraverseInPOSTOrder(BSTree* root, void (*function)(ItemType* p)) { + // ... +} + +void BSTreeTraverseLevelByLevelWithQUEUE(BSTree* root, + void (*function)(ItemType* p)) { + if (root == NULL) { + return; + } + + // Not checking for queue errors !! + // Create the QUEUE for storing POINTERS + + Queue* queue = QueueCreate(); + + QueueEnqueue(queue, root); + + while (QueueIsEmpty(queue) == 0) { + BSTree* p = QueueDequeue(queue); + + function(&(p->item)); + + if (p->left != NULL) { + QueueEnqueue(queue, p->left); + } + if (p->right != NULL) { + QueueEnqueue(queue, p->right); + } + } + + QueueDestroy(&queue); +} + +void BSTreeTraverseInPREOrderWithSTACK(BSTree* root, + void (*function)(ItemType* p)) {} + +void BSTreeTraverseINOrderWithSTACK(BSTree* root, + void (*function)(ItemType* p)) {} + +// ... + +int BSTreeContains(const BSTree* root, const ItemType item) { + // ... + return 0; +} + +// +// NEW +// +int BSTreeAdd(BSTree** pRoot, const ItemType item) { + BSTree* root = *pRoot; + + struct _BSTreeNode* new = (struct _BSTreeNode*)malloc(sizeof(*new)); + assert(new != NULL); + + new->item = item; + new->left = new->right = NULL; + + if (root == NULL) { + *pRoot = new; + return 1; + } + + struct _BSTreeNode* prev = NULL; + struct _BSTreeNode* current = root; + + while (current != NULL) { + if (current->item == item) { + free(new); + return 0; + } // Not allowed + + prev = current; + if (current->item > item) { + current = current->left; + } else { + current = current->right; + } + } + + if (prev->item > item) { + prev->left = new; + } else { + prev->right = new; + } + return 0; +} + +// +// NEW +// +void _deleteNextNode(BSTree** pRoot, ItemType* pItem) { + if ((*pRoot)->left == NULL) { + // FOUND IT + BSTree* auxPointer = *pRoot; + + *pItem = auxPointer->item; + + *pRoot = auxPointer->right; + + free(auxPointer); + } else { + _deleteNextNode(&((*pRoot)->left), pItem); + } +} + +// +// NEW +// +void _removeNode(BSTree** pPointer) { + BSTree* nodePointer = *pPointer; + + if ((nodePointer->left == NULL) && (nodePointer->right == NULL)) { + /* A LEAF node */ + + free(nodePointer); + + *pPointer = NULL; + + return; + } + + if (nodePointer->left == NULL) { + /* It has only a RIGHT sub-tree */ + + *pPointer = nodePointer->right; + + free(nodePointer); + + return; + } + + if (nodePointer->right == NULL) { + /* It has only a LEFT sub-tree */ + + *pPointer = nodePointer->left; + + free(nodePointer); + + return; + } + + /* Node has TWO CHILDREN */ + /* Replace its item with the item of the next node in-order */ + /* And remove that node */ + + _deleteNextNode(&(nodePointer->right), &(nodePointer->item)); +} + +// +// NEW - Search for the node and remove it +// with the help an auxiliary function +// +int BSTreeRemove(BSTree** pRoot, const ItemType item) { + BSTree* root = *pRoot; + + if (root == NULL) { + return 0; + } + if (root->item == item) { + _removeNode(pRoot); + return 1; + } + if (root->item > item) { + return BSTreeRemove(&(root->left), item); + } + + return BSTreeRemove(&(root->right), item); +} + +// ... + +// Storing and reading from a FILE + +struct _fileNode { + ItemType item; + int emptyLeftSubBSTree; + int emptyRightSubBSTree; +}; + +static void _storeInFile(const BSTree* root, FILE* f, int fileType) { + if (root == NULL) { + return; + } + + struct _fileNode r; + r.item = root->item; + r.emptyLeftSubBSTree = (root->left == NULL); + r.emptyRightSubBSTree = (root->right == NULL); + + if (fileType == 1) { + fprintf(f, "%d %d %d ", r.item, r.emptyLeftSubBSTree, + r.emptyRightSubBSTree); + } else { + fwrite(&r, sizeof(struct _fileNode), 1, f); + } + + _storeInFile(root->left, f, fileType); + _storeInFile(root->right, f, fileType); +} + +static void _getFromFile(BSTree** pRoot, FILE* f, int fileType) { + struct _fileNode r; + + if (fileType == 1) { + fscanf(f, "%d", &r.item); + fscanf(f, "%d", &r.emptyLeftSubBSTree); + fscanf(f, "%d", &r.emptyRightSubBSTree); + } else { + fread(&r, sizeof(struct _fileNode), 1, f); + } + + BSTree* newNode = (BSTree*)malloc(sizeof(struct _BSTreeNode)); + + newNode->item = r.item; + + if (r.emptyLeftSubBSTree) { + newNode->left = NULL; + } else { + _getFromFile(&(newNode->left), f, fileType); + } + + if (r.emptyRightSubBSTree) { + newNode->right = NULL; + } else { + _getFromFile(&(newNode->right), f, fileType); + } + + *pRoot = newNode; +} + +int BSTreeStoreInFile(const BSTree* root, char* fileName, int fileType) { + FILE* f = fopen(fileName, "w"); + if (f == NULL) { + return 0; + } + + _storeInFile(root, f, fileType); + + fclose(f); + return 1; +} + +BSTree* BSTreeGetFromFile(char* fileName, int fileType) { + FILE* f = fopen(fileName, "r"); + if (f == NULL) { + return NULL; + } + + BSTree* root; + _getFromFile(&root, f, fileType); + + fclose(f); + return root; +} + +// JUST FOR RUNNING EXAMPLES - REMOVE FROM THE INTERFACE + +// +// TO DO : change to BST +// +BSTree* createExampleBSTree(unsigned int n) { + int numNodes = 20; + + BSTree* root = BSTreeCreate(); + + for (int i = 10; i < numNodes; i += 2) { + BSTreeAdd(&root, 2 * i + 1); + } + + for (int i = 0; i < numNodes; i += 2) { + BSTreeAdd(&root, 2 * i); + } + + return root; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/BinarySearchTree.h b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/BinarySearchTree.h new file mode 100644 index 0000000..0339cce --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/BinarySearchTree.h @@ -0,0 +1,98 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from an old example... +// +// Integers Binary Search Tree --- INCOMPLETE +// + +#ifndef _BINARY_SEARCH_Tree_ +#define _BINARY_SEARCH_Tree_ + +#include + +// JUST storing integers +typedef int ItemType; + +static int NO_ITEM = INT_MAX; + +static int MIN_POSSIBLE = INT_MIN; + +typedef struct _BSTreeNode BSTree; + +BSTree* BSTreeCreate(void); + +void BSTreeDestroy(BSTree** pRoot); + +// BSTree properties + +int BSTreeIsEmpty(const BSTree* root); + +int BSTreeIsBST(const BSTree* root); + +int BSTreeEquals(const BSTree* root1, const BSTree* root2); + +int BSTreeMirrors(const BSTree* root1, const BSTree* root2); + +// ... + +// Getters + +int BSTreeGetNumberOfNodes(const BSTree* root); + +int BSTreeGetHeight(const BSTree* root); + +ItemType BSTreeGetMin(const BSTree* root); + +ItemType BSTreeGetMax(const BSTree* root); + +BSTree* BSTreeGetPointerToMinNode(const BSTree* root); + +BSTree* BSTreeGetPointerToMaxNode(const BSTree* root); + +// ... + +// Recursive Traversals + +void BSTreeTraverseInPREOrder(BSTree* root, void (*function)(ItemType* p)); + +void BSTreeTraverseINOrder(BSTree* root, void (*function)(ItemType* p)); + +void BSTreeTraverseInPOSTOrder(BSTree* root, void (*function)(ItemType* p)); + +// Traversals using a QUEUE or STACK + +void BSTreeTraverseLevelByLevelWithQUEUE(BSTree* root, + void (*function)(ItemType* p)); + +void BSTreeTraverseInPREOrderWithSTACK(BSTree* root, + void (*function)(ItemType* p)); + +void BSTreeTraverseINOrderWithSTACK(BSTree* root, + void (*function)(ItemType* p)); + +// ... + +// Operations with items + +int BSTreeContains(const BSTree* root, const ItemType item); + +int BSTreeAdd(BSTree** pRoot, const ItemType item); + +int BSTreeRemove(BSTree** pRoot, const ItemType item); + +// ... + +// Storing and reading from a FILE + +int BSTreeStoreInFile(const BSTree* root, char* fileName, int fileType); + +BSTree* BSTreeGetFromFile(char* fileName, int fileType); + +// JUST FOR RUNNING EXAMPLES - REMOVE FROM THE INTERFACE + +BSTree* createExampleBSTree(unsigned int n); + +BSTree* createAnotherExampleBSTree(void); + +#endif // _BINARY_SEARCH_Tree_ diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersQueue.c b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersQueue.c new file mode 100644 index 0000000..9158b8f --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersQueue.c @@ -0,0 +1,117 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers queue (First In First Out) implementation based on an array +// of pointers +// + +#include "PointersQueue.h" + +#include +#include + +struct _PointersQueueNode { + void* data; + struct _PointersQueueNode* next; +}; + +struct _PointersQueue { + int size; // current Queue size + struct _PointersQueueNode* head; // the head of the Queue + struct _PointersQueueNode* tail; // the tail of the Queue +}; + +Queue* QueueCreate(void) { + Queue* q = (Queue*)malloc(sizeof(Queue)); + assert(q != NULL); + + q->size = 0; + q->head = NULL; + q->tail = NULL; + return q; +} + +void QueueDestroy(Queue** p) { + assert(*p != NULL); + Queue* q = *p; + + QueueClear(q); + + free(q); + *p = NULL; +} + +void QueueClear(Queue* q) { + assert(q != NULL); + + struct _PointersQueueNode* p = q->head; + struct _PointersQueueNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + q->size = 0; + q->head = NULL; + q->tail = NULL; +} + +int QueueSize(const Queue* q) { + assert(q != NULL); + return q->size; +} + +int QueueIsEmpty(const Queue* q) { + assert(q != NULL); + return (q->size == 0) ? 1 : 0; +} + +void* QueuePeek(const Queue* q) { + assert(q != NULL && q->size > 0); + return q->head->data; +} + +void QueueEnqueue(Queue* q, void* p) { + assert(q != NULL); + + struct _PointersQueueNode* aux; + aux = (struct _PointersQueueNode*)malloc(sizeof(*aux)); + assert(aux != NULL); + + aux->data = p; + aux->next = NULL; + + q->size++; + + if (q->size == 1) { + q->head = aux; + q->tail = aux; + } else { + q->tail->next = aux; + q->tail = aux; + } +} + +void* QueueDequeue(Queue* q) { + assert(q != NULL && q->size > 0); + + struct _PointersQueueNode* aux = q->head; + void* p = aux->data; + + q->size--; + + if (q->size == 0) { + q->head = NULL; + q->tail = NULL; + } else { + q->head = aux->next; + } + + free(aux); + + return p; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersQueue.h b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersQueue.h new file mode 100644 index 0000000..bfc3a6c --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersQueue.h @@ -0,0 +1,29 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Pointers queue (First In First Out) implementation based on a linked list +// + +#ifndef _POINTERS_QUEUE_ + +#define _POINTERS_QUEUE_ + +typedef struct _PointersQueue Queue; + +Queue* QueueCreate(void); + +void QueueDestroy(Queue** p); + +void QueueClear(Queue* q); + +int QueueSize(const Queue* q); + +int QueueIsEmpty(const Queue* q); + +void* QueuePeek(const Queue* q); + +void QueueEnqueue(Queue* q, void* p); + +void* QueueDequeue(Queue* q); + +#endif // _POINTERS_QUEUE_ diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersStack.c b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersStack.c new file mode 100644 index 0000000..2f3555b --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersStack.c @@ -0,0 +1,102 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers stack (First In Last Out) implementation based on an array +// of pointers +// + +#include "PointersStack.h" + +#include +#include + +struct _PointersStackNode { + void* data; + struct _PointersStackNode* next; +}; + +struct _PointersStack { + int cur_size; // current stack size + struct _PointersStackNode* top; // the node on the top of the stack +}; + +Stack* StackCreate(void) { + Stack* s = (Stack*)malloc(sizeof(Stack)); + assert(s != NULL); + + s->cur_size = 0; + s->top = NULL; + return s; +} + +void StackDestroy(Stack** p) { + assert(*p != NULL); + Stack* s = *p; + + StackClear(s); + + free(s); + *p = NULL; +} + +void StackClear(Stack* s) { + assert(s != NULL); + + struct _PointersStackNode* p = s->top; + struct _PointersStackNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + s->cur_size = 0; + s->top = NULL; +} + +int StackSize(const Stack* s) { + assert(s != NULL); + return s->cur_size; +} + +int StackIsEmpty(const Stack* s) { + assert(s != NULL); + return (s->cur_size == 0) ? 1 : 0; +} + +void* StackPeek(const Stack* s) { + assert(s != NULL && s->cur_size > 0); + return s->top->data; +} + +void StackPush(Stack* s, void* p) { + assert(s != NULL); + + struct _PointersStackNode* aux; + aux = (struct _PointersStackNode*)malloc(sizeof(*aux)); + assert(aux != NULL); + + aux->data = p; + aux->next = s->top; + + s->top = aux; + + s->cur_size++; +} + +void* StackPop(Stack* s) { + assert(s != NULL && s->cur_size > 0); + + struct _PointersStackNode* aux = s->top; + s->top = aux->next; + s->cur_size--; + + void* p = aux->data; + + free(aux); + + return p; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersStack.h b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersStack.h new file mode 100644 index 0000000..bfb78f0 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/16_AED_Arvores_Binarias_II/03_IntegersBinSearchTree_V_1/PointersStack.h @@ -0,0 +1,28 @@ +// +// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023 +// +// Pointers stack (First In Last Out) implementation based on a linked list +// + +#ifndef _POINTERS_STACK_ +#define _POINTERS_STACK_ + +typedef struct _PointersStack Stack; + +Stack* StackCreate(void); + +void StackDestroy(Stack** p); + +void StackClear(Stack* s); + +int StackSize(const Stack* s); + +int StackIsEmpty(const Stack* s); + +void* StackPeek(const Stack* s); + +void StackPush(Stack* s, void* p); + +void* StackPop(Stack* s); + +#endif // _POINTERS_STACK_ diff --git a/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III.pdf b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III.pdf new file mode 100644 index 0000000..4f301ba Binary files /dev/null and b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III.pdf differ diff --git a/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/01_example.c b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/01_example.c new file mode 100644 index 0000000..c034f49 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/01_example.c @@ -0,0 +1,118 @@ +// +// Joaquim Madeira, May 2020 +// +// Integers AVL Tree --- INCOMPLETE +// + +#include +#include + +#include "AVLTree.h" + +void printInteger(int* p) { printf("%d ", *p); } + +void printIntegerForTreeDisplay(int* p) { printf("%d ", *p); } + +void multiplyIntegerBy2(int* p) { *p *= 2; } + +int main(void) { + AVLTree* tree = createExampleAVLTree(16); + + if (AVLTreeIsBST(tree)) { + printf("Created an example AVLTree that is a BST\n"); + } else { + printf("The created AVLTree is NOT a BST\n"); + } + + if (AVLTreeIsEmpty(tree)) { + printf("The created AVLTree is EMPTY\n"); + } else { + printf("The created AVLTree is OK\n"); + } + + printf("Number of nodes = %d\n", AVLTreeGetNumberOfNodes(tree)); + + printf("Height = %d\n", AVLTreeGetHeight(tree)); + + printf("SMALLEST value = %d\n", AVLTreeGetMin(tree)); + + printf("LARGEST value = %d\n", AVLTreeGetMax(tree)); + + printf("PRE-Order traversal : "); + + AVLTreeTraverseInPREOrder(tree, printInteger); + + printf("\n"); + + printf("IN-Order traversal : "); + + AVLTreeTraverseINOrder(tree, printInteger); + + printf("\n"); + + printf("POST-Order traversal : "); + + AVLTreeTraverseInPOSTOrder(tree, printInteger); + + printf("\n"); + + printf("LEVEL-by-LEVEL traversal using a QUEUE: "); + + AVLTreeTraverseLevelByLevelWithQUEUE(tree, printInteger); + + printf("\n"); + + AVLTreeDisplay(tree, printIntegerForTreeDisplay); + + printf("REMOVING some elements\n"); + + for (int i = 0; i < 25; i++) { + AVLTreeRemove(&tree, i); + } + + printf("PRE-Order traversal : "); + + AVLTreeTraverseInPREOrder(tree, printInteger); + + printf("\n"); + + printf("IN-Order traversal : "); + + AVLTreeTraverseINOrder(tree, printInteger); + + printf("\n"); + + printf("POST-Order traversal : "); + + AVLTreeTraverseInPOSTOrder(tree, printInteger); + + printf("\n"); + + printf("LEVEL-by-LEVEL traversal using a QUEUE: "); + + AVLTreeTraverseLevelByLevelWithQUEUE(tree, printInteger); + + printf("\n"); + + AVLTreeDestroy(&tree); + + printf("The AVLTree was DESTROYED\n"); + + if (AVLTreeIsEmpty(tree)) { + printf("The AVLTree is NOW EMPTY\n"); + } else { + printf("Something WRONG happened!!\n"); + } + + printf("Inserting the natural numbers:\n"); + + for (int i = 1; i < 13; i++) { + AVLTreeAdd(&tree, i); + printf("--\n"); + AVLTreeDisplay(tree, printIntegerForTreeDisplay); + printf("--\n"); + } + + AVLTreeStoreInFile(tree, "arvore.txt", 1); + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/AVLTree.c b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/AVLTree.c new file mode 100644 index 0000000..ce6ee08 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/AVLTree.c @@ -0,0 +1,510 @@ +// +// Joaquim Madeira, May 2020 +// +// Integers AVL Tree --- INCOMPLETE +// + +#include "AVLTree.h" + +#include +#include +#include + +#include "PointersQueue.h" +#include "PointersStack.h" + +struct _AVLTreeNode { + ItemType item; + struct _AVLTreeNode* left; + struct _AVLTreeNode* right; + int height; +}; + +AVLTree* AVLTreeCreate(void) { return NULL; } + +void AVLTreeDestroy(AVLTree** pRoot) { + // ... +} + +int AVLTreeIsEmpty(const AVLTree* root) { return root == NULL; } + +// +// NEW - Adapted from +// https://www.geeksforgeeks.org/check-if-a-binary-tree-is-bst-simple-and-efficient-approach/ +// +int _isBST(const AVLTree* root, ItemType* prevItem) { + if (root == NULL) { + return 1; + } + // IN_ORDER TRAVERSAL + if (_isBST(root->left, prevItem) == 0) { + return 0; + } + // Allow only distinct valued nodes + if (root->item <= *prevItem) { + return 0; + } + // Update prevValue to current + *prevItem = root->item; + + return _isBST(root->right, prevItem); +} +// +// NEW +// +int AVLTreeIsBST(const AVLTree* root) { + int prevItem = MIN_POSSIBLE; + + return _isBST(root, &prevItem); +} + +int AVLTreeEquals(const AVLTree* root1, const AVLTree* root2) { + // ... + return 0; +} + +int AVLTreeMirrors(const AVLTree* root1, const AVLTree* root2) { + // ... + return 0; +} + +int AVLTreeGetNumberOfNodes(const AVLTree* root) { + // ... + return 0; +} + +// +// NEW +// +int AVLTreeGetHeight(const AVLTree* root) { + if (root == NULL) return -1; + + return root->height; +} + +int AVLTreeGetMin(const AVLTree* root) { + // ... + return 0; +} + +int AVLTreeGetMax(const AVLTree* root) { + // ... + return 0; +} + +void AVLTreeTraverseInPREOrder(AVLTree* root, void (*function)(ItemType* p)) { + // ... +} + +void AVLTreeTraverseINOrder(AVLTree* root, void (*function)(ItemType* p)) { + // ... +} + +void AVLTreeTraverseInPOSTOrder(AVLTree* root, void (*function)(ItemType* p)) { + // ... +} + +void AVLTreeTraverseLevelByLevelWithQUEUE(AVLTree* root, + void (*function)(ItemType* p)) { + if (root == NULL) { + return; + } + + // Not checking for queue errors !! + // Create the QUEUE for storing POINTERS + + Queue* queue = QueueCreate(); + + QueueEnqueue(queue, root); + + while (QueueIsEmpty(queue) == 0) { + AVLTree* p = QueueDequeue(queue); + + function(&(p->item)); + + if (p->left != NULL) { + QueueEnqueue(queue, p->left); + } + if (p->right != NULL) { + QueueEnqueue(queue, p->right); + } + } + + QueueDestroy(&queue); +} + +void AVLTreeTraverseInPREOrderWithSTACK(AVLTree* root, + void (*function)(ItemType* p)) {} + +void AVLTreeTraverseINOrderWithSTACK(AVLTree* root, + void (*function)(ItemType* p)) {} + +// ... + +int AVLTreeContains(const AVLTree* root, const ItemType item) { + // ... + return 0; +} + +// Auxiliary functions for tree balancing + +static void _updateNodeHeight(AVLTree* t) { + assert(t != NULL); + + int leftHeight = AVLTreeGetHeight(t->left); + + int rightHeight = AVLTreeGetHeight(t->right); + + if (leftHeight >= rightHeight) { + t->height = leftHeight + 1; + } else { + t->height = rightHeight + 1; + } +} + +static void _singleRotateWithLeftChild(AVLTree** p) { + AVLTree* pLeft = (*p)->left; + + (*p)->left = pLeft->right; + pLeft->right = *p; + + _updateNodeHeight(*p); + _updateNodeHeight(pLeft); + + *p = pLeft; +} + +static void _singleRotateWithRightChild(AVLTree** p) { + AVLTree* pRight = (*p)->right; + + (*p)->right = pRight->left; + pRight->left = *p; + + _updateNodeHeight(*p); + _updateNodeHeight(pRight); + + *p = pRight; +} + +static void _doubleRotateWithLeftChild(AVLTree** p) { + _singleRotateWithRightChild(&(*p)->left); + _singleRotateWithLeftChild(p); +} + +static void _doubleRotateWithRightChild(AVLTree** p) { + _singleRotateWithLeftChild(&(*p)->right); + _singleRotateWithRightChild(p); +} + +static void _balanceNode(AVLTree** pRoot) { + int leftHeight, rightHeight; + + if (*pRoot == NULL) return; + leftHeight = AVLTreeGetHeight((*pRoot)->left); + rightHeight = AVLTreeGetHeight((*pRoot)->right); + + if (leftHeight - rightHeight == 2) { + leftHeight = AVLTreeGetHeight((*pRoot)->left->left); + rightHeight = AVLTreeGetHeight((*pRoot)->left->right); + if (leftHeight >= rightHeight) + _singleRotateWithLeftChild(pRoot); + else + _doubleRotateWithLeftChild(pRoot); + } else if (rightHeight - leftHeight == 2) { + rightHeight = AVLTreeGetHeight((*pRoot)->right->right); + leftHeight = AVLTreeGetHeight((*pRoot)->right->left); + if (rightHeight >= leftHeight) + _singleRotateWithRightChild(pRoot); + else + _doubleRotateWithRightChild(pRoot); + } else + (*pRoot)->height = + leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1; +} + +// +// NEW +// +int AVLTreeAdd(AVLTree** pRoot, const ItemType item) { + AVLTree* root = *pRoot; + + if (root == NULL) { + root = (struct _AVLTreeNode*)malloc(sizeof(*root)); + assert(root != NULL); + + root->item = item; + root->left = root->right = NULL; + root->height = 0; + + *pRoot = root; + return 1; + } + + if (item < root->item) { + // Try to insert on the left + if (AVLTreeAdd(&(root->left), item) == 0) { + // No success + return 0; + } + + // Unbalanced on the left ? + if (AVLTreeGetHeight(root->left) - AVLTreeGetHeight(root->right) == 2) { + if (item < root->left->item) { + _singleRotateWithLeftChild(pRoot); + } else { + _doubleRotateWithLeftChild(pRoot); + } + } + _updateNodeHeight(root); + return 1; + } else if (item > root->item) { + // Try to insert on the right + if (AVLTreeAdd(&(root->right), item) == 0) { + return 0; + } + + // Unbalanced on the right ? + if (AVLTreeGetHeight(root->right) - AVLTreeGetHeight(root->left) == 2) { + if (item > root->right->item) { + _singleRotateWithRightChild(pRoot); + } else { + _doubleRotateWithRightChild(pRoot); + } + } + _updateNodeHeight(root); + return 1; + } else { + // Not allowed + return 0; + } +} + +// +// NEW +// +void _deleteNextNode(AVLTree** pRoot, ItemType* pItem) { + if ((*pRoot)->left == NULL) { + // FOUND IT + AVLTree* auxPointer = *pRoot; + + *pItem = auxPointer->item; + + *pRoot = auxPointer->right; + + free(auxPointer); + } else { + _deleteNextNode(&((*pRoot)->left), pItem); + + _updateNodeHeight(*pRoot); + } +} + +// +// NEW +// +void _removeNode(AVLTree** pPointer) { + AVLTree* nodePointer = *pPointer; + + if ((nodePointer->left == NULL) && (nodePointer->right == NULL)) { + /* A LEAF node */ + + free(nodePointer); + + *pPointer = NULL; + + return; + } + + if (nodePointer->left == NULL) { + /* It has only a RIGHT sub-tree */ + + *pPointer = nodePointer->right; + + free(nodePointer); + + return; + } + + if (nodePointer->right == NULL) { + /* It has only a LEFT sub-tree */ + + *pPointer = nodePointer->left; + + free(nodePointer); + + return; + } + + /* Node has TWO CHILDREN */ + /* Replace its item with the item of the next node in-order */ + /* And remove that node */ + + _deleteNextNode(&(nodePointer->right), &(nodePointer->item)); +} + +// +// NEW - Search for the node and remove it +// with the help an auxiliary function +// +int AVLTreeRemove(AVLTree** pRoot, const ItemType item) { + AVLTree* root = *pRoot; + + if (root == NULL) { + return 0; + } + if (root->item == item) { + _removeNode(pRoot); + _balanceNode(pRoot); // Balance at this node + return 1; + } + if (root->item > item) { + int result = AVLTreeRemove(&(root->left), item); + if (result) { + _balanceNode(pRoot); // Balance at this node + } + return result; + } + + int result = AVLTreeRemove(&(root->right), item); + if (result) { + _balanceNode(pRoot); // Balance at this node + } + return result; +} + +// ... + +// DISPLAYING on the console + +static void _displayTree(const AVLTree* root, unsigned int level, + void (*printFunc)(ItemType* p)) { + unsigned int i; + + if (root == NULL) { + for (i = 0; i <= level; i++) printf("\t"); + printf("*\n"); + return; + } + + _displayTree(root->right, level + 1, printFunc); + + for (i = 0; i <= level; i++) printf("\t"); + + printf("%d\n", root->item); + + _displayTree(root->left, level + 1, printFunc); +} + +void AVLTreeDisplay(const AVLTree* root, void (*printFunc)(ItemType* p)) { + if (root == NULL) { + return; + } + + _displayTree(root, 0, printFunc); +} + +// Storing and reading from a FILE + +struct _fileNode { + ItemType item; + int emptyLeftSubAVLTree; + int emptyRightSubAVLTree; + int nodeHeight; +}; + +static void _storeInFile(const AVLTree* root, FILE* f, int fileType) { + if (root == NULL) { + return; + } + + struct _fileNode r; + r.item = root->item; + r.emptyLeftSubAVLTree = (root->left == NULL); + r.emptyRightSubAVLTree = (root->right == NULL); + r.nodeHeight = root->height; + + if (fileType == 1) { + fprintf(f, "%d %d %d %d ", r.item, r.nodeHeight, r.emptyLeftSubAVLTree, + r.emptyRightSubAVLTree); + } else { + fwrite(&r, sizeof(struct _fileNode), 1, f); + } + + _storeInFile(root->left, f, fileType); + _storeInFile(root->right, f, fileType); +} + +static void _getFromFile(AVLTree** pRoot, FILE* f, int fileType) { + struct _fileNode r; + + if (fileType == 1) { + fscanf(f, "%d", &r.item); + fscanf(f, "%d", &r.emptyLeftSubAVLTree); + fscanf(f, "%d", &r.emptyRightSubAVLTree); + fscanf(f, "%d", &r.nodeHeight); + } else { + fread(&r, sizeof(struct _fileNode), 1, f); + } + + AVLTree* newNode = (AVLTree*)malloc(sizeof(struct _AVLTreeNode)); + + newNode->item = r.item; + newNode->height = r.nodeHeight; + + if (r.emptyLeftSubAVLTree) { + newNode->left = NULL; + } else { + _getFromFile(&(newNode->left), f, fileType); + } + + if (r.emptyRightSubAVLTree) { + newNode->right = NULL; + } else { + _getFromFile(&(newNode->right), f, fileType); + } + + *pRoot = newNode; +} + +int AVLTreeStoreInFile(const AVLTree* root, char* fileName, int fileType) { + FILE* f = fopen(fileName, "w"); + if (f == NULL) { + return 0; + } + + _storeInFile(root, f, fileType); + + fclose(f); + return 1; +} + +AVLTree* AVLTreeGetFromFile(char* fileName, int fileType) { + FILE* f = fopen(fileName, "r"); + if (f == NULL) { + return NULL; + } + + AVLTree* root; + _getFromFile(&root, f, fileType); + + fclose(f); + return root; +} + +// JUST FOR RUNNING EXAMPLES - REMOVE FROM THE INTERFACE + +AVLTree* createExampleAVLTree(unsigned int n) { + int numNodes = 20; + + AVLTree* root = AVLTreeCreate(); + + for (int i = 10; i < numNodes; i += 2) { + AVLTreeAdd(&root, 2 * i + 1); + } + + for (int i = 0; i < numNodes; i += 2) { + AVLTreeAdd(&root, 2 * i); + } + + return root; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/AVLTree.h b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/AVLTree.h new file mode 100644 index 0000000..899d876 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/AVLTree.h @@ -0,0 +1,100 @@ +// +// Joaquim Madeira, May 2020 +// +// Integers AVL Tree --- INCOMPLETE +// + +#ifndef _AVL_Tree_ +#define _AVL_Tree_ + +#include + +// JUST storing integers +typedef int ItemType; + +static int NO_ITEM = INT_MAX; + +static int MIN_POSSIBLE = INT_MIN; + +typedef struct _AVLTreeNode AVLTree; + +AVLTree* AVLTreeCreate(void); + +void AVLTreeDestroy(AVLTree** pRoot); + +// AVLTree properties + +int AVLTreeIsEmpty(const AVLTree* root); + +int AVLTreeIsBST(const AVLTree* root); + +int AVLTreeEquals(const AVLTree* root1, const AVLTree* root2); + +int AVLTreeMirrors(const AVLTree* root1, const AVLTree* root2); + +// ... + +// Getters + +int AVLTreeGetNumberOfNodes(const AVLTree* root); + +int AVLTreeGetHeight(const AVLTree* root); + +ItemType AVLTreeGetMin(const AVLTree* root); + +ItemType AVLTreeGetMax(const AVLTree* root); + +AVLTree* AVLTreeGetPointerToMinNode(const AVLTree* root); + +AVLTree* AVLTreeGetPointerToMaxNode(const AVLTree* root); + +// ... + +// Recursive Traversals + +void AVLTreeTraverseInPREOrder(AVLTree* root, void (*function)(ItemType* p)); + +void AVLTreeTraverseINOrder(AVLTree* root, void (*function)(ItemType* p)); + +void AVLTreeTraverseInPOSTOrder(AVLTree* root, void (*function)(ItemType* p)); + +// Traversals using a QUEUE or STACK + +void AVLTreeTraverseLevelByLevelWithQUEUE(AVLTree* root, + void (*function)(ItemType* p)); + +void AVLTreeTraverseInPREOrderWithSTACK(AVLTree* root, + void (*function)(ItemType* p)); + +void AVLTreeTraverseINOrderWithSTACK(AVLTree* root, + void (*function)(ItemType* p)); + +// ... + +// Operations with items + +int AVLTreeContains(const AVLTree* root, const ItemType item); + +int AVLTreeAdd(AVLTree** pRoot, const ItemType item); + +int AVLTreeRemove(AVLTree** pRoot, const ItemType item); + +// ... + +// DISPLAYING on the console + +void AVLTreeDisplay(const AVLTree* root, void (*printFunc)(ItemType* p)); + +// Storing and reading from a FILE + +int AVLTreeStoreInFile(const AVLTree* root, char* fileName, int fileType); + +AVLTree* AVLTreeGetFromFile(char* fileName, int fileType); + +// JUST FOR RUNNING EXAMPLES - REMOVE FROM THE INTERFACE + +AVLTree* createExampleAVLTree(unsigned int n); + +AVLTree* createAnotherExampleAVLTree(void); + +#endif // _AVL_Tree_ diff --git a/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersQueue.c b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersQueue.c new file mode 100644 index 0000000..458dfa7 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersQueue.c @@ -0,0 +1,117 @@ +// +// Joaquim Madeira, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers queue (First In First Out) implementation based on an array +// of pointers +// + +#include "PointersQueue.h" + +#include +#include + +struct _PointersQueueNode { + void* data; + struct _PointersQueueNode* next; +}; + +struct _PointersQueue { + int size; // current Queue size + struct _PointersQueueNode* head; // the head of the Queue + struct _PointersQueueNode* tail; // the tail of the Queue +}; + +Queue* QueueCreate(void) { + Queue* q = (Queue*)malloc(sizeof(Queue)); + assert(q != NULL); + + q->size = 0; + q->head = NULL; + q->tail = NULL; + return q; +} + +void QueueDestroy(Queue** p) { + assert(*p != NULL); + Queue* q = *p; + + QueueClear(q); + + free(q); + *p = NULL; +} + +void QueueClear(Queue* q) { + assert(q != NULL); + + struct _PointersQueueNode* p = q->head; + struct _PointersQueueNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + q->size = 0; + q->head = NULL; + q->tail = NULL; +} + +int QueueSize(const Queue* q) { + assert(q != NULL); + return q->size; +} + +int QueueIsEmpty(const Queue* q) { + assert(q != NULL); + return (q->size == 0) ? 1 : 0; +} + +void* QueuePeek(const Queue* q) { + assert(q != NULL && q->size > 0); + return q->head->data; +} + +void QueueEnqueue(Queue* q, void* p) { + assert(q != NULL); + + struct _PointersQueueNode* aux; + aux = (struct _PointersQueueNode*)malloc(sizeof(*aux)); + assert(aux != NULL); + + aux->data = p; + aux->next = NULL; + + q->size++; + + if (q->size == 1) { + q->head = aux; + q->tail = aux; + } else { + q->tail->next = aux; + q->tail = aux; + } +} + +void* QueueDequeue(Queue* q) { + assert(q != NULL && q->size > 0); + + struct _PointersQueueNode* aux = q->head; + void* p = aux->data; + + q->size--; + + if (q->size == 0) { + q->head = NULL; + q->tail = NULL; + } else { + q->head = aux->next; + } + + free(aux); + + return p; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersQueue.h b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersQueue.h new file mode 100644 index 0000000..fd84d67 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersQueue.h @@ -0,0 +1,29 @@ +// +// Joaquim Madeira, April 2020 +// +// Pointers queue (First In First Out) implementation based on a linked list +// + +#ifndef _POINTERS_QUEUE_ + +#define _POINTERS_QUEUE_ + +typedef struct _PointersQueue Queue; + +Queue* QueueCreate(void); + +void QueueDestroy(Queue** p); + +void QueueClear(Queue* q); + +int QueueSize(const Queue* q); + +int QueueIsEmpty(const Queue* q); + +void* QueuePeek(const Queue* q); + +void QueueEnqueue(Queue* q, void* p); + +void* QueueDequeue(Queue* q); + +#endif // _POINTERS_QUEUE_ diff --git a/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersStack.c b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersStack.c new file mode 100644 index 0000000..f0e791e --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersStack.c @@ -0,0 +1,102 @@ +// +// Joaquim Madeira, April 2020 +// +// Adapted from Tomás Oliveira e Silva, AED, September 2015 +// +// Pointers stack (First In Last Out) implementation based on an array +// of pointers +// + +#include "PointersStack.h" + +#include +#include + +struct _PointersStackNode { + void* data; + struct _PointersStackNode* next; +}; + +struct _PointersStack { + int cur_size; // current stack size + struct _PointersStackNode* top; // the node on the top of the stack +}; + +Stack* StackCreate(void) { + Stack* s = (Stack*)malloc(sizeof(Stack)); + assert(s != NULL); + + s->cur_size = 0; + s->top = NULL; + return s; +} + +void StackDestroy(Stack** p) { + assert(*p != NULL); + Stack* s = *p; + + StackClear(s); + + free(s); + *p = NULL; +} + +void StackClear(Stack* s) { + assert(s != NULL); + + struct _PointersStackNode* p = s->top; + struct _PointersStackNode* aux; + + while (p != NULL) { + aux = p; + p = aux->next; + free(aux); + } + + s->cur_size = 0; + s->top = NULL; +} + +int StackSize(const Stack* s) { + assert(s != NULL); + return s->cur_size; +} + +int StackIsEmpty(const Stack* s) { + assert(s != NULL); + return (s->cur_size == 0) ? 1 : 0; +} + +void* StackPeek(const Stack* s) { + assert(s != NULL && s->cur_size > 0); + return s->top->data; +} + +void StackPush(Stack* s, void* p) { + assert(s != NULL); + + struct _PointersStackNode* aux; + aux = (struct _PointersStackNode*)malloc(sizeof(*aux)); + assert(aux != NULL); + + aux->data = p; + aux->next = s->top; + + s->top = aux; + + s->cur_size++; +} + +void* StackPop(Stack* s) { + assert(s != NULL && s->cur_size > 0); + + struct _PointersStackNode* aux = s->top; + s->top = aux->next; + s->cur_size--; + + void* p = aux->data; + + free(aux); + + return p; +} diff --git a/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersStack.h b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersStack.h new file mode 100644 index 0000000..06b91f3 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema08/17_AED_Arvores_Binarias_III/01_AVL_Tree_Storing_Integer_Values/PointersStack.h @@ -0,0 +1,28 @@ +// +// Joaquim Madeira, April 2020 +// +// Pointers stack (First In Last Out) implementation based on a linked list +// + +#ifndef _POINTERS_STACK_ +#define _POINTERS_STACK_ + +typedef struct _PointersStack Stack; + +Stack* StackCreate(void); + +void StackDestroy(Stack** p); + +void StackClear(Stack* s); + +int StackSize(const Stack* s); + +int StackIsEmpty(const Stack* s); + +void* StackPeek(const Stack* s); + +void StackPush(Stack* s, void* p); + +void* StackPop(Stack* s); + +#endif // _POINTERS_STACK_