C Simple Solution - Easy to Understand, 100% Memory Efficient
\ntypedef struct node\n{\n    int val;\n    struct node * next;\n}Node;\n\n\ntypedef struct \n{\n  Node * front;\n  Node * rear;\n  int count;\n} FrontMiddleBac
```\ntypedef struct node\n{\n    int val;\n    struct node * next;\n}Node;\n\n\ntypedef struct \n{\n  Node * front;\n  Node * rear;\n  int count;\n} FrontMiddleBackQueue;\n\n\nFrontMiddleBackQueue* frontMiddleBackQueueCreate() \n{\n    FrontMiddleBackQueue * queue = (FrontMiddleBackQueue *)malloc(sizeof(FrontMiddleBackQueue));\n    queue->front = NULL;\n    queue->rear = NULL;\n    queue->count = 0;\n    return queue;\n}\n\nvoid frontMiddleBackQueuePushFront(FrontMiddleBackQueue* obj, int val) \n{\n    Node * new_node = (Node *)malloc(sizeof(Node));\n    new_node->val = val;\n    \n    new_node->next = obj->front;\n    obj->front = new_node;\n    \n    //Only if the insertion at front is first insertion\n    if(obj->rear == NULL)\n    {\n        obj->rear = obj->front;\n    }\n    \n    obj->count++;\n   \n}\n\nvoid frontMiddleBackQueuePushMiddle(FrontMiddleBackQueue* obj, int val) \n{\n    Node * slow_ptr = obj->front;\n    \n    if(slow_ptr == NULL)    //First element\n    {\n       Node * new_node = (Node *)malloc(sizeof(Node));\n       new_node->val = val; \n       new_node->next = NULL;\n        \n       obj->front = new_node;\n       obj->rear = new_node;\n       obj->count++;\n       return;\n    }\n    \n    else if(slow_ptr->next == NULL) //Only one element in queue\n    {\n        Node * new_node = (Node *)malloc(sizeof(Node));\n        new_node->val = val;\n        \n        obj->front = new_node;\n        new_node->next = slow_ptr;\n        obj->count++;\n        return;\n    }\n    \n    Node * prev_slow_ptr = NULL;\n    Node * fast_ptr = obj->front->next;\n    \n    while(fast_ptr != NULL)\n    {\n        prev_slow_ptr = slow_ptr;\n        slow_ptr = slow_ptr->next;\n        fast_ptr = fast_ptr->next;\n        \n        if(fast_ptr != NULL)\n            fast_ptr = fast_ptr->next;\n    }\n    \n    Node * new_node = (Node *)malloc(sizeof(Node));\n    new_node->val = val;\n    \n    prev_slow_ptr->next = new_node;\n    new_node->next = slow_ptr;   \n    \n    obj->count++;\n}\n\nvoid frontMiddleBackQueuePushBack(FrontMiddleBackQueue* obj, int val)\n{\n    Node * new_node = (Node *)malloc(sizeof(Node));\n    new_node->val = val;  \n    \n    if(obj->rear != NULL)\n    {\n        obj->rear->next = new_node; \n    }\n    else    //First Node\n    {\n        obj->front = new_node;\n    }\n    obj->rear = new_node;    \n    new_node->next = NULL;\n    \n    obj->count++;\n}\n\nint frontMiddleBackQueuePopFront(FrontMiddleBackQueue* obj) \n{\n    if(obj->front == NULL)\n        return -1;\n    \n    int ret_val = obj->front->val;    \n    Node * del_node = obj->front;    \n    obj->front = obj->front->next;\n    free(del_node);\n    \n    if(obj->front == NULL)  //Queue is empty\n    {\n        obj->rear = NULL;\n    } \n    \n    obj->count--;\n    return ret_val;\n}\n\nint frontMiddleBackQueuePopMiddle(FrontMiddleBackQueue* obj) \n{\n\n    Node * slow_ptr = obj->front;\n    int ret_val;\n    \n    if(slow_ptr == NULL)\n        return -1;\n    \n    if(slow_ptr->next == NULL)  //Only 1 element\n    {\n        printf("Here");\n        ret_val = slow_ptr->val;\n        obj->front = NULL;\n        obj->rear = NULL;\n        obj->count--;\n        free(slow_ptr);\n        return ret_val;\n    }\n    \n    Node * prev_slow_ptr = NULL;\n    Node * prev_prev_slow_ptr = NULL;\n    Node * fast_ptr = obj->front->next;\n    \n    while(fast_ptr != NULL)\n    {\n        prev_prev_slow_ptr = prev_slow_ptr;\n        prev_slow_ptr = slow_ptr;\n        slow_ptr = slow_ptr->next;\n        fast_ptr = fast_ptr->next;\n        \n        if(fast_ptr!=NULL)\n            fast_ptr = fast_ptr->next;\n    }\n    \n    if((obj->count)%2 == 0) //Even number of nodes\n    {\n        ret_val = prev_slow_ptr->val;\n        if(obj->count == 2)\n        {\n            free(prev_slow_ptr);\n            obj->front = slow_ptr;        \n        }\n        else\n        {\n            prev_prev_slow_ptr->next = slow_ptr;\n            free(prev_slow_ptr);\n        }       \n    }\n    else    //Odd number of nodes\n    {\n        ret_val = slow_ptr->val;\n        prev_slow_ptr->next = slow_ptr->next;\n        free(slow_ptr);\n    }\n    \n    obj->count--;\n    return ret_val;\n}\n\nint frontMiddleBackQueuePopBack(FrontMiddleBackQueue* obj) \n{\n    if(obj->rear == NULL)\n        return -1;\n    \n    int ret_val = obj->rear->val;\n    Node * trav_ptr = obj->front;    \n    if(trav_ptr == obj->rear)   //Only one element\n    {\n        obj->front = NULL;\n        obj->rear = NULL;\n        free(trav_ptr);\n    }\n    else\n    {\n        while(trav_ptr->next != obj->rear)\n        {\n            trav_ptr = trav_ptr->next;\n        }\n        trav_ptr->next = NULL;\n        free(obj->rear);\n        obj->rear = trav_ptr;\n    }\n    obj->count--;\n    return ret_val;\n}\n\nvoid frontMiddleBackQueueFree(FrontMiddleBackQueue* obj)\n{\n    Node * trav_ptr = obj->front;\n    Node * del_ptr = NULL;\n    \n    while(trav_ptr != NULL)\n    {\n        del_ptr = trav_ptr;\n        trav_ptr = trav_ptr->next;\n        free(del_ptr);\n    }\n    \n    obj->front = NULL;\n    obj->rear = NULL;\n    obj->count = 0;\n    \n}\n\n/**\n * Your FrontMiddleBackQueue struct will be instantiated and called as such:\n * FrontMiddleBackQueue* obj = frontMiddleBackQueueCreate();\n * frontMiddleBackQueuePushFront(obj, val);\n \n * frontMiddleBackQueuePushMiddle(obj, val);\n \n * frontMiddleBackQueuePushBack(obj, val);\n \n * int param_4 = frontMiddleBackQueuePopFront(obj);\n \n * int param_5 = frontMiddleBackQueuePopMiddle(obj);\n \n * int param_6 = frontMiddleBackQueuePopBack(obj);\n \n * frontMiddleBackQueueFree(obj);\n*/\n```
['C']