Projects/2BIT/winter-semester/IAL 1.DU/c201.c
2026-04-14 19:28:46 +02:00

254 lines
8.8 KiB
C

/* c201.c **********************************************************************
** Téma: Jednosměrný lineární seznam
**
** Návrh a referenční implementace: Petr Přikryl, říjen 1994
** Úpravy: Andrea Němcová listopad 1996
** Petr Přikryl, listopad 1997
** Přepracované zadání: Petr Přikryl, březen 1998
** Přepis do jazyka C: Martin Tuček, říjen 2004
** Úpravy: Kamil Jeřábek, září 2020
** Daniel Dolejška, září 2021
** Daniel Dolejška, září 2022
**
** Implementujte abstraktní datový typ jednosměrný lineární seznam.
** Užitečným obsahem prvku seznamu je celé číslo typu int.
** Seznam bude jako datová abstrakce reprezentován proměnnou typu List.
** Definici konstant a typů naleznete v hlavičkovém souboru c201.h.
**
** Vaším úkolem je implementovat následující operace, které spolu s výše
** uvedenou datovou částí abstrakce tvoří abstraktní datový typ List:
**
** List_Dispose ....... zrušení všech prvků seznamu,
** List_Init .......... inicializace seznamu před prvním použitím,
** List_InsertFirst ... vložení prvku na začátek seznamu,
** List_First ......... nastavení aktivity na první prvek,
** List_GetFirst ...... vrací hodnotu prvního prvku,
** List_DeleteFirst ... zruší první prvek seznamu,
** List_DeleteAfter ... ruší prvek za aktivním prvkem,
** List_InsertAfter ... vloží nový prvek za aktivní prvek seznamu,
** List_GetValue ...... vrací hodnotu aktivního prvku,
** List_SetValue ...... přepíše obsah aktivního prvku novou hodnotou,
** List_Next .......... posune aktivitu na další prvek seznamu,
** List_IsActive ...... zjišťuje aktivitu seznamu.
**
** Nemusíte ošetřovat situaci, kdy místo legálního ukazatele na seznam předá
** někdo jako parametr hodnotu NULL.
**
** Svou implementaci vhodně komentujte!
**/
#include "c201.h"
#include <stdio.h> // printf
#include <stdlib.h> // malloc, free
bool error_flag;
bool solved;
/**
* Vytiskne upozornění na to, že došlo k chybě. Nastaví error_flag na logickou 1.
* Tato funkce bude volána z některých dále implementovaných operací.
*/
void List_Error(void) {
printf("*ERROR* The program has performed an illegal operation.\n");
error_flag = true;
}
/**
* Provede inicializaci seznamu list před jeho prvním použitím (tzn. žádná
* z následujících funkcí nebude volána nad neinicializovaným seznamem).
* Tato inicializace se nikdy nebude provádět nad již inicializovaným
* seznamem, a proto tuto možnost neošetřujte. Vždy předpokládejte,
* že neinicializované proměnné mají nedefinovanou hodnotu.
*
* @param list Ukazatel na strukturu jednosměrně vázaného seznamu
*/
void List_Init( List *list ) {
list->firstElement = NULL;
list->activeElement = NULL;
list->currentLength = 0;
}
/**
* Zruší všechny prvky seznamu list a uvede seznam list do stavu, v jakém se nacházel
* po inicializaci. Veškerá paměť používaná prvky seznamu list bude korektně
* uvolněna voláním operace free.
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
**/
void List_Dispose( List *list ) {
while (list->firstElement != NULL)
{
ListElementPtr tmp = list->firstElement;
list->firstElement = list->firstElement->nextElement;
free(tmp);
}
list->activeElement = NULL;
list->currentLength = 0;
}
/**
* Vloží prvek s hodnotou data na začátek seznamu list.
* V případě, že není dostatek paměti pro nový prvek při operaci malloc,
* volá funkci List_Error().
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
* @param data Hodnota k vložení na začátek seznamu
*/
void List_InsertFirst( List *list, int data ) {
ListElementPtr newElement = (ListElementPtr) malloc(sizeof(struct ListElement));
if (newElement == NULL)
{
List_Error();
return;
}
newElement->data = data;
newElement->nextElement = list->firstElement;
list->firstElement = newElement;
list->currentLength++;
}
/**
* Nastaví aktivitu seznamu list na jeho první prvek.
* Funkci implementujte jako jediný příkaz, aniž byste testovali,
* zda je seznam list prázdný.
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
*/
void List_First( List *list ) {
list->activeElement = list->firstElement;
}
/**
* Prostřednictvím parametru dataPtr vrátí hodnotu prvního prvku seznamu list.
* Pokud je seznam list prázdný, volá funkci List_Error().
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
* @param dataPtr Ukazatel na cílovou proměnnou
*/
void List_GetFirst( List *list, int *dataPtr ) {
if (list->firstElement == NULL)
{
List_Error();
return;
}
*dataPtr = list->firstElement->data;
}
/**
* Zruší první prvek seznamu list a uvolní jím používanou paměť.
* Pokud byl rušený prvek aktivní, aktivita seznamu se ztrácí.
* Pokud byl seznam list prázdný, nic se neděje.
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
*/
void List_DeleteFirst( List *list ) {
if (list->firstElement != NULL)
{
ListElementPtr tmp = list->firstElement;
list->firstElement = list->firstElement->nextElement;
if (list->activeElement == tmp)
{
list->activeElement = NULL;
}
free(tmp);
list->currentLength--;
}
}
/**
* Zruší prvek seznamu list za aktivním prvkem a uvolní jím používanou paměť.
* Pokud není seznam list aktivní nebo pokud je aktivní poslední prvek seznamu list,
* nic se neděje.
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
*/
void List_DeleteAfter( List *list ) {
if (list->activeElement != NULL && list->activeElement->nextElement != NULL)
{
ListElementPtr tmp = list->activeElement->nextElement;
list->activeElement->nextElement = tmp->nextElement;
free(tmp);
list->currentLength--;
}
}
/**
* Vloží prvek s hodnotou data za aktivní prvek seznamu list.
* Pokud nebyl seznam list aktivní, nic se neděje!
* V případě, že není dostatek paměti pro nový prvek při operaci malloc,
* zavolá funkci List_Error().
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
* @param data Hodnota k vložení do seznamu za právě aktivní prvek
*/
void List_InsertAfter( List *list, int data ) {
if (list->activeElement != NULL)
{
ListElementPtr newElement = (ListElementPtr) malloc(sizeof(struct ListElement));
if (newElement == NULL)
{
List_Error();
return;
}
newElement->data = data;
newElement->nextElement = list->activeElement->nextElement;
list->activeElement->nextElement = newElement;
list->currentLength++;
}
}
/**
* Prostřednictvím parametru dataPtr vrátí hodnotu aktivního prvku seznamu list.
* Pokud seznam není aktivní, zavolá funkci List_Error().
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
* @param dataPtr Ukazatel na cílovou proměnnou
*/
void List_GetValue( List *list, int *dataPtr ) {
if (list->activeElement == NULL)
{
List_Error();
return;
}
*dataPtr = list->activeElement->data;
}
/**
* Přepíše data aktivního prvku seznamu list hodnotou data.
* Pokud seznam list není aktivní, nedělá nic!
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
* @param data Nová hodnota právě aktivního prvku
*/
void List_SetValue( List *list, int data ) {
if (list->activeElement != NULL)
{
list->activeElement->data = data;
}
}
/**
* Posune aktivitu na následující prvek seznamu list.
* Všimněte si, že touto operací se může aktivní seznam stát neaktivním.
* Pokud není předaný seznam list aktivní, nedělá funkce nic.
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
*/
void List_Next( List *list ) {
if (list->activeElement != NULL)
{
list->activeElement = list->activeElement->nextElement;
}
}
/**
* Je-li seznam list aktivní, vrací nenulovou hodnotu, jinak vrací 0.
* Tuto funkci je vhodné implementovat jedním příkazem return.
*
* @param list Ukazatel na inicializovanou strukturu jednosměrně vázaného seznamu
*/
int List_IsActive( List *list ) {
return list->activeElement != NULL;
}
/* Konec c201.c */