This code  provides a Tree abstraction.  I would like to finalize the code structure only in tree directory, before starting implementation, because there are multiple conditional compilations, written at the function level.User code (testing) is yet to be attempted, as it is yet to fill the functions in Tree abstraction.The main intent of this query is to finalize the code structure.The code is compiled and linked successfully./code$ ls -LR.:list  testList.c testTree.c  tree  type.h./list:arrayImpl.c  linkedListImpl.c  list.h./tree:binarySearchTree.c  binaryTree.c  lcrsImpl.c  multiWalkImpl.c  tree.htype.hThis file provides some system headers:/********* type.h ********/#ifndef TYPE_H#define TYPE_H /* Header guard */ #include<stdbool.h> #include<stddef.h> #include<stdlib.h> #include<stdio.h> #include<string.h>#endif /* TYPE_H */list.hThis is the List abstraction, re-used by Tree abstraction:/************ list.h ************//*   List is an ordered collection of homogenuous type elements(unique or duplicate).   List is not designed to have collection of heterogenuous type elements   All elements in a List are related.   List is mutable   Each element has a position.   If an element is deleted, then still the remaining elements sit in new order.   Array implementation of List   Linked implementation of List*/#ifndef LIST_H /* Header guard */#define LIST_H#includetype.h/***************** Usage-start ************/#if defined(ARRAY) || (LINKED_LIST)  /* To ensure Encapsulation(i.e., maintain invariants of array & linked list)     So, Just provide the `List` declartion, to avoid mis-use of `List`  */  typedef struct List List;#else  #error Wrong list implementation macro name !!!#endif void listInsertItem(List *, void *newItem); void *listDeleteItem(List *, int listIndex); void *listDeleteLastItem(List *); void *listDeleteFirstItem(List *); const void *listGetItem(List *, int index); /* 'index' is array index */ int listGetSize(List *); List* createList(); bool freeList(List *);#endif /* LIST_H *//***************** Usage-end ***************/arrayImpl.c/***************** arrayImpl.c **************/#includelist/list.h#if defined(ARRAY)typedef enum {DOUBLE_THE_LIST, HALF_THE_LIST}ListResizeOperation;static List *resizeList(List *, ListResizeOperation);/************ Representation - start ************/typedef struct List{  void **array;  /* Housekeeping - Array enhancement/shrink */  int lastItemPosition;  int size;}List;#define INITIAL_LIST_SIZE 50#define FIRST_ITEM_INDEX 0/********************* Representation - end ************//************* Usage - start ***************/List *createList(){    List *list = malloc(sizeof(List));    if(list != NULL){      list->array = malloc(INITIAL_LIST_SIZE*sizeof(void*));      if(list->array != NULL){        /* Is it safe to initialise zero to  array of  pointers? */        list->array = memset(list->array, 0, INITIAL_LIST_SIZE*sizeof(void *));      }else{        return NULL;      }      list->lastItemPosition = -1;      list->size = INITIAL_LIST_SIZE;      return list;    }else{      return NULL;    }}bool freeList(List *list){  if(list != NULL){    int index = 0;    while( index < list->size){      free(list->array[index]);    }    free(list->array);    free(list);    return true;  }else{    return false;  }}int listGetSize(List *list){  if(list != NULL){    return list->size;  }else{    fprintf(stderr, List is NULL\n );    return -1;  }}const void *listGetItem(List *list, int index){  if((index >=0) && (index < list->size)){    return (const void *)list->array[index];  }else{    return NULL;  }}void listInsertItem(List *arrayList, void *newItem){  /* House keeping - Enhance the array */  if(arrayList->lastItemPosition + 1 == arrayList->size){    arrayList = resizeList(arrayList, DOUBLE_THE_LIST);    if(arrayList == NULL){      fprintf(stderr, insertItem() - Unable to allocate memory \n);      exit(1);    }  }  /* Insert new element - O(1) operation */  arrayList->array[++(arrayList->lastItemPosition)] = newItem;}void *listDeleteItem(List *arrayList, int listIndex){  void *returnElement  = arrayList->array[listIndex];  /* Delete operation - O(n) operation */  for(int accumulator = listIndex; accumulator <= arrayList->lastItemPosition; accumulator++){    arrayList->array[accumulator] = arrayList->array[accumulator + 1];  }  arrayList->lastItemPosition--;  /* House keeping - Half the list */  if(arrayList->size > INITIAL_LIST_SIZE){ /* Minimum size maintained */    if((arrayList->lastItemPosition + 1) == ((arrayList->size)/2)){      arrayList = resizeList(arrayList, HALF_THE_LIST);      if(arrayList == NULL){        fprintf(stderr, deleteItem() - Unable to allocate memory \n);        exit(1);      }    }  }  return returnElement; /* User must free this element*/}void * listDeleteLastItem(List *arrayList){  return listDeleteItem(arrayList, arrayList->lastItemPosition);}void *listDeleteFirstItem(List *arrayList){  return listDeleteItem(arrayList, FIRST_ITEM_INDEX);}/******************** Usage - end *******************/linkedListImpl.c/**********linkedListImpl.c ***********/#includetype.h#if defined(LINKED_LIST)/***************** Representation - start ******************/  /* struct members are not visible to other .c files */  struct DListNode{    void *item;    struct DListNode *next;    struct DListNode *prev;  };  /* Should be used in this .c file, only, so static */  typedef struct DListNode DListNode;  static DListNode* createNode(void *);  /* struct members are not visible to other .c files */  typedef struct List{    DListNode *head;    int size; /*size attribute is not part of list definition, but quick way to help user code */  }List;#define SENTINEL_NODE_DATA_ITEM (void *)0/************ Representation - end *************//******** Usage - start **********/List *createList(){List *list = (List *)malloc(sizeof(List));if(list != NULL){  DListNode *sentinel = createNode(SENTINEL_NODE_DATA_ITEM);  list->head = sentinel;  list->head->next = list->head;  list->head->prev = list->head;  list->size = 0;  return list;}else{  return NULL;}}bool freeList(List *list){  if(list != NULL){    if(list->size > 0){      int index = 0;      DListNode *currentNode, *nextNode;      currentNode = list->head->next;      do{        nextNode = currentNode->next;        free(currentNode->item);        free(currentNode);        currentNode = nextNode;      }while(++index < list->size);      return true;    }else{      return true;    }  }else{    return false;  }}int listGetSize(List *list){  if(list != NULL){    return list->size;  }else{    fprintf(stderr, List is NULL\n );    return -1;  }}const void *listGetItem(List *list, int index){  if((index >=0) && (index < list->size)){    DListNode *node = list->head->next;    while(index-- > 0){      node = node->next;    }    return (const void *)node->item;  }else{    fprintf(stderr, Invalid index \n);    return NULL;  }}    /* O(1) operation - insert() operation */void listInsertItem(List *linkedList, void *newItem){  DListNode *newNode = createNode(newItem);  if(linkedList->size == 0){    linkedList->head->next = linkedList->head->prev = newNode;  }else{    /* Link with current last node in the linked list*/    newNode->prev = linkedList->head->prev;    linkedList->head->prev->next = newNode;    /* Link with Sentinel node */    newNode->next = linkedList->head;    linkedList->head->prev = newNode;  }}       /* O(n) - delete() operation*/void *listDeleteItem(List *linkedList, int listIndex){  int accumulator = 0;  DListNode *nodeToDelete = linkedList->head->next;  if(listIndex < linkedList->size){     while(accumulator++ < listIndex){      nodeToDelete = nodeToDelete->next;     }     nodeToDelete->prev->next = nodeToDelete->next;     nodeToDelete->next->prev = nodeToDelete->prev;     linkedList->size++;     void *item = nodeToDelete->item;     free(nodeToDelete);     return item; /* User must delete by casting to free(item); */  }else{    fprintf(stderr, deleteItem() - Invalid Index);    return NULL;  }}/* O(1) - deleteLastItem() operation */void *listDeleteLastItem(List *linkedList){  if(linkedList->size){    DListNode *nodeToDelete = linkedList->head->prev;    void *item = nodeToDelete->item;    nodeToDelete->prev->next = nodeToDelete->next;    nodeToDelete->next->prev = nodeToDelete->prev;    free(nodeToDelete);    return item; /* User must free this item,by casting, free(item) */  }else{    return NULL;  }}/* O(1) - deleteFirstItem() operation */void *listDeleteFirstItem(List *linkedList){  if(linkedList->size){    DListNode *nodeToDelete = linkedList->head->next;    void *item = nodeToDelete->item;    nodeToDelete->next->prev = nodeToDelete->prev;    nodeToDelete->prev->next = nodeToDelete->next;    free(nodeToDelete);    return item; /* User must free this item,by casting, free(item) */  }else{    return NULL;  }}/********** Usage - end *************//********** Helper function - start ****************//*    createNode() is not visible to the linker(ld)    */static DListNode *createNode(void * value){  DListNode *newNode= malloc(sizeof(DListNode));  newNode->next = newNode;  newNode->prev = newNode;  newNode->item = value;  return newNode;}/******** Helper function - end ********/#endiftree.h/*************** tree.h ***************************/#ifndef TREE_H /* Header guard */#define TREE_H#if defined(MULTI_WALK) || (BINARY_TREE_USING_ARRAY) || (BINARY_SEARCH_TREE_USING_ARRAY)  #includelist/list.h //Using array implementation#elif defined(LCRS) ||  (BINARY_TREE_USING_NODE) || (BINARY_SEARCH_TREE_USING_NODE)  #includetype.h#else  #error Invalid representation\n#endif/****************** Usage-start ************/#if defined(LCRS)  typedef struct LCRSTree Tree;#elif defined(MULTI_WALK)  typedef struct multiWalkTree Tree;#elif defined(BINARY_TREE_USING_NODE) || (BINARY_TREE_USING_ARRAY)  typedef struct BinaryTree Tree;#elif defined(BINARY_SEARCH_TREE_USING_NODE) || (BINARY_SEARCH_TREE_USING_ARRAY) typedef struct BinarySearchTree Tree;#endiftypedef void (*visitFunc)(void *);Tree * newTree(void);bool destroyTree(Tree *);#if defined(LCRS) || (MULTI_WALK) typedef void* (*parseFunc)(void *); void treeInsertItem(Tree *, void *item, parseFunc); void* treeDeleteItem(Tree *, void *item, parseFunc);#elif defined(BINARY_TREE_USING_NODE) || (BINARY_TREE_USING_ARRAY) || (BINARY_SEARCH_TREE_USING_NODE) || (BINARY_SEARCH_TREE_USING_ARRAY) void treeInsertItem(Tree *, void *item); void* treeDeleteItem(Tree *, void *item);#endifvoid preOrderTraversal(Tree*, visitFunc);void postOrderTraversal(Tree *, visitFunc);void breadthFirstTraversal(Tree *, visitFunc);void inOrderTraversal(Tree *, visitFunc);int treeGetSize(Tree *);/**************** Usage-end ******************/#endif  /* TREE_H */multiWalkImpl.c/******************* multiWalkImpl.c*************/#includetree.h#if defined(MULTI_WALK)typedef struct treeNode{  struct treeNode *parent;  void *item;  List **childList;}Node;typedef struct multiWalkTree{  Node *root;  int size;}Tree;/*  Analysis  ========  Ignoring the size of actual data, but including the size of pointer pointing  to data, multi walk tree takes more space compared to LCRS tree*/Tree * newTree(void){  return NULL;}bool destroyTree(Tree *t){  return false;}int treeGetSize(Tree *t){  return 0;}void treeInsertItem(Tree *t, void *item, parseFunc f){  return;}void* treeDeleteItem(Tree *t, void *item, parseFunc f){  return NULL;}void preOrderTraversal(Tree *t, visitFunc f){  return;}void postOrderTraversal(Tree *t, visitFunc f){  return;}void  breadthFirsTraversal(Tree *t, visitFunc f){  return;}#endiflcrsImpl.c/**********************lcrsImpl.c ***********************/#includetree.h#if defined(LCRS)  /*******************Representation-start **************/  typedef struct SiblingTreeNode{    struct SiblingTreeNode *parent;    void *item;    struct SiblingTreeNode *firstChild;    struct SiblingTreeNode *nextSibling;  }Node;  static void postOrderTraverse(Node *, visitFunc);  static void preOrderTraverse(Node *, visitFunc);  static void breadthFirstTraverse(Node *, visitFunc);  typedef struct LCRSTree{    Node *root;    int size;  }Tree;/******************Representation-end*********************//**********************Usage-start************************/Tree * newTree(void){  Tree *rootedTree = malloc(sizeof(Tree));  rootedTree->root = NULL;  rootedTree->size = 0;  return rootedTree;}bool destroyTree(Tree *t){  return false;}int treeGetSize(Tree *t){  return 0;}void *treeDeleteItem(Tree *t, void *item, parseFunc f){  return NULL;}void treeInsertItem(Tree *rootedTree, void *item, parseFunc f){  if(rootedTree->root == NULL){    Node *rootNode = malloc(sizeof(Node));    rootNode->parent = NULL;    rootNode->item = item;    rootNode->firstChild = NULL;    rootNode->nextSibling = NULL;    rootedTree->root = rootNode;    rootedTree->size = 0;  }else{  }}void preOrderTraversal(Tree *tree, visitFunc f){  preOrderTraverse(tree->root, f);}void postOrderTraversal(Tree *tree, visitFunc f){  postOrderTraverse(tree->root, f);}/*  Level-order traversal*/void breadthFirsTraversal(Tree *t, visitFunc f){  breadthFirstTraverse(t->root, f);}/**********************Usage-end ***************//***********************Helper function - start ************/static void postOrderTraverse(Node *node, visitFunc f){}static void preOrderTraverse(Node * node, visitFunc f){}static void breadthFirstTraverse(Node *n, visitFunc f){}/***************Helper function -end******************/#endifbinaryTree.c/***************binaryTree.c***************/#includetree/tree.h#if defined(BINARY_TREE_USING_ARRAY)/************* Representation-start *************/typedef struct BinaryTree{  List **array;  int size;}Tree;/**************Representation-end *****************/#elif defined(BINARY_TREE_USING_NODE)/************* Representation-start *************/typedef struct BinaryTreeNode{  void *item;  struct BinaryTreeNode *parent;  struct BinaryTreeNode *left;  struct BinaryTreeNode *right;}Node;typedef struct BinaryTree{  Node *root;  int size;}Tree;/**************Representation-end *****************/static void inOrderTraverse(Node *, visitFunc);static void postOrderTraverse(Node *, visitFunc);static void preOrderTraverse(Node *, visitFunc);static void breadthFirstTraverse(Node *, visitFunc);#endif#if defined(BINARY_TREE_USING_NODE) || (BINARY_TREE_USING_ARRAY)/******************Usage-start *****************/Tree * newTree(void){  #if defined(BINARY_TREE_USING_NODE)  #elif defined(BINARY_TREE_USING_ARRAY)  #endif  return NULL;}bool destroyTree(Tree *t){  #if defined(BINARY_TREE_USING_NODE)  #elif defined(BINARY_TREE_USING_ARRAY)  #endif  return false;}void treeInsertItem(Tree *t, void *item){  #if defined(BINARY_TREE_USING_NODE)  #elif defined(BINARY_TREE_USING_ARRAY)  #endif}void* treeDeleteItem(Tree *t, void *item){  #if defined(BINARY_TREE_USING_NODE)  #elif defined(BINARY_TREE_USING_ARRAY)  #endif  return NULL;}int treeGetSize(Tree *t){  #if defined(BINARY_TREE_USING_NODE)  #elif defined(BINARY_TREE_USING_ARRAY)  #endif  return 0;}void preOrderTraversal(Tree* t, visitFunc action){  #if defined(BINARY_TREE_USING_NODE)      preOrderTraverse(t->root, action);  #elif defined(BINARY_TREE_USING_ARRAY)  #endif  /* only iterative - no recursive approach */}void inOrderTraversal(Tree *bT, visitFunc action){  #if defined(BINARY_TREE_USING_NODE)    inOrderTraverse(bT->root, action);  #elif defined(BINARY_TREE_USING_ARRAY)  #endif}void postOrderTraversal(Tree *t, visitFunc action){  #if defined(BINARY_TREE_USING_NODE)    postOrderTraverse(t->root, action);  #elif defined(BINARY_TREE_USING_ARRAY)  #endifvoid breadthFirsTraversal(Tree *t, visitFunc action){  #if defined(BINARY_TREE_USING_NODE)    breadthFirstTraverse(t->root, action);  #elif defined(BINARY_TREE_USING_ARRAY)  #endif}/****************Usage-end ********************/#endif#if defined(BINARY_TREE_USING_NODE)/*****************Helper function-start **************/static void inOrderTraverse(Node *n, visitFunc action){}static void breadthFirstTraverse(Node *n, visitFunc action){}static void postOrderTraverse(Node *n, visitFunc action){}static void preOrderTraverse(Node *n, visitFunc action){}/*****************Helper function-end *****************/#endifbinarySearchTree.c/***************binarySearchTree.c***************/#includetree/tree.h#if defined(BINARY_SEARCH_TREE_USING_ARRAY)/************* Representation-start *************/typedef struct BinarySearchTree{  List **array;  int size;}Tree;/**************Representation-end *****************/#elif defined(BINARY_SEARCH_TREE_USING_NODE)/************* Representation-start *************/typedef struct BinarySearchTreeNode{  void *item;  struct BinaryTreeNode *parent;  struct BinaryTreeNode *left;  struct BinaryTreeNode *right;}Node;typedef struct BinarySearchTree{  Node *root;  int size;}Tree;/**************Representation-end *****************/static void inOrderTraverse(Node *, visitFunc);static void postOrderTraverse(Node *, visitFunc);static void preOrderTraverse(Node *, visitFunc);static void breadthFirstTraverse(Node *, visitFunc);#endif#if defined(BINARY_SEARCH_TREE_USING_NODE) || (BINARY_SEARCH_TREE_USING_ARRAY)/******************Usage-start *****************/Tree * newTree(void){  #if defined(BINARY_SEARCH_TREE_USING_NODE)  #elif defined(BINARY_SEARCH_TREE_USING_ARRAY)  #endif  return NULL;}bool destroyTree(Tree *t){  #if defined(BINARY_SEARCH_TREE_USING_NODE)  #elif defined(BINARY_SEARCH_TREE_USING_ARRAY)  #endif  return false;}void treeInsertItem(Tree *t, void *item){  #if defined(BINARY_SEARCH_TREE_USING_NODE)  #elif defined(BINARY_SEARCH_TREE_USING_ARRAY)  #endif}void* treeDeleteItem(Tree *t, void *item){  #if defined(BINARY_SEARCH_TREE_USING_NODE)  #elif defined(BINARY_SEARCH_TREE_USING_ARRAY)  #endif  return NULL;}int treeGetSize(Tree *t){  #if defined(BINARY_SEARCH_TREE_USING_NODE)  #elif defined(BINARY_SEARCH_TREE_USING_ARRAY)  #endif  return 0;}void preOrderTraversal(Tree* t, visitFunc action){  #if defined(BINARY_SEARCH_TREE_USING_NODE)    preOrderTraverse(t->root, action);  #elif defined(BINARY_SEARCH_TREE_USING_ARRAY)  #endif  /* only iterative - no recursive approach */}void inOrderTraversal(Tree *bT, visitFunc action){  #if defined(BINARY_SEARCH_TREE_USING_NODE)    inOrderTraverse(bT->root, action);  #elif defined(BINARY_SEARCH_TREE_USING_ARRAY)  #endif}void postOrderTraversal(Tree *t, visitFunc action){  #if defined(BINARY_SEARCH_TREE_USING_NODE)    postOrderTraverse(t->root, action);  #elif defined(BINARY_SEARCH_TREE_USING_ARRAY)  #endif}void breadthFirsTraversal(Tree *t, visitFunc action){  #if defined(BINARY_SEARCH_TREE_USING_NODE)     breadthFirstTraverse(t->root, action);  #elif defined(BINARY_SEARCH_TREE_USING_ARRAY)  #endif}/****************Usage-end ********************/#endif#if defined(BINARY_SEARCH_TREE_USING_NODE)/*****************Helper function-start **************/static void inOrderTraverse(Node *n, visitFunc action){}static void breadthFirstTraverse(Node *n, visitFunc action){}static void postOrderTraverse(Node *n, visitFunc action){}static void preOrderTraverse(Node *n, visitFunc action){}/*****************Helper function-end *****************/#endifCompilation procedure:To test Multiwalk tree using list:Sit in code folder,Run command, gcc -Wall -g -I. -DMULTI_WALK -DARRAY ./list/*.c ./tree/*.c testTree.c -o testTreeTo test Binary tree using list:Sit in code folder,Run command, gcc -Wall -g -I. -DARRAY -DBINARY_TREE_USING_ARRAY ./list/*.c ./tree/*.c testTree.c -o testTreeTo test Binary search tree using list:Sit in code folder,Run command, gcc -Wall -g -I. -DARRAY -DBINARY_SEARCH_TREE_USING_ARRAY ./list/*.c ./tree/*.c testTree.c -o testTreeTo test LCRS tree:Sit in code folder,Run command, gcc -Wall -g -I. -DLCRS ./tree/*.c testTree.c -o testTreeTo test Binary tree using node:Sit in code folder,Run command, gcc -Wall -g -I. -DBINARY_TREE_USING_NODE ./tree/*.c testTree.c -o testTreeTo test Binary search tree using node:Sit in code folder,Run command, gcc -Wall -g -I. -DBINARY_SEARCH_TREE_USING_NODE ./tree/*.c testTree.c -o testTreeUsers of Tree abstraction:Priority queue can be implemented efficiently using LCRS implementation of N-ary tree (N <= 2). State propagation tree, shown here, can be implemented using multi walk tree Ordered data can be maintained by a binary search tree Expression trees can be implemented using a binary tree Questions:Does the code structure that involves conditional compilation, at function level, looks maintainable? If no, can the code get further structured that minimizes conditional compilations?As per this declaration, void inOrderTraversal(Tree *, visitFunc); inOrder traversal is applied on N-ary tree(N>2). As per this answer, does it practically make sense to apply on other than a binary tree?Further, PriorityQueue abstraction code will not be part of tree directory, by definition. It will sit in codedirectory. Please confirm the correction of this approach.Note: After review of code structure, implementation of the functions would continue. Complete code is here .
Tree abstraction
c;array;linked list;tree;binary search