
/*
 * Robocza implementacja stosu. Funkcje tutaj zdefiniowane moga sie przydac.
 * Podstawowe sposoby uzycia:
 *   Stack *S;
 *   S = createStack( dane... );    (utworzenie stosu i wstawienie pierwszych danych)
 *   S = pushStack( S, dane );      (dodanie elementu)
 *   dane = popStack( &S );         (zdjecie elementu z wierzcholka)
 *   freeStack( &S );               (usuniecie calego stosu)
 *
 * Graficznie stos mozna przestawic tak:
 *
 *  <____> S->head    (glowa stosu, jedyny dostepny element)
 *  <____>            (kolejny element)
 *  <____>            (dno stosu)
 *  <null>
 *
 * Dodatkowo, ta wersja stosu jest obudowana przez strukture pamietajaca liczbe
 * wstawianych na stos elementow, dzieki czemu w kazdej chwili znamy rozmiar stosu.
 *
 * [c] piotao, 20051105
 */

#ifndef __STOS__
#define __STOS__

#include <stdlib.h>

typedef float NodeData;  // typ danych przechowywanych przez stos

const NodeData ZERO = { 0.00 };  // pusta wartosc zgodna z typem danych w stosie (dla pop na pustym)

typedef struct StackNode {        // struktura definiuje jeden wezel stosu
	NodeData data;                 // element danych (moze byc rozny)
	struct StackNode *next;       // wskaznik na nastepny element
} StackNode;

typedef struct {   // 'nosnik' stosu, struktura obudowujaca
	int size;                      // rozmiar stosu
	StackNode *head;              // glowa stosu
} Stack;                       // ... wszystko to ma nazywac sie 'Stos'


// zrobienie nowego, pustego wezla stosu
// n = newNode();
StackNode *newNode(){
	return (StackNode*) malloc( sizeof( StackNode ) );
}

// obliczenie liczby wezlow w stosie
// int s = sizeStack(S);
int sizeStack(Stack *stack){
	StackNode *tmp;
	int size = 0;
	if(stack != NULL){
		tmp = stack->head;
		while( tmp != NULL ){
			size++;
			tmp = tmp->next;
		}
	}
	return size;
}

// zrobienie nowego, pustego stosu (czyli struktury obudowujacej, nosnika)
// s = newStack( NULL );
Stack *newStack( StackNode *head ){
	Stack *S = (Stack*) malloc( sizeof( Stack ) );
	S->head = head;
	S->size = sizeStack( S );
	return S;
}

// wypelnienie wezla danymi (ustawienie danych oraz pola ->next)
// n = defNode( n, data, next_n );
StackNode *defNode( StackNode *node, NodeData data, StackNode *nextNode ){
	if(node != NULL){
		node->data = data;
		node->next = nextNode;
	}
	return node;
}

// utworzenie nowego wezla z danymi w jednym kroku
// S = createStack( data );
Stack *createStack( NodeData data ){
	return newStack( defNode( newNode(), data, NULL ) );
}

// dodanie elementu do stosu
// S = pushStack( S, data );
Stack *pushStack( Stack *stack, NodeData data ){
	StackNode *tmp;
	if(stack == NULL){
		return newStack( defNode( newNode(), data, NULL ) );
	}
	else{
		tmp = defNode( newNode(), data, stack->head );
		stack->head = tmp;
		stack->size++;
	}
	return stack;
}

// pobranie danych z usunieciem elementu
// float x = popStack( &S );
NodeData popStack( Stack **stack ){
	StackNode *tmp;
	NodeData n;
	if(stack != NULL && *stack != NULL){
		if((*stack)->head != NULL){
			tmp = (*stack)->head;
			(*stack)->head = (*stack)->head->next;
			(*stack)->size--;
			n = tmp->data;
			free(tmp);
			if((*stack)->size == 0){  // zwolnienie pamieci zajmowanej przez pojemnik na stos
				free(*stack);
				*stack = NULL;
			}
			return n;
		}
		else{
			return ZERO;
		}
	}
	else{
		return ZERO;
	}
}

// usuniecie calego stosu
// freeStack(&S);
void freeStack(Stack **stack){
	StackNode *tmp,*clr;
	if(stack != NULL && *stack != NULL){
		tmp = (*stack)->head;
		while( tmp != NULL ){
			clr = tmp->next;
			free(tmp);
			tmp = clr;
		}
		free(*stack);
		*stack = NULL;
	}
}



#endif

