[AED] Restructure

Signed-off-by: TiagoRG <tiago.rgarcia@ua.pt>
This commit is contained in:
Tiago Garcia 2023-11-14 00:52:40 +00:00
parent 0df8b9f032
commit 59da5dd695
Signed by: TiagoRG
GPG Key ID: DFCD48E3F420DB42
103 changed files with 5945 additions and 0 deletions

3
.gitignore vendored
View File

@ -5,6 +5,9 @@
# Config files
/**/*.iml
# Data files
/**/*.dat
# Output/Cache files
/**/out/
/**/__pycache__/

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,137 @@
//
// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre
//
// J. Madeira - Outubro 2023
//
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -0,0 +1,125 @@
//
// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre
//
// J. Madeira - Outubro 2023
//
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#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);
}

View File

@ -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

View File

@ -0,0 +1,61 @@
//
// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre
//
// J. Madeira - Outubro 2023
//
#include <assert.h>
#include <stdio.h>
#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;
}

View File

@ -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 <stdio.h>
#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;
}

View File

@ -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 <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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 <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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 <assert.h>
#include <stdlib.h>
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)];
}

View File

@ -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_

View File

@ -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

View File

@ -0,0 +1,137 @@
//
// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre
//
// J. Madeira - Outubro 2023
//
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -0,0 +1,125 @@
//
// Algoritmos e Estruturas de Dados - 2023/2024 - 1o semestre
//
// J. Madeira - Outubro 2023
//
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#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);
}

View File

@ -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 <assert.h>
#include <stdlib.h>
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)];
}

View File

@ -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_

View File

@ -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

View File

@ -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 <assert.h>
#include <stdlib.h>
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];
}

View File

@ -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_

View File

@ -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 <assert.h>
#include <stdlib.h>
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];
}

View File

@ -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_

View File

@ -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 !!

View File

@ -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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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

View File

@ -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 <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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 <assert.h>
#include <stdlib.h>
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;
}

View File

@ -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_

View File

@ -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 <assert.h>
#include <stdlib.h>
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;
}

View File

@ -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_

View File

@ -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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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 <assert.h>
#include <stdlib.h>
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) {}

View File

@ -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_

View File

@ -0,0 +1,4 @@
1 - Complete the missing functions on the .c file
2 - Redo the previous application examples !!

View File

@ -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

View File

@ -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 <assert.h>
#include <stdlib.h>
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) {}

View File

@ -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_

View File

@ -0,0 +1,3 @@
Complete the missing functions on the .c file

View File

@ -0,0 +1,76 @@
///
// Joaquim Madeira, April 2020
//
// TESTING the TAD SORTED LIST implementation
//
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -0,0 +1,74 @@
///
// Joaquim Madeira, April 2020
//
// TESTING the TAD SORTED LIST implementation
//
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -0,0 +1,139 @@
#include "Date.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
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 a<b.
int DateCompare(const Date* a, const Date* b) {
int r = (int)a->year - (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;
}

View File

@ -0,0 +1,36 @@
#ifndef _DATE_
#define _DATE_
#include <inttypes.h>
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_

View File

@ -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 <assert.h>
#include <stdlib.h>
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;
}
}

View File

@ -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_

View File

@ -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 <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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 <assert.h>
#include <stdlib.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;
}
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];
}

View File

@ -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_

View File

@ -0,0 +1,128 @@
//
// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023
//
// Integers Binary Tree --- SECOND VERSION --- INCOMPLETE
//
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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];
}

View File

@ -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_

View File

@ -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 <assert.h>
#include <stdlib.h>
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;
}

View File

@ -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_

View File

@ -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 <assert.h>
#include <stdlib.h>
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;
}

View File

@ -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_

View File

@ -0,0 +1,104 @@
//
// Joaquim Madeira, Algoritmos e Estruturas de Dados, November 2023
//
// Integers Binary Search Tree --- INCOMPLETE
//
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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 <limits.h>
// 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_

View File

@ -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 <assert.h>
#include <stdlib.h>
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;
}

View File

@ -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_

View File

@ -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 <assert.h>
#include <stdlib.h>
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;
}

View File

@ -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_

View File

@ -0,0 +1,118 @@
//
// Joaquim Madeira, May 2020
//
// Integers AVL Tree --- INCOMPLETE
//
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -0,0 +1,510 @@
//
// Joaquim Madeira, May 2020
//
// Integers AVL Tree --- INCOMPLETE
//
#include "AVLTree.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -0,0 +1,100 @@
//
// Joaquim Madeira, May 2020
//
// Integers AVL Tree --- INCOMPLETE
//
#ifndef _AVL_Tree_
#define _AVL_Tree_
#include <limits.h>
// 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_

View File

@ -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 <assert.h>
#include <stdlib.h>
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;
}

Some files were not shown because too many files have changed in this diff Show More