自学内容网 自学内容网

栈和队列面试题(C 语言)

1. 有效的括号

题目描述: 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = “()”
输出:true

示例 2:

输入:s = “()[]{}”
输出:true

示例 3:

输入:s = “(]”
输出:false

示例 4:

输入:s = “([])”
输出:true

提示:

1 <= s.length <= 104
s 仅由括号 ‘()[]{}’ 组成

题目OJ链接: link

解题思路: 分析题目可得,每次出现的右括号总是和离得最近的左括号匹配。那么可以把左括号都压入栈中,遇到右括号就拿出来匹配,不匹配就返回 false。直到遍历完整个字符串,如果栈中元素为空,那么就返回 true,否则返回 false。

由于本题是使用 C 语言答题,需要手搓一个栈出来,还是比较考验答题者的代码水平。

当然也可以使用数组模拟栈,但是其中有一些需要注意的地方。

代码如下:

// 栈

// 类型声明
typedef char DataType;

// 常量声明
#define CAPACITY_INIT 8

// 栈结构声明
typedef struct Stack
{
    DataType* pdata;  // 指向数据的指针
    size_t top;  // 当前栈中元素个数和下一个入栈的位置
    size_t capacity;  // 当前栈的容量
}Stack;

// 方法

// 初始化栈
void StackInit(Stack* sk)
{
    assert(sk);
    // 申请空间
    sk->pdata = (DataType*)malloc(sizeof(DataType)*CAPACITY_INIT);
    if (NULL == sk->pdata)
    {
        perror("StackInit::malloc: ");
        exit(-1);
    }
    // 成员初始化
    sk->capacity = CAPACITY_INIT;
    sk->top = 0;
}

// 入栈
void StackPush(Stack* sk, DataType data)
{
    assert(sk);
    // 增容判断
    if (sk->top == sk->capacity)
    {
        DataType* tmp = (DataType*)realloc(sk->pdata, sizeof(DataType)*sk->capacity*2);
        if (NULL == tmp)
        {
            perror("StackPush::realloc: ");
            exit(-1);
        }
        // 更新成员
        sk->pdata = tmp;
        sk->capacity *= 2;
    }
    // 入栈
    sk->pdata[sk->top++] = data;
}

// 出栈
void StackPop(Stack* sk)
{
    assert(sk);
    // 空栈判duan
    if (0 == sk->top)
    {
        printf("Empty Stack!\n");
        exit(-1);
    }
    // 出栈
    --sk->top;
}

// 返回栈顶元素
DataType StackTop(const Stack* sk)
{
    assert(sk);
    // 空栈判断
    if (0 == sk->top)
    {
        printf("Empty Stack!\n");
        exit(-1);
    }
    // 返回
    return sk->pdata[sk->top-1];
}

// 返回栈中当前元素个数
size_t StackSize(const Stack* sk)
{
    assert(sk);
    return sk->top;
}

// 空栈判断
bool StackEmpty(const Stack* sk)
{
    assert(sk);
    return (0 == sk->top);
}

// 销毁栈
void StackDestory(Stack* sk)
{
    assert(sk);
    // 释放空间
    free(sk->pdata);
    sk->pdata = NULL;
    // 成员置零
    sk->top = sk->capacity = 0;
}

bool isValid(char* s) {
    // 创建并初始化栈
    Stack sk;
    StackInit(&sk);
    // 遍历字符串
    const char* cur = s;
    while (*cur)
    {
        // 左括号入栈
        if ('(' == *cur || '[' == *cur || '{' == *cur)
        {
            StackPush(&sk, *cur);
        }
        else
        {
            // 空栈判断
            if (StackEmpty(&sk))
                return false;
            // 获得栈顶元素
            char top = StackTop(&sk);
            StackPop(&sk);
            // 匹配判断
            if ((')' == *cur && '(' != top)
            || (']' == *cur && '[' != top) 
            || ('}' == *cur && '{' != top))
                return false;
        }
        // 下一个字符
        ++cur;
    }
    // 空栈判断
    if (StackEmpty(&sk))
        return true;
    else
        return false;
}

2. 用队列实现栈

题目描述: 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:
你只能使用队列的标准操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:
输入:
[“MyStack”, “push”, “push”, “top”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

提示:
1 <= x <= 9
最多调用100 次 push、pop、top 和 empty
每次调用 pop 和 top 都保证栈不为空

题目OJ链接: link

解题思路: 使用两个队列——q1 和 q2。当需要入栈的时候,往两个队列中不为空的队列入数据;当需要出栈的时候,把不为空的队列的数据除了队尾的数据,其他全部导入另一个空队中,然后把队尾的数据出队,也就完成了出栈的操作。那么剩下的操作就非常简单了。

本题也可以使用一个队列来完成,入栈的时候入队就行,出栈的时候需要把除队尾以外的所有元素全部出队再入队,然后队尾的元素就在队头的,然后把它出队,这样就完成了出栈的操作。

代码如下:
(1)两个队列

// 队列

// 类型声明
typedef int DataType;

// 节点结构声明
typedef struct Node
{
    DataType val;  // 数据
    struct Node* next;  // 下一个结点的位置
}Node;

// 队列结构声明
typedef struct Queue
{
    Node* head;  // 队头位置
    Node* tail;  // 队尾位置
    size_t size;  // 当前队列元素个数
}Queue;

// 方法

// 初始化队列
void QueueInit(Queue* q)
{
    assert(q);
    q->head = q->tail = NULL;
    q->size = 0;
}

// 入队
void QueuePush(Queue* q, DataType data)
{
    assert(q);
    // 申请新节点
    Node* new_node = (Node*)malloc(sizeof(Node));
    if (NULL == new_node)
    {
        perror("QueuePush::malloc: ");
        exit(-1);
    }
    // 赋值
    new_node->val = data;
    new_node->next = NULL;
    // 入队
    // 头插判断
    if (NULL == q->head)
    {
        q->head = q->tail = new_node;
    }
    else  // 尾插
    {
        q->tail->next = new_node;
        q->tail = new_node;
    }
    // 元素个数 +1
    ++q->size;
}

// 出队
void QueuePop(Queue* q)
{
    assert(q);
    // 空队判断
    if (0 == q->size)
    {
        printf("Empty Queue!\n");
        exit(-1);
    }
    // 出队
    // 尾删判断
    if (NULL == q->head->next)
    {
        free(q->head);
        q->head = q->tail = NULL;
    }
    else  // 头删
    {
        // 存储下一个节点的位置
        Node* next = q->head->next;
        // 删除头节点
        free(q->head);
        // 新的头节点
        q->head = next;
    }
    // 元素个数 -1
    --q->size;
}

// 返回队头元素
DataType QueueFront(const Queue* q)
{
    assert(q);
    // 空队判断
    if (0 == q->size)
    {
        printf("Empty Queue!\n");
        exit(-1);
    }
    // 返回
    return q->head->val;
}

// 返回队尾元素
DataType QueueBack(const Queue* q)
{
    assert(q);
    // 空队判断
    if (0 == q->size)
    {
        printf("Empty Queue!\n");
        exit(-1);
    }
    // 返回
    return q->tail->val;
}

// 空队判断
bool QueueEmpty(const Queue* q)
{
    assert(q);
    return (0 == q->size);
}

// 返回当前队列的元素个数
size_t QueueSize(const Queue* q)
{
    assert(q);
    return q->size;
}

// 销毁队列
void QueueDestory(Queue* q)
{
    assert(q);
    Node* cur = q->head;
    while (cur)
    {
        // 存储下一个节点
        Node* next = cur->next;
        // 释放当前节点
        free(cur);
        // 下一个节点
        cur = next;
    }
    // 成员置零
    q->head = q->tail = NULL;
}

typedef struct {
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() {
    // 申请空间
    MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
    if (NULL == obj)
    {
        perror("myStackCreate::malloc: ");
        exit(-1);
    }
    // 成员初始化
    QueueInit(&obj->q1);
    QueueInit(&obj->q2);
    // 返回
    return obj;
}

void myStackPush(MyStack* obj, int x) {
    assert(obj);
    // 往非空队列入元素
    if (QueueEmpty(&obj->q1))
        QueuePush(&obj->q2, x);
    else
        QueuePush(&obj->q1, x);
}

int myStackPop(MyStack* obj) {
    assert(obj);
    // 找到空队
    Queue* empty = &obj->q1;
    Queue* non_empty = &obj->q2;
    if (QueueEmpty(&obj->q2))
    {
        empty = &obj->q2;
        non_empty = &obj->q1;
    }
    // 把非空队除队尾元素以外全部入到空队
    int n = (int)QueueSize(non_empty) - 1;
    int i = 0;
    for (i = 0; i < n; ++i)
    {
        QueuePush(empty, QueueFront(non_empty));
        QueuePop(non_empty);
    }
    // 出队尾元素并返回
    DataType ret = QueueFront(non_empty);
    QueuePop(non_empty);
    return ret;
}

int myStackTop(MyStack* obj) {
    assert(obj);
    // 返回非空队的队尾元素
    if (QueueEmpty(&obj->q1))
        return QueueBack(&obj->q2);
    else
        return QueueBack(&obj->q1);
}

bool myStackEmpty(MyStack* obj) {
    assert(obj);
    // 判断两个队列是否都为空
    return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) {
    // 释放两个队列
    QueueDestory(&obj->q1);
    QueueDestory(&obj->q2);
    // 释放栈
    free(obj);
}

(2)一个队列

// 队列

// 类型声明
typedef int DataType;

// 节点结构声明
typedef struct Node
{
    DataType val;  // 数据
    struct Node* next;  // 下一个节点的位置
}Node;

// 队列结构声明
typedef struct Queue
{
    Node* head;  // 队头位置
    Node* tail;  // 队尾位置
    size_t size;  // 队列元素个数
}Queue;

// 方法

// 初始化队列
void QueueInit(Queue* q)
{
    assert(q);
    q->head = q->tail = NULL;
    q->size = 0;
}

// 入队
void QueuePush(Queue* q, DataType data)
{
    assert(q);
    // 申请新节点
    Node* new_node = (Node*)malloc(sizeof(Node));
    if (NULL == new_node)
    {
        perror("QueuePush::malloc: ");
        exit(-1);
    }
    // 赋值
    new_node->val = data;
    new_node->next = NULL;
    // 头插判断
    if (NULL == q->head)
    {
        q->head = q->tail = new_node;
    }
    else  // 尾插
    {
        q->tail->next = new_node;
        q->tail = new_node;
    }
    // 元素个数 +1
    ++q->size;
}

// 出队
void QueuePop(Queue* q)
{
    assert(q);
    // 空队判断
    if (0 == q->size)
    {
        printf("Empty Queue!\n");
        exit(-1);
    }
    // 尾删判断
    if (NULL == q->head->next)
    {
        free(q->head);
        q->head = q->tail = NULL;
    }
    else  // 头删
    {
        // 存储下一个节点
        Node* next = q->head->next;
        // 释放头结点
        free(q->head);
        // 新的头节点
        q->head = next;
    }
    // 元素个数 -1
    --q->size;
}

// 返回队头元素
DataType QueueFront(const Queue* q)
{
    assert(q);
    // 空队判断
    if (0 == q->size)
    {
        printf("Empty Queue!\n");
        exit(-1);
    }
    // 返回
    return q->head->val;
}

// 返回队尾元素
DataType QueueBack(const Queue* q)
{
    assert(q);
    // 空队判断
    if (0 == q->size)
    {
        printf("Empty Queue!\n");
        exit(-1);
    }
    // 返回
    return q->tail->val;
}

// 空队判断
bool QueueEmpty(const Queue* q)
{
    assert(q);
    return (0 == q->size);
}

// 返回当前队列中元素个数
size_t QueueSize(const Queue* q)
{
    assert(q);
    return q->size;
}

// 销毁队列
void QueueDestory(Queue* q)
{
    assert(q);
    Node* cur = q->head;
    while (cur)
    {
        // 存储下一个结点的位置
        Node* next = cur->next;
        // 删除当前节点
        free(cur);
        // 下一个节点
        cur = next;
    }
    // 成员置零
    q->head = q->tail = NULL;
    q->size = 0;
}


typedef struct {
    Queue q;
} MyStack;


MyStack* myStackCreate() {
    // 申请空间
    MyStack* sk = (MyStack*)malloc(sizeof(MyStack));
    if (NULL == sk)
    {
        perror("myStackCreate::malloc: ");
        exit(-1);
    }
    // 成员初始化
    QueueInit(&sk->q);
    // 返回
    return sk;
}

void myStackPush(MyStack* obj, int x) {
    assert(obj);
    // 直接入队
    QueuePush(&obj->q, x);
}

int myStackPop(MyStack* obj) {
    assert(obj);
    // 把除队尾以外所有元素重新入队
    int n = (int)QueueSize(&obj->q) - 1;
    while (n--)
    {
        QueuePush(&obj->q, QueueFront(&obj->q));
        QueuePop(&obj->q);
    }
    // 返回队头元素并出队
    DataType ret = QueueFront(&obj->q);
    QueuePop(&obj->q);
    return ret;
}

int myStackTop(MyStack* obj) {
    assert(obj);
    return QueueBack(&obj->q);
}

bool myStackEmpty(MyStack* obj) {
    assert(obj);
    return QueueEmpty(&obj->q);
}

void myStackFree(MyStack* obj) {
    assert(obj);
    // 释放队列
    QueueDestory(&obj->q);
    // 释放栈
    free(obj);
    obj = NULL;
}

3. 用栈实现队列

题目描述: 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

示例 1:
输入:
[“MyQueue”, “push”, “push”, “peek”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

提示:
1 <= x <= 9
最多调用 100 次 push、pop、peek 和 empty
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

题目OJ链接: link

解题思路: 一个栈专门用来入数据,另一个栈专门用来出数据。当出数据的栈为空时,就把入数据栈中的数据导入到出数据的栈中。

代码如下:

// 栈

// 类型声明
typedef int DataType;

// 常量声明
#define CAPACITY_INIT 8

// 栈结构声明
typedef struct Stack
{
    DataType* pdata;  // 数据的位置
    size_t top;  // 下一个入栈位置和当前栈中的元素个数
    size_t capacity;  // 当前栈的容量
}Stack;

// 方法

// 初始化栈
void StackInit(Stack* sk)
{
    assert(sk);
    // 申请空间
    sk->pdata = (DataType*)malloc(sizeof(DataType)*CAPACITY_INIT);
    if (NULL == sk->pdata)
    {
        perror("StackInit::malloc: ");
        exit(-1);
    }
    // 成员初始化
    sk->capacity = CAPACITY_INIT;
    sk->top = 0;
}

// 入栈
void StackPush(Stack* sk, DataType data)
{
    assert(sk);
    // 增容判断
    if (sk->top == sk->capacity)
    {
        DataType* tmp = (DataType*)realloc(sk->pdata, sizeof(DataType)*sk->capacity*2);
        if (NULL == tmp)
        {
            perror("StackPush::realloc: ");
            exit(-1);
        }
        // 增容成功,更新成员
        sk->pdata = tmp;
        sk->capacity *= 2;
    }
    // 入栈
    sk->pdata[sk->top++] = data;
}

// 出栈
void StackPop(Stack* sk)
{
    assert(sk);
    // 空栈判断
    if (0 == sk->top)
    {
        printf("Empty Stack!\n");
        exit(-1);
    }
    // 出栈
    --sk->top;
}

// 返回栈顶元素
DataType StackTop(const Stack* sk)
{
    assert(sk);
    // 返回
    return sk->pdata[sk->top-1];
}

// 返回栈中当前元素个数
size_t StackSize(const Stack* sk)
{
    assert(sk);
    // 返回
    return sk->top;
}

// 栈空判断
bool StackEmpty(const Stack* sk)
{
    assert(sk);
    // 返回
    return (0 == sk->top);
}

// 销毁栈
void StackDestory(Stack* sk)
{
    assert(sk);
    // 释放数据
    free(sk->pdata);
    sk->pdata = NULL;
    // 成员置零
    sk->top = sk->capacity = 0;
}

typedef struct {
    // 两个栈,分别出入数据
    Stack push;
    Stack pop;
} MyQueue;


MyQueue* myQueueCreate() {
    // 申请空间
    MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
    if (NULL == q)
    {
        perror("myQueueCreat::malloc: ");
        exit(-1);
    }
    // 成员初始化
    StackInit(&q->push);
    StackInit(&q->pop);
    // 返回
    return q;
}

void myQueuePush(MyQueue* obj, int x) {
    assert(obj);
    StackPush(&obj->push, x);
}

int myQueuePop(MyQueue* obj) {
    assert(obj);
    // 导数据判断
    if (StackEmpty(&obj->pop))
    {
        while (!StackEmpty(&obj->push))
        {
            StackPush(&obj->pop, StackTop(&obj->push));
            StackPop(&obj->push);
        }
    }
    // 出数据
    DataType ret = StackTop(&obj->pop);
    StackPop(&obj->pop);
    return ret;
}

int myQueuePeek(MyQueue* obj) {
    assert(obj);
    // 导数据判断
    if (StackEmpty(&obj->pop))
    {
        while (!StackEmpty(&obj->push))
        {
            StackPush(&obj->pop, StackTop(&obj->push));
            StackPop(&obj->push);
        }
    }
    // 返回
    return StackTop(&obj->pop);
}

bool myQueueEmpty(MyQueue* obj) {
    assert(obj);
    return StackEmpty(&obj->push) && StackEmpty(&obj->pop);
}

void myQueueFree(MyQueue* obj) {
    assert(obj);
    // 释放栈
    StackDestory(&obj->push);
    StackDestory(&obj->pop);
    // 释放队列
    free(obj);
    obj = NULL;
}

4. 设计循环队列

题目描述: 设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。

示例:
MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3
circularQueue.enQueue(1); // 返回 true
circularQueue.enQueue(2); // 返回 true
circularQueue.enQueue(3); // 返回 true
circularQueue.enQueue(4); // 返回 false,队列已满
circularQueue.Rear(); // 返回 3
circularQueue.isFull(); // 返回 true
circularQueue.deQueue(); // 返回 true
circularQueue.enQueue(4); // 返回 true
circularQueue.Rear(); // 返回 4

提示:
所有的值都在 0 至 1000 的范围内;
操作数将在 1 至 1000 的范围内;
请不要使用内置的队列库。

解题思路: 本题的解题思路在我的栈和队列的博客当中,其中的循环队列讲解了如何实现的思路。博客链接如下:
link

代码如下:
(1)额外开辟一个空间

// 类型声明
typedef int DataTpye;

typedef struct {
    DataTpye* pdata;  // 数据的位置
    size_t head;  // 队头下标
    size_t tail;  // 队尾下标
    size_t k;  // 环形队列的大小
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    // 申请空间
    MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    if (NULL == q)
    {
        perror("myCircularQueueCreate::malloc: ");
        exit(-1);
    }
    // 成员初始化
    q->pdata = (DataTpye*)malloc(sizeof(DataTpye)*(k+1));
    if (NULL == q->pdata)
    {
        perror("myCircularQueueCreate::malloc: ");
        exit(-1);
    }
    q->k = k;
    q->head = q->tail = 0;
    // 返回
    return q;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    assert(obj);
    return (obj->head == obj->tail);
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    assert(obj);
    return ((obj->tail+1)%(obj->k+1) == obj->head);
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    assert(obj);
    // 满队判断
    if (myCircularQueueIsFull(obj))
        return false;
    // 入队
    obj->pdata[obj->tail] = value;
    obj->tail = (obj->tail+1)%(obj->k+1);
    // 入队成功
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    assert(obj);
    // 空队判断
    if (myCircularQueueIsEmpty(obj))
        return false;
    // 出队
    obj->head = (obj->head+1)%(obj->k+1);
    // 出队成功
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    assert(obj);
    // 空队判断
    if (myCircularQueueIsEmpty(obj))
        return -1;
    // 返回
    return obj->pdata[obj->head];
}

int myCircularQueueRear(MyCircularQueue* obj) {
     assert(obj);
    // 空队判断
    if (myCircularQueueIsEmpty(obj))
        return -1;
    // 返回
    if (obj->tail)
        return obj->pdata[obj->tail-1];
    else
        return obj->pdata[obj->k];
}

void myCircularQueueFree(MyCircularQueue* obj) {
    assert(obj);
    // 释放数据
    free(obj->pdata);
    obj->pdata = NULL;
    // 成员置零
    obj->head = obj->tail = 0;
    obj->k = 0;
    // 释放队列
    free(obj);
    obj = NULL;
}

(2)额外使用一个 size_t 类型的变量 size 存储当前队列元素个数

// 类型声明
typedef int DataType;

typedef struct {
    DataType* pdata;  // 数据位置
    size_t head;  // 队头下标
    size_t tail;  // 队尾下标
    size_t size;  // 当前队列元素个数
    size_t k;  // 队列大小
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    // 申请队列空间
    MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    if (NULL == q)
    {
        perror("myCircularQueueCreate::malloc: ");
        exit(-1);
    }
    // 申请数据空间
    q->pdata = (DataType*)malloc(sizeof(DataType)*(k+1));
    if (NULL == q->pdata)
    {
        perror("myCircularQueueCreate::malloc: ");
        exit(-1);
    }
    // 成员初始化
    q->head = q->tail = 0;
    q->size = 0;
    q->k = k;
    // 返回
    return q;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    assert(obj);
    // 满队判断
    if (obj->size == obj->k)
        return false;
    // 入队
    obj->pdata[obj->tail] = value;
    obj->tail = (obj->tail+1)%(obj->k+1);
    ++obj->size;
    // 入队成功
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    assert(obj);
    // 空队判断
    if (0 == obj->size)
    {
        return false;
    }
    // 出队
    obj->head = (obj->head+1)%(obj->k+1);
    --obj->size;
    // 出队成功
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    assert(obj);
    // 空队判断
    if (0 == obj->size)
        return -1;
    // 返回
    return obj->pdata[obj->head];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    assert(obj);
    // 空队判断
    if (0 == obj->size)
        return -1;
    // 返回
    if (obj->tail)
        return obj->pdata[obj->tail-1];
    else
        return obj->pdata[obj->k];
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    assert(obj);
    return (0 == obj->size);
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    assert(obj);
    return (obj->size == obj->k);
}

void myCircularQueueFree(MyCircularQueue* obj) {
    assert(obj);
    // 释放数据
    free(obj->pdata);
    // 释放队列
    free(obj);
    obj = NULL;
}

原文地址:https://blog.csdn.net/weixin_70742989/article/details/143612352

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!