[C language] stack and queue

Keywords: C C++ Algorithm data structure

The code in this paper is basically implemented by C language, except for the code implementation of "2.3.4 Leetcode496".

1. Queue

1.1 nature of queue

FIFO: first in, first out.
The team goes out first and the team goes out at the end.

1.2 general queue

1.2.1 code implementation of ordinary queue

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//Normal queue, false overflow problem


typedef struct Queue {
    int *data;
    int head, tail;
    int capacity;
} Queue;


/*
 * Queue initialization 
 */
Queue *init(int n) {
    Queue *que = (Queue *)malloc(sizeof(Queue));
    que->data = (int *)malloc(sizeof(int) * n);
    que->head = 0;
    que->tail = 0;
    que->capacity = n;
    return que;
}

/*
 * Returns the first element of the queue
 */
int front(Queue *que) {
    return que->data[que->head];
}

/*
 * Determine whether the queue is empty
 */
int empty(Queue *que) {
    return que->head == que->tail;
}

/*
 * Join the team
 */
int push(Queue *que, int val) {
    if (que == NULL) return -1;
    if (que->tail == que->capacity) { //Determine whether the queue is full
        return -1;
    }
    que->data[que->tail++] = val;//Join the team first and then update the tail value
    return 0;
}

/*
 * Out of the team
 */
int pop(Queue *que) {
    if (que == NULL) return -1;
    if (empty(que)) return -1;
    que->head++;
    return 0;
}

/*
 * Printing of queue elements
 */
void output(Queue *que) {
    printf("Queue : [");
    for (int i = que->head, j = 0; i < que->tail; i++, j++) {
        j && printf(", ");
        printf("%d", que->data[i]);
    }
    printf("]\n");
    return ;
}

/*
 * Queue destruction
 */
void clear(Queue *que) {
    if (que == NULL) return ;
    free(que->data);
    free(que);
    return ;
}

int main() {
    srand(time(0));
    #define max_op 20
    Queue *que = init(max_op);
    for (int i = 0; i < max_op * 2; i++) {
        int val = rand() % 100;
        int op = rand() % 4;
        switch (op) {
            case 0:
            case 1:
            case 2: {
                printf("push %d to the Queue, result = %d\n", val, push(que, val));
            } break;
            case 3: {
                printf("pop %d from the Queue, result = %d\n", front(que), pop(que));
            } break;
        }
        output(que), printf("\n");
    }
    #undef max_op
    clear(que);

    return 0;
}

1.2.2 common queue problems

Existing problem: false overflow.
Reason: when entering the queue, it is to judge whether the tail reaches capacity - 1. If tail = capacity - 1, it has reached the maximum capacity of the whole queue logically, but if there is an out of queue operation before, it can actually be inserted before the queue.

1.3 circular queue

In order to solve the false overflow problem of ordinary queues, circular queues appear.
Because head is not necessarily in front of tail, a new variable count is defined to record the number of elements actually stored in the circular queue.

1.3.1 code implementation of circular queue

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define COLOR(a, b) "\033[;" #b "m" a "\033[0m"
#define RED(a) COLOR(a, 31)

typedef struct Queue {
    int *data;
    int head;
    int tail;
    int count; //Record the number of elements that have been stored in the queue
    int capacity;
} Queue;

/*
 * Queue initialization
 */
Queue *init(int n) {
    Queue *que = (Queue *)malloc(sizeof(Queue));
    que->data = (int *)malloc(sizeof(int) * n);
    que->head = 0;
    que->tail = 0;
    que->count = 0;
    que->capacity = n;
    return que;
}

/*
 * Returns the first element of the queue
 */
int front(Queue *que) {
    return que->data[que->head];
}

/*
 * Determine whether the queue is empty
 */
int empty(Queue *que) {
    return que->count == 0;
}

/*
 * Join the team
 */
int push(Queue *que, int val) {
    if (que == NULL) return -1;
    if (que->count == que->capacity) {
        printf(RED("Queue is full!")"\n");
        return -1;
    }
    que->data[que->tail++] = val;
    if (que->tail == que->capacity) que->tail = 0;
    que->count++;
    return 0;
}

/*
 * Out of the team
 */
int pop(Queue *que) {
    if (que == NULL) return -1;
    if (empty(que)) return -1;
    que->head++;
    if (que->head == que->capacity) que->head = 0;
    que->count--;
    return 0;
}

/*
 * Printing of queue elements
 */
void output(Queue *que) {
    printf("Queue : [");
    for (int i = que->head, j = 0; j < que->count; j++, i++) {
        j && printf(", ");
        printf("%d", que->data[i % que->capacity]);
    }
    printf("]\n");
    return ;
}

/*
 * Queue destruction
 */
void clear(Queue *que) {
    if (que == NULL) return ;
    free(que->data);
    free(que);
    return ;
}

int main() {
    srand(time(0));
    #define max_op 20 
    Queue *que = init(max_op / 2);
    for (int i = 0; i < max_op; i++) {
        int val = rand() % 100;
        int op = rand() % 4;
        switch (op) {
            case 0:
            case 1:
            case 2: {
                printf("push %d to the Queue, result = %d\n", val, push(que, val));
            } break;
            case 3: {
                printf("pop %d from the Queue, result = %d\n", front(que), pop(que));
            } break;
        }
        output(que), printf("\n");
    }
    #undef max_op 
    clear(que);

    return 0;
}

1.3.2 shortage of circular queue

The currently implemented circular queue cannot be expanded. When the circular queue is full, it is not possible to insert elements.

1.3.3 cyclic queue expansion

realloc is not recommended for cyclic queue expansion, because the head pointing to the first element of the queue is not necessarily in front of the tail pointing to the end element. The cyclic queue is output in strict order from head to tail, but their order in memory layout is not certain.

malloc or calloc is recommended. When the development is successful, copy it to the new space according to the original order of the circular queue, and then actively release the original space.

int expand(Queue *q) { //Queue expansion operation
    int extr_size = q->length;
    int *p;
    while (extr_size) {
        p = (int *)malloc(sizeof(int) * (q->length + extr_size));
        if (p) break;
        extr_size /= 2;
    }
    if (p == NULL) return 0;
    //The values in the original queue are copied to the new space, copied from the element at the head, and the values at the original head are placed at the 0 subscript of the new space
    for (int i = q->head, j = 0; j < q->count; j++) {
        p[j] = q->data[(i + j) % q->length];
    }
    free(q->data);
    q->data = p;
    q->length += extr_size;
    q->head = 0;
    q->tail = q->count;
    return 1;
}

//Join the team
int push(Queue *q, int val) {
    if (q == NULL) return 0;
    if (q->count == q->length) { //Judge whether the queue is full, and expand the capacity when it is full
        if (!expand(q)) return 0;
        printf(GREEN("Expand sucessfully!Queue->size(%d)") "\n", q->length);
    }
    //Join the team first, and then update the value of tail
    q->data[q->tail++] = val;
    if (q->tail == q->length) q->tail = 0;
    q->count++;
    return 1;
}

Full code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define COLOR(a, b) "\033[" #b "m" a "\033[0m"
#define RED(a) COLOR(a, 31)
#define GREEN(a) COLOR(a, 32)

typedef struct Queue {
    int *data;
    int head;
    int tail;
    int count;
    int capacity;
} Queue;

/*
 * Queue initialization
 */
Queue *init(int n) {
    Queue *que = (Queue *)malloc(sizeof(Queue));
    que->data = (int *)malloc(sizeof(int) * n);
    que->head = 0;
    que->tail = 0;
    que->count = 0;
    que->capacity = n;
    return que;
}

/*
 * Determine whether the queue is empty
 */
int empty(Queue *que) {
    return que->count == 0;
}

/*
 * Get team leader element
 */
int front(Queue *que) {
    return que->data[que->head];
}

/*
 * Queue expansion
 */
int expand(Queue *que) {
    int extra_size = que->capacity;
    int *p;
    while (extra_size) {
        p = (int *)malloc(sizeof(int) * (que->capacity + extra_size));
        if (p) break;
        extra_size /= 2;
    }
    if (p == NULL) return -1;
    for (int i = que->head, j = 0; j < que->count; i++, j++) {
        p[j] = que->data[(i + j) % que->capacity]; 
    }
    free(que->data);
    que->data = p;
    que->capacity += extra_size;
    que->head = 0;
    que->tail = que->count;
    return 0;
}

/*
 * Join the team
 */
int push(Queue *que, int val) {
    if (que == NULL) return -1;
    if (que->count == que->capacity) { //If the queue is full, perform capacity expansion
        if (expand(que) == -1) {
            printf(RED("Expand queue fail!")"\n");
            return -1;
        }
        printf(GREEN("Expand queue successfully! Queue->capacity(%d)") "\n", que->capacity);
    }
    que->data[que->tail++] = val;
    if (que->tail == que->capacity) que->tail = 0;
    que->count++;
    return 0;
}

/*
 * Out of the team
 */
int pop(Queue *que) {
    if (que == NULL) return -1;
    if (empty(que)) return -1;
    que->head++;
    if (que->head == que->capacity) que->head = 0;
    que->count--;
    return 0;
}

/*
 * Printing of queue elements
 */
void output(Queue *que) {
    printf("Queue : [");
    for (int i = que->head, j = 0; j < que->count; i++, j++) {
        j && printf(", ");
        printf("%d", que->data[i % que->capacity]);
    }
    printf("]\n");
    return ;
}

/*
 * Queue destruction
 */
void clear(Queue *que) {
    if (que == NULL) return ;
    free(que->data);
    free(que);
    return ;
}


int main() {
    srand(time(0));
    #define max_op 20 
    Queue *que = init(max_op / 4);
    for (int i = 0; i < max_op; i++) {
        int val = rand() % 100;
        int op = rand() % 4;
        switch (op) {
            case 0:
            case 1:
            case 2: {
                printf("push %d to the Queue, reuslt = %d\n", val, push(que, val));
            } break;
            case 3: {
                printf("pop %d from the Queue, result = %d\n", front(que), pop(que));
            } break;
        }
        output(que), printf("\n");
    }
    #undef max_op
    clear(que);
    return 0;
}

1.4 application of queue

  • Queue (loop): sequence traversal of tree, breadth first search (graph algorithm basis)
  • Monotone queue: interval maximum (small) value

1.4.1 Leetcode 239. Sliding window maximum - monotonic queue

The solution is the interval maximum, so the monotone queue is used.

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize){
    int que[numsSize]; //Save the array subscript. The value in the array corresponding to the subscript is monotonically decreasing
    int head = 0, tail = 0;
    for (int i = 0; i < k; i++) {
        while (head < tail && nums[i] >= nums[que[tail - 1]]) {
            tail--;
        }
        que[tail++] = i;
    }
    *returnSize = 0;
    int *ret = malloc(sizeof(int) * (numsSize - k + 1));
    ret[(*returnSize)++] = nums[que[head]];
    for (int i = k; i < numsSize; i++) {
        while (head < tail && nums[i] >= nums[que[tail - 1]]) {
            tail--;
        }
        que[tail++] = i;
        while (que[head] <= i - k) { //Determine whether the queue head element of the monotone queue is in the sliding window
            head++;
        }
        ret[(*returnSize)++] = nums[que[head]];
    }
    return ret;
}

2. Stack

2.1 nature of stack

FILO: First In, Last Out.

2.2 code implementation of stack

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct Stack {
   int *data;
   int capacity; //Stack capacity
   int top; //Stack top pointer
} Stack;

/*
* Stack initialization
*/
Stack *init(int n) {
   Stack *sta = (Stack *)malloc(sizeof(Stack));
   sta->data = (int *)malloc(sizeof(int) * n);
   sta->capacity = n;
   sta->top = -1;
   return sta;
}

/*
* Get stack top element
*/
int top(Stack *sta) {
   return sta->data[sta->top];
}

/*
* Determine whether the stack is empty
*/
int empty(Stack *sta) {
   return sta->top == -1;
}

/*
* Push 
*/
int push(Stack *sta, int val) {
   if (sta == NULL) return -1;
   if (sta->top == sta->capacity - 1) return -1;
   sta->data[++(sta->top)] = val;
   return 0;
}

/*
* Out of stack
*/ 
int pop(Stack *sta) {
   if (sta == NULL) return -1;
   if (empty(sta)) return -1;
   sta->top--;
   return 0;
}

/*
* Printing of elements in stack
*/
void output(Stack *sta) {
   printf("Stack(%d) = [", sta->top + 1);
   for (int i = 0; i <= sta->top; i++) {
       i && printf(", ");
       printf("%d", sta->data[i]);
   }
   printf("]\n");
   return ;
}

/*
* Stack destruction
*/
void clear(Stack *sta) {
   if (sta == NULL) return ;
   free(sta->data);
   free(sta);
   return ;
}

int main() {
   srand(time(0));
   #define max_op 20 
   Stack *sta = init(max_op);
   for (int i = 0; i < max_op; i++) {
       int val = rand() % 100;
       int op = rand() % 4;
       switch (op) {
           case 0:
           case 1:
           case 2: {
               printf("push %d to the Stack, result = %d\n", val, push(sta, val));
           } break;
           case 3: {
               printf("pop %d from the Stack, result = %d\n", top(sta), pop(sta));
           } break;
       }
       output(sta), printf("\n");
   }
   #undef max_op
   clear(sta);
   return 0;
}

2.3 Application of stack

  • Stack: tree depth traversal and depth first search (Fig. algorithm basis)
  • Monotone stack: near the maximum (small) value
    The elements stored in the stack are monotonic, which is the classical data structure "monotonic stack".
    Typical application scenario of monotone stack: find the first number satisfying a certain condition in a one-dimensional array.

2.3.1 Leetcode 20. Valid parentheses

//Array implementation stack
int getValue(char c) {
    if (c == ')') return '(';
    if (c == ']') return '[';
    if (c == '}') return '{';
    return 0;
}

bool isValid(char * s){
    int sta[strlen(s) + 1], top = 0;
    for (int i = 0; s[i]; i++) {
        int ch = getValue(s[i]);
        if (ch) {
            if (top == 0 || sta[top - 1] != ch) 
                return false;
            top--;
        } else {
            sta[top++] = s[i];
        }
    }
    return top == 0;
}

2.3.2 Leetcode 42. Rainwater connection - monotonic stack

//Find the first column above it on the left and the first column above it on the right (near the maximum)
//Time complexity O(n)
int trap(int* height, int heightSize) {
    int n = heightSize;
    if (n == 0) {
        return 0;
    }
    int ans = 0;
    int stk[n], top = 0;
    for (int i = 0; i < n; ++i) {
        while (top && height[i] > height[stk[top - 1]]) {
            int stk_top = stk[--top];
            if (!top) {
                break;
            }
            int left = stk[top - 1];
            int currWidth = i - left - 1;
            int currHeight = fmin(height[left], height[i]) - height[stk_top];
            ans += currWidth * currHeight;
        }
        stk[top++] = i;
    }
    return ans;
}

2.3.3 Leetcode 84. The largest rectangle in the histogram - monotone stack + constant optimization

int largestRectangleArea(int* heights, int heightsSize){
    int n = heightsSize;
    int left[n], right[n];
    int ans = 0;
    int mono_stack[n], top = -1;
    //Find and record the first position on the left and right of each column that is less than the height of the column
    for (int i = 0; i < n; i++) {
        right[i] = n;
        while (top != -1 && heights[mono_stack[top]] >= heights[i]) {
            right[mono_stack[top]] = i; //On the right side of the stack top position, the first column less than this height is the column at i position
            top--;
        }
        left[i] = top == -1 ? -1 : mono_stack[top];
        mono_stack[++top] = i;
    }

    for (int i = 0; i < n; i++) {
        ans = fmax(ans, (right[i] - left[i] - 1) * heights[i]);
    }
    return ans;
}

2.3.4 Leetcode 496. Next larger element I - monotone stack + hash table

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        vector<int> ans;
        stack<int> mono_stack;
        unordered_map<int, int> ans_map;

        int n = nums1.size(), m = nums2.size();
        for (int i = 0; i < m; i++) {
            ans_map[nums2[i]] = -1;
            //The monotone stack holds the first number greater than the number on the right of each number in nums2 array
            while (!mono_stack.empty() && nums2[i] > mono_stack.top()) {
                ans_map[mono_stack.top()] = nums2[i];
                mono_stack.pop();
            }
            mono_stack.push(nums2[i]);
        }

        for (int i = 0; i < n; i++) {
            ans.push_back(ans_map[nums1[i]]);
        }

        return ans;
    }
};

2.3.5 Leetcode 503. Next larger element II - monotone stack + circular array

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* nextGreaterElements(int* nums, int numsSize, int* returnSize){
    *returnSize = numsSize;
    if (numsSize == 0) return NULL;

    int *res = (int *)malloc(sizeof(int) * numsSize);
    memset(res, -1, sizeof(int) * numsSize);
    //sta stores subscripts and uses modulo to process cyclic arrays
    int sta[numsSize * 2], top = 0;
    for (int i = 0; i < numsSize * 2 - 1; i++) {
        while (top > 0 && nums[sta[top - 1]] < nums[i % numsSize]) {
            res[sta[top - 1]] = nums[i % numsSize];
            top--;
        }
        sta[top++] = i % numsSize;
    }
    return res;
}

2.3.6 Leetcode 739. Daily temperature - monotonic stack

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* nextGreaterElements(int* nums, int numsSize, int* returnSize){
    *returnSize = numsSize;
    if (numsSize == 0) return NULL;

    int *res = (int *)malloc(sizeof(int) * numsSize);
    memset(res, -1, sizeof(int) * numsSize);
    //sta stores subscripts and uses modulo to process cyclic arrays
    int sta[numsSize * 2], top = 0;
    for (int i = 0; i < numsSize * 2 - 1; i++) {
        while (top > 0 && nums[sta[top - 1]] < nums[i % numsSize]) {
            res[sta[top - 1]] = nums[i % numsSize];
            top--;
        }
        sta[top++] = i % numsSize;
    }
    return res;
}

2.3.7 Leetcode 1673. Find the most competitive subsequence - monotone stack

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* mostCompetitive(int* nums, int numsSize, int k, int* returnSize){
    *returnSize = k;
    if (numsSize == 0) return NULL;

    int n = numsSize;
    int sta[n], top = 0;
    int *ret = (int *)malloc(sizeof(int) * k);
    
    int removeCount = n - k;
    for (int i = 0; i < n; i++) {
        while (removeCount > 0 && top && nums[i] < nums[sta[top - 1]]) {
            removeCount--;
            top--;
        }
        sta[top++] = i;
    }
    //At this time, the data corresponding to the array subscript stored in the monotonic stack increases monotonically from the bottom of the stack to the top of the stack
    //The k elements from the bottom of the stack are the final answer
    while (removeCount--) {
        --top;
    }
    
    int ind = k - 1;
    while (ind >= 0 && top) {
        ret[ind--] = nums[sta[top - 1]];
        top--;
    }

    return ret;
}

3. Leetcode 225. Implement stack with queue

Idea: one queue is enough. After a new element enters the queue, the elements in front of the element in the queue exit the queue in turn and enter the queue again.

//Implementing queues with arrays
typedef struct {
    int *data;
    int head;
    int tail;
    int length;
    int capacity;
} MyStack;

/** Initialize your data structure here. */

MyStack* myStackCreate() {
    MyStack *sta = (MyStack *)malloc(sizeof(MyStack));
    sta->data = (int *)malloc(sizeof(int) * 100);
    sta->head = 0;
    sta->tail = 0;
    sta->length = 0;
    sta->capacity = 100;
    return sta;
}

/** Push element x onto stack. */
void myStackPush(MyStack* obj, int x) {
    //if (obj->tail == obj->capacity) obj->tail = 0;
    obj->data[obj->tail++] = x;
    int n = obj->length;
    while (n--) {
        obj->data[obj->tail++] = obj->data[obj->head];
        obj->head++;
    }
    obj->length++;
}

/** Removes the element on top of the stack and returns that element. */
int myStackPop(MyStack* obj) {
    if (obj->length == 0) return -1;
    int data = obj->data[obj->head++];
    obj->length--;
    return data;
}

/** Get the top element. */
int myStackTop(MyStack* obj) {
    return obj->data[obj->head];
}

/** Returns whether the stack is empty. */
bool myStackEmpty(MyStack* obj) {
    return obj->length == 0;
}

void myStackFree(MyStack* obj) {
    if (obj == NULL) return ;
    free(obj->data);
    free(obj);
    return ;
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

The queue is realized by linked list, and then the header insertion method is adopted:

typedef  struct tagLinkNode {
    int val;
    struct tagLinkNode *next;
} LinkNode;

typedef struct {
    LinkNode *top;
} MyStack;

/** Initialize your data structure here. */

MyStack* myStackCreate() {
    MyStack *stk = calloc(1, sizeof(MyStack));
    return stk;
}

/** Push element x onto stack. */
void myStackPush(MyStack* obj, int x) {
    LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));
    node->val = x;
    node->next = obj->top;
    obj->top = node;
    return ;
}

/** Removes the element on top of the stack and returns that element. */
int myStackPop(MyStack* obj) {
    if (obj->top == NULL) return -1;
    LinkNode *node = obj->top;
    int data = node->val;
    obj->top = node->next;
    free(node);
    return data;
}

/** Get the top element. */
int myStackTop(MyStack* obj) {
    return obj->top ? obj->top->val : -1;
}

/** Returns whether the stack is empty. */
bool myStackEmpty(MyStack* obj) {
    return (obj->top) == NULL;
}

void myStackFree(MyStack* obj) {
    while (obj->top != NULL) {
        LinkNode *node = obj->top;
        obj->top = node->next;
        free(node);
    }
    return ;
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

4. Leetcode 232. Implement queue with stack

Idea: dual stack, one input stack (handling push) and one output stack (handling pop and peek)

//C language to achieve their own stack and application 
typedef struct {
    int *data;
    int top;
    int capacity;
} Stack;

Stack *stackCreate(int capacity) {
    Stack *sta = malloc(sizeof(Stack));
    sta->data = malloc(sizeof(int) * capacity);
    sta->top = -1;
    sta->capacity = capacity;
    return sta;
}

void stackPush(Stack *obj, int x) {
    obj->data[++(obj->top)] = x;
}

void stackPop(Stack *obj) {
    obj->top--;   
} 

int stackTop(Stack *obj) {
    return obj->data[obj->top];
}

bool stackEmpty(Stack *obj) {
    return obj->top == -1;
}

void stackFree(Stack *obj) {
    if (obj == NULL) return ;
    free(obj->data);
    free(obj);
    return ;
}

typedef struct {
    Stack *inStack;
    Stack *outStack;
} MyQueue;

/** Initialize your data structure here. */

MyQueue* myQueueCreate() {
    MyQueue *que = malloc(sizeof(MyQueue));
    que->inStack = stackCreate(100);
    que->outStack = stackCreate(100);
    return que;
}

/** Push element x to the back of queue. */
void myQueuePush(MyQueue* obj, int x) {
    stackPush(obj->inStack, x);
}

void in2out(MyQueue *obj) {
    while (!stackEmpty(obj->inStack)) {
        stackPush(obj->outStack, stackTop(obj->inStack));
        stackPop(obj->inStack);
    }
}

/** Removes the element from in front of queue and returns that element. */
int myQueuePop(MyQueue* obj) {
    if (stackEmpty(obj->outStack)) {
        in2out(obj);
    }
    int x = stackTop(obj->outStack);
    stackPop(obj->outStack);
    return x;
}

/** Get the front element. */
int myQueuePeek(MyQueue* obj) {
    if (stackEmpty(obj->outStack)) {
        in2out(obj);
    }
    return stackTop(obj->outStack);
}

/** Returns whether the queue is empty. */
bool myQueueEmpty(MyQueue* obj) {
    return stackEmpty(obj->inStack) && stackEmpty(obj->outStack);
}

void myQueueFree(MyQueue* obj) {
    stackFree(obj->inStack);
    stackFree(obj->outStack);
}

/**
 * Your MyQueue struct will be instantiated and called as such:
 * MyQueue* obj = myQueueCreate();
 * myQueuePush(obj, x);
 
 * int param_2 = myQueuePop(obj);
 
 * int param_3 = myQueuePeek(obj);
 
 * bool param_4 = myQueueEmpty(obj);
 
 * myQueueFree(obj);
*/

Posted by logicsound on Wed, 08 Sep 2021 01:45:14 -0700