JS Solution using Doubly Linked List
\n// T.C: \n// O(1) for init and methods other than pushMiddle(), popMiddle()\n// O(N) for pushMiddle(), popMiddle()\n// S.C: O(N) for storage \n\n// Doubly lin
```\n// T.C: \n// O(1) for init and methods other than pushMiddle(), popMiddle()\n// O(N) for pushMiddle(), popMiddle()\n// S.C: O(N) for storage \n\n// Doubly linked list node\nfunction ListNode(val, prev, next) {\n    this.val = val || 0;\n    this.prev = prev || null;\n    this.next = next || null;\n}\n\nvar FrontMiddleBackQueue = function() {\n    this.head = null;\n    this.tail = null;\n    this.len = 0;\n};\n\n/** \n * @param {number} val\n * @return {void}\n */\nFrontMiddleBackQueue.prototype.pushFront = function(val) {\n    if (this.len === 0) {\n        this.head = new ListNode(val);\n        this.tail = this.head;\n        this.len += 1;\n        return;\n    }\n    \n    let newNode = new ListNode(val);\n    newNode.next = this.head;\n    this.head.prev = newNode;\n    this.head = newNode; // the new node becomes the new head\n    this.len += 1;\n};\n\n/** \n * @param {number} val\n * @return {void}\n */\nFrontMiddleBackQueue.prototype.pushMiddle = function(val) {\n    if (this.len <= 1) {\n        this.pushFront(val);\n        return;\n    }\n    let cur = this.head;\n    for (let i = 1; i < Math.floor(this.len / 2); i++) { // we go to previous node of median\n        cur = cur.next;    \n    }\n    let newNode = new ListNode(val);\n    let next = cur.next;\n    cur.next = newNode;\n    newNode.prev = cur;\n    newNode.next = next;\n    if (next) next.prev = newNode;\n    this.len += 1;\n};\n\n/** \n * @param {number} val\n * @return {void}\n */\nFrontMiddleBackQueue.prototype.pushBack = function(val) {\n    if (this.len === 0) {\n        this.pushFront(val);\n        return;\n    }\n    \n    let newNode = new ListNode(val);\n    this.tail.next = newNode;\n    newNode.prev = this.tail;\n    this.tail = newNode; // end node becomes the new tail\n    this.len += 1;\n};\n\n/**\n * @return {number}\n */\nFrontMiddleBackQueue.prototype.popFront = function() {\n    if (this.len === 0) {\n        return -1;\n    }\n    let front = this.head;\n    let next = front.next;\n    if (next) next.prev = null;\n    this.head = next;\n    this.len -= 1;\n    return front.val;\n};\n\n/**\n * @return {number}\n */\nFrontMiddleBackQueue.prototype.popMiddle = function() {\n    if (this.len <= 2) {\n        return this.popFront();\n    }\n    let cur = this.head;\n    for (let i = 1; i < Math.ceil(this.len / 2); i++) { // we go to median node\n        cur = cur.next;    \n    }\n\n    let prev = cur.prev;\n    let next = cur.next;\n    cur.prev = null;\n    cur.next = null;\n    if (prev) prev.next = next;    \n    if (next) next.prev = prev;\n    this.len -= 1;\n    return cur.val;\n};\n\n/**\n * @return {number}\n */\nFrontMiddleBackQueue.prototype.popBack = function() {\n    if (this.len <= 1) {\n        return this.popFront();\n    }\n    let end = this.tail;\n    let prev = end.prev;\n    end.prev = null;\n    prev.next = null;\n    this.tail = prev;\n    this.len -= 1;\n    return end.val;\n};\n\n/** \n * Your FrontMiddleBackQueue object will be instantiated and called as such:\n * var obj = new FrontMiddleBackQueue()\n * obj.pushFront(val)\n * obj.pushMiddle(val)\n * obj.pushBack(val)\n * var param_4 = obj.popFront()\n * var param_5 = obj.popMiddle()\n * var param_6 = obj.popBack()\n */\n```
['JavaScript']