#include <stdio.h>
#include <stdlib.h>
#include "ilist_destructive.h"
// The ilist ADT is a pointer to this secret struct
struct ilist_ADT {
struct ilist_ADT * rest;
int first;
int length;
struct ilist_ADT * last;
};
ilist iempty(){
return NULL;
}
int iempty_huh(ilist il){
return il == iempty();
}
int ifirst(ilist il){
return il->first;
}
ilist icons_destroy(int in, ilist il){
if(iempty_huh(il)) {
ilist end = malloc(sizeof(struct ilist_ADT));
end->rest = iempty();
end->length = 1;
end->first = in;
end->last = end;
return end;
}
ilist temp = malloc(sizeof(struct ilist_ADT));
temp->length = il->length;
temp->first = il->first;
temp->rest = il->rest;
temp->last = il->last;
il->last = temp->last;
il->length = ilength(il) + 1;
il->rest = temp;
il->first = in;
return il;
}
// returns an ilist with in added as the first element of il
// references to il cease to be valid ilists
// the result must eventually be consumed by one of:
// icons_destroy, irest_destroy, idelete
ilist irest_destroy(ilist il){
ilist temp = il->rest;
free (il);
return temp;
}
// modifies il to remove the first element, and returns the modified ilist
// frees the memory associated with the first element
// references to il cease to be valid ilists
// the result (if non-empty) must eventually be consumed by one of:
// icons_destroy, irest_destroy, idelete
ilist icopy(ilist il){
if (il== iempty())
{return iempty();}
ilist head = malloc (sizeof(struct ilist_ADT));
head->first = il->first;
head->length = il->length;
head->rest = iempty();
ilist lstend = head;
for (ilist a = il->rest; a!=iempty(); a = a->rest){
ilist temp = malloc (sizeof(struct ilist_ADT));
temp->first = a->first;
temp->length = a->length;
temp->rest = iempty();
lstend->rest = temp;
lstend = temp;
}
return head;
}
// returns a new copy of il that continues to be a valid
// ilist with the same elements even when il is destroyed
// the result must eventually be consumed by one of:
// icons_destroy, irest_destroy, idelete
int ilength(ilist il)
{
if (iempty_huh(il))
{
return 0;
}
else
{
return il->length;
}
}
// computes the number of elements in il
void idelete(ilist il){
while (il != iempty()) {
ilist next = il->rest;
free(il);
il = next;
}
}
// frees the storage for ilist
// all further references to il become invalid
// NOTE: every ilist created by icons_destroy or
// irest_destroy or icopy must eventually be destroyed
// by being consumed by icons_destroy or
// irest_destroy or idelete
ilist iappend_destroy (ilist il1, ilist il2){
if (iempty_huh(il1)){
return il2;
}
if (iempty_huh(il2)){
return il1;
}
if (il1 == il2){
il2 = icopy(il1);
}
il1->last->rest = il2;
return il1;
}