333 lines
10 KiB
C
333 lines
10 KiB
C
/*****************************************/
|
|
/* Implémentations des listes de sommets */
|
|
/* Utilisation d'un tuyau par liste */
|
|
/*****************************************/
|
|
|
|
#include "type_dequeue.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "error.h"
|
|
#include "type_boolarray.h"
|
|
|
|
/************************/
|
|
/* Fonctions primitives */
|
|
/************************/
|
|
|
|
/* Création */
|
|
dequeue *create_dequeue(void) {
|
|
dequeue *ptr = malloc(sizeof(dequeue));
|
|
ptr->array = malloc(sizeof(uint) * 1);
|
|
ptr->size_array = 1;
|
|
ptr->left = 0;
|
|
ptr->right = 0;
|
|
ptr->empty = true;
|
|
return ptr;
|
|
}
|
|
|
|
/* Suppression */
|
|
void delete_dequeue(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("delete_dequeue : ptr NULL");
|
|
if (ptr->array != NULL) free(ptr->array);
|
|
if (ptr != NULL) free(ptr);
|
|
ptr = NULL;
|
|
}
|
|
|
|
/* Test du vide */
|
|
bool isempty_dequeue(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("isempty_dequeue : ptr NULL");
|
|
return ptr->empty;
|
|
}
|
|
|
|
/* Vidage d'un tuyau*/
|
|
void makeempty_dequeue(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("makeempty_dequeue : ptr NULL");
|
|
if (ptr->array != NULL) free(ptr->array);
|
|
ptr->array = malloc(sizeof(uint) * 1);
|
|
ptr->size_array = 1;
|
|
ptr->left = 0;
|
|
ptr->right = 0;
|
|
ptr->empty = true;
|
|
}
|
|
|
|
/* Taille */
|
|
uint size_dequeue(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("size_dequeue : ptr NULL");
|
|
if (isempty_dequeue(ptr))
|
|
return 0;
|
|
else if (ptr->right > ptr->left)
|
|
return ptr->right - ptr->left;
|
|
else if (ptr->right == ptr->left)
|
|
return ptr->size_array;
|
|
else
|
|
return ptr->size_array - ptr->left + ptr->right;
|
|
}
|
|
|
|
/* Lecture */
|
|
uint lefread_dequeue(dequeue *ptr, uint i) {
|
|
if (ptr == NULL) ERROR("lefread_dequeue : ptr NULL");
|
|
if (isempty_dequeue(ptr)) ERROR("lefread_dequeue : ptr empty");
|
|
if (i >= size_dequeue(ptr)) ERROR("lefread_dequeue : i out of bounds");
|
|
return ptr->array[(ptr->left + i) % ptr->size_array];
|
|
}
|
|
|
|
uint rigread_dequeue(dequeue *ptr, uint i) {
|
|
if (ptr == NULL) ERROR("rigread_dequeue : ptr NULL");
|
|
if (isempty_dequeue(ptr)) ERROR("rigread_dequeue : ptr empty");
|
|
if (i >= size_dequeue(ptr)) ERROR("rigread_dequeue : i out of bounds");
|
|
return ptr->array[(ptr->right - i - 1) % ptr->size_array];
|
|
}
|
|
|
|
static void grow_dequeue(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("grow_dequeue : ptr NULL");
|
|
while (ptr->left != 0) {
|
|
int temp = ptr->array[ptr->left];
|
|
for (uint i = 0; i < ptr->size_array; i++) {
|
|
ptr->array[(ptr->left + i) % ptr->size_array] =
|
|
ptr->array[(ptr->left + i + 1) % ptr->size_array];
|
|
}
|
|
ptr->array[(ptr->left - 1) % ptr->size_array] = temp;
|
|
ptr->left--;
|
|
ptr->right = (ptr->right - 1) % ptr->size_array;
|
|
}
|
|
ptr->right = ptr->size_array;
|
|
ptr->left = 0;
|
|
ptr->size_array *= 2;
|
|
ptr->array = realloc(ptr->array, ptr->size_array * sizeof(int));
|
|
return;
|
|
}
|
|
|
|
/* Insérer */
|
|
void lefins_dequeue(uint val, dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("lefins_dequeue : ptr NULL");
|
|
if (ptr->left == ptr->right && !isempty_dequeue(ptr)) {
|
|
grow_dequeue(ptr);
|
|
}
|
|
ptr->left = (ptr->left - 1 + ptr->size_array) % ptr->size_array;
|
|
ptr->array[ptr->left] = val;
|
|
ptr->empty = false;
|
|
return;
|
|
}
|
|
|
|
void rigins_dequeue(uint val, dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("rigins_dequeue : ptr NULL");
|
|
if (ptr->left == ptr->right && !isempty_dequeue(ptr)) {
|
|
grow_dequeue(ptr);
|
|
}
|
|
ptr->array[ptr->right] = val;
|
|
ptr->right = (ptr->right + 1) % ptr->size_array;
|
|
ptr->empty = false;
|
|
return;
|
|
}
|
|
|
|
static void shrink_dequeue(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("shrink_dequeue : ptr NULL");
|
|
uint *aux = malloc((ptr->size_array / 2) * sizeof(uint));
|
|
for (uint i = 0; i < size_dequeue(ptr); i++) {
|
|
aux[i] = ptr->array[(ptr->left + i) % ptr->size_array];
|
|
}
|
|
free(ptr->array);
|
|
ptr->array = aux;
|
|
ptr->left = 0;
|
|
ptr->size_array = ptr->size_array / 2;
|
|
ptr->right = size_dequeue(ptr);
|
|
return;
|
|
}
|
|
|
|
/* Retirer */
|
|
uint lefpull_dequeue(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("lefpull_dequeue : ptr NULL");
|
|
if (isempty_dequeue(ptr)) ERROR("lefpull_dequeue : ptr empty");
|
|
int val = ptr->array[ptr->left];
|
|
ptr->left = (ptr->left + 1) % ptr->size_array;
|
|
if (size_dequeue(ptr) <= ptr->size_array / 4 && ptr->size_array > 1) {
|
|
shrink_dequeue(ptr);
|
|
}
|
|
if (ptr->left == ptr->right) ptr->empty = true;
|
|
return val;
|
|
}
|
|
|
|
uint rigpull_dequeue(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("rigpull_dequeue : ptr NULL");
|
|
if (isempty_dequeue(ptr)) ERROR("rigpull_dequeue : ptr empty");
|
|
ptr->right = (ptr->right - 1) % ptr->size_array;
|
|
int val = ptr->array[ptr->right];
|
|
if (size_dequeue(ptr) <= ptr->size_array / 4 && ptr->size_array > 1) {
|
|
shrink_dequeue(ptr);
|
|
}
|
|
if (ptr->left == ptr->right) ptr->empty = true;
|
|
return val;
|
|
}
|
|
|
|
/* Création d'une copie avec décalage */
|
|
void copy_dequeue_right(dequeue *ptr1, dequeue *ptr2, uint val) {
|
|
if (ptr1 == NULL || ptr2 == NULL) ERROR("copy_dequeue_right : ptr NULL");
|
|
if (isempty_dequeue(ptr2)) ERROR("copy_dequeue_right : ptr2 empty");
|
|
for (uint i = 0; i < size_dequeue(ptr2); i++) {
|
|
lefread_dequeue(ptr2, i);
|
|
rigins_dequeue(lefread_dequeue(ptr2, i) + val, ptr1);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Teste si un élément appartient à une dequeue*/
|
|
bool mem_dequeue(uint val, dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("mem_dequeue : ptr NULL");
|
|
for (uint i = 0; i < size_dequeue(ptr); i++) {
|
|
if (val == lefread_dequeue(ptr, i)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* Affichage */
|
|
void print_dequeue(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("print_dequeue : ptr NULL");
|
|
printf("Deque : ");
|
|
for (uint i = 0; i < size_dequeue(ptr); i++) {
|
|
printf("%d ", lefread_dequeue(ptr, i));
|
|
}
|
|
printf("\n");
|
|
return;
|
|
}
|
|
|
|
/* Tri par ordre croissant et suppression des doublons */
|
|
void sort_dequeue_norepeat(dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("sort_dequeue_norepeat : ptr NULL");
|
|
if (isempty_dequeue(ptr)) return;
|
|
if (size_dequeue(ptr) == 1) return;
|
|
for (uint i = 0; i < size_dequeue(ptr); i++) {
|
|
for (uint j = i + 1; j < size_dequeue(ptr); j++) {
|
|
if (lefread_dequeue(ptr, i) > lefread_dequeue(ptr, j)) {
|
|
int temp = lefread_dequeue(ptr, i);
|
|
ptr->array[(ptr->left + i) % ptr->size_array] =
|
|
lefread_dequeue(ptr, j);
|
|
ptr->array[(ptr->left + j) % ptr->size_array] = temp;
|
|
}
|
|
}
|
|
}
|
|
uint i;
|
|
for (i = 0; i < size_dequeue(ptr) &&
|
|
lefread_dequeue(ptr, i) != rigread_dequeue(ptr, 0);
|
|
i++) {
|
|
uint count = 0;
|
|
while (i + count < size_dequeue(ptr) &&
|
|
lefread_dequeue(ptr, i) == lefread_dequeue(ptr, i + count)) {
|
|
count++;
|
|
}
|
|
for (uint j = 1; j < count; j++) {
|
|
for (uint k = i; k < size_dequeue(ptr) - 1; k++) {
|
|
ptr->array[(ptr->left + k) % ptr->size_array] =
|
|
lefread_dequeue(ptr, k + 1);
|
|
}
|
|
}
|
|
}
|
|
ptr->right = (ptr->right - (size_dequeue(ptr) - i - 1)) % ptr->size_array;
|
|
return;
|
|
}
|
|
|
|
/*****************************************************************/
|
|
/* Fonctions spécifiques aux ensembles triés par ordre croissant */
|
|
/*****************************************************************/
|
|
|
|
bool mem_dequeue_sorted(uint val, dequeue *ptr) {
|
|
if (ptr == NULL) ERROR("mem_dequeue_sorted : ptr NULL");
|
|
if (isempty_dequeue(ptr)) return false;
|
|
int left = 0;
|
|
int right = size_dequeue(ptr) - 1;
|
|
while (left <= right) {
|
|
int mid = (left + right) / 2;
|
|
if (lefread_dequeue(ptr, mid) == val) return true;
|
|
if (lefread_dequeue(ptr, mid) < val) {
|
|
left = mid + 1;
|
|
} else {
|
|
right = mid - 1;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void merge_sorted_dequeue(dequeue *ptr1, dequeue *ptr2) {
|
|
if (ptr1 == NULL || ptr2 == NULL) ERROR("merge_sorted_dequeue : ptr NULL");
|
|
if (isempty_dequeue(ptr2)) return;
|
|
if (isempty_dequeue(ptr1)) {
|
|
copy_dequeue_right(ptr1, ptr2, 0);
|
|
return;
|
|
}
|
|
uint i = 0;
|
|
uint j = 0;
|
|
dequeue *temp = create_dequeue();
|
|
while (i < size_dequeue(ptr1) && j < size_dequeue(ptr2)) {
|
|
if (lefread_dequeue(ptr1, i) <= lefread_dequeue(ptr2, j)) {
|
|
rigins_dequeue(lefread_dequeue(ptr1, i), temp);
|
|
i++;
|
|
} else {
|
|
rigins_dequeue(lefread_dequeue(ptr2, j), temp);
|
|
j++;
|
|
}
|
|
}
|
|
while (i < size_dequeue(ptr1)) {
|
|
rigins_dequeue(lefread_dequeue(ptr1, i), temp);
|
|
i++;
|
|
}
|
|
while (j < size_dequeue(ptr2)) {
|
|
rigins_dequeue(lefread_dequeue(ptr2, j), temp);
|
|
j++;
|
|
}
|
|
makeempty_dequeue(ptr1);
|
|
copy_dequeue_right(ptr1, temp, 0);
|
|
if (temp == NULL) delete_dequeue(temp);
|
|
for (i = 0; i < size_dequeue(ptr1) &&
|
|
lefread_dequeue(ptr1, i) != rigread_dequeue(ptr1, 0);
|
|
i++) {
|
|
uint count = 0;
|
|
while (i + count < size_dequeue(ptr1) &&
|
|
lefread_dequeue(ptr1, i) == lefread_dequeue(ptr1, i + count)) {
|
|
count++;
|
|
}
|
|
for (j = 1; j < count; j++) {
|
|
for (uint k = i; k < size_dequeue(ptr1) - 1; k++) {
|
|
ptr1->array[(ptr1->left + k) % ptr1->size_array] =
|
|
lefread_dequeue(ptr1, k + 1);
|
|
}
|
|
}
|
|
}
|
|
ptr1->right =
|
|
(ptr1->right - (size_dequeue(ptr1) - i - 1)) % ptr1->size_array;
|
|
return;
|
|
}
|
|
|
|
dequeue *make_inter_sorted_dequeue(dequeue *ptr1, dequeue *ptr2) {
|
|
if (ptr1 == NULL || ptr2 == NULL)
|
|
ERROR("make_inter_sorted_dequeue : ptr NULL");
|
|
dequeue *ptr = create_dequeue();
|
|
for (uint i = 0; i < size_dequeue(ptr1); i++) {
|
|
if (mem_dequeue_sorted(lefread_dequeue(ptr1, i), ptr2)) {
|
|
rigins_dequeue(lefread_dequeue(ptr1, i), ptr);
|
|
}
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
/* Insére un nouveau sommet dans une liste */
|
|
void insert_dequeue(dequeue *ptr, uint val) {
|
|
if (ptr == NULL) ERROR("insert_dequeue : ptr NULL");
|
|
if (mem_dequeue_sorted(val, ptr)) return;
|
|
dequeue *temp = create_dequeue();
|
|
rigins_dequeue(val, temp);
|
|
merge_sorted_dequeue(ptr, temp);
|
|
}
|
|
|
|
/* Teste si deux dequeues triées s'intersectent */
|
|
bool intersec_dequeue(dequeue *ptr1, dequeue *ptr2) {
|
|
if (ptr1 == NULL || ptr2 == NULL) ERROR("intersec_dequeue : ptr NULL");
|
|
if (isempty_dequeue(ptr1) || isempty_dequeue(ptr2)) return false;
|
|
for (uint i = 0; i < size_dequeue(ptr1); i++) {
|
|
if (mem_dequeue_sorted(lefread_dequeue(ptr1, i), ptr2)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|