天天看點

資料結構--棧和隊列(C語言)

一、棧

1.棧的概念及結構

棧:一種特殊的線性表,其隻允許在固定的一端進行插入和删除元素操作。進行資料插入和删除操作的一端稱為棧頂,另一端稱為棧底。棧中的資料元素遵守後進先出LIFO(Last In First Out)的原則。

壓棧:棧的插入操作叫做進棧/壓棧/入棧,入資料在棧頂。

出棧:棧的删除操作叫做出棧。出資料也在棧頂。

資料結構--棧和隊列(C語言)

棧的實作一般可以使用數組或者連結清單實作,相對而言數組的結構實作更優一些。因為數組在尾上插入資料的代價比較小。

數組棧

資料結構--棧和隊列(C語言)

鍊式棧

資料結構--棧和隊列(C語言)
資料結構--棧和隊列(C語言)

對于第一種頭作為棧頂,插入删除資料為頭插和頭删,這樣很容易找到頭進行操作,如果用頭做棧頂,頭插頭删,就可以設計成單連結清單。

第二種尾作為棧頂,插入删除資料為尾插和尾删,這種結構設計成雙向連結清單比較好,否則删除資料效率低。

其次數組棧緩存使用率高,因為數組是一段連續的空間,記憶體通路數組的第一個數的時候,後面的數字已經預緩存在cache中,而鍊式棧的空間不是連續的,是用連結清單将不連續的空間連接配接起來,在找到連結清單的第一個數字後,如果找不到第二個空間,假設不命中,一次加載20byte到緩存(具體加載多大取決硬體體系)。鍊式棧的緩存命中率低。

對于鍊式棧唯一的好處就是可以随時開辟空間,不浪費空間,數組棧隻能在空間不夠的時候開辟一定的空間,存在空間的浪費,但是鍊式棧僅限于這個好處。除非要在一個不能浪費空間的地方使用,比如嵌入式,我們用鍊式棧。

是以對于棧,兩種都可以,非要選一種,我們最好用數組棧。

2.棧的實作

對于各個函數的聲明和頭檔案的包括,我們寫在Stack.h中
#pragma once           

#include <stdio.h>

#include <stdlib.h>

#include <assert.h>

#include <stdbool.h>

typedef int STDataType;

typedef struct Stack

{

STDataType* a;//數組指針

int top;//棧頂

int capacity;//最大容量

}ST;

//初始化數組

void StackInit(ST ps);

//銷毀數組

void StackDestroy(ST ps);

void StackPush(ST ps, STDataType x);

void STackPop(ST ps);

//找到棧頂元素

STDataType StackTop(ST ps);

//棧的大小

int StackSize(ST ps);

//判斷棧是否為空

bool StackEmpty(ST* ps);//引用頭檔案

#### 棧的初始化
将指針置空,棧中最大個數為0,棧的下标為0或-1
```c
void StackInit(ST* ps)
{
    assert(ps);
    ps->a = NULL;
    ps->top = 0;//指向棧頂的下一個,指向棧頂後,+1指向下一個
    //ps->top=-1;//指向棧頂,先+1再指向棧頂
    ps->capacity = 0;
}           

插入資料

棧的插入資料隻有一種,在棧頂插入,将資料插入棧頂,top下标也要增加一個,當插入到棧滿的時候,我們需要擴容。

void StackPush(ST* ps, STDataType x)
{
    assert(ps);
    if (ps->top == ps->capacity)
    {
        int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
        STDataType* tmp = realloc(ps->a, sizeof(STDataType)*newcapacity);
        if (tmp == NULL)
        {
            printf("realloc fail\n");
            exit(-1);
        }
        ps->a = tmp;
        ps->capacity = newcapacity;
    }
    ps->a[ps->top] = x;
    ps->top++;
}           

銷毀資料

void StackDestroy(ST* ps)
{
    assert(ps);
    free(ps->a);//釋放置空
    ps->a = NULL;
    ps->capacity = ps->top = 0;//置為0
}           

删除資料

删除非常簡單,隻需要将top減減,但在test.c中測試,删除資料最後top會小于0,變成-1,-2...,是以我們直接斷言一下,在top大于0時,才能删除

void STackPop(ST* ps)
{
    assert(ps);
    assert(ps->top > 0);

    ps->top--;
}           

取棧頂資料

因為前面初始化棧頂top為0,最後指向棧頂元素的下一個,是以傳回top-1.當棧為空時,top-1為野指針,傳回随機值,是以斷言一下top>0

STDataType StackTop(ST* ps)
{
    assert(ps);
    assert(ps->top > 0);

    return(ps->a[ps->top-1]);
}           

棧的大小

int StackSize(ST* ps)
{
    assert(ps);
    return ps->top;
}           

判斷棧是否為空

bool StackEmpty(ST* ps)
{
    /*if (ps->top == 0)//檢視下标top是否為0
    {
        return true;
    }
    else
    {
        return false;
    }*/
    return ps->top == 0;//如果為0傳回ture,其他情況傳回false
}           

棧的實作時非常簡單的

那麼如何實作棧的周遊列印呢

void TestStack2()
{
    ST st;
    StackInit(&st);
    StackPush(&st, 1);
    StackPush(&st, 2);
    StackPush(&st, 3);
    StackPush(&st, 4);

    while (!StackEmpty(&st))
    {
        printf("%d ", StackTop(&st));
        StackPop(&st);
    }

    StackDestroy(&st);
}           

每次列印棧頂,并删除棧頂即可,最後棧為空跳出循環,列印結束。

3.OJ練習題--有效的括号

我們來做一道OJ題小試牛刀

給定一個隻包括 '(',')','{','}','[',']' 的字元串 s ,判斷字元串是否有效。

有效字元串需滿足:

左括号必須用相同類型的右括号閉合。
左括号必須以正确的順序閉合。           

來源:力扣(LeetCode)

連結:https://leetcode-cn.com/problems/valid-parentheses

資料結構--棧和隊列(C語言)
資料結構--棧和隊列(C語言)

這道題我們運用上面寫好的接口,因為用的是C語言來寫,不像C++有STL庫刷起來那麼友善,需要自己實作接口,這是C刷題的一個弊端。

思路:當遇到左括号入棧,當遇到右括号左括号出棧跟右括号比對示例5中,遇到左括号入棧,當遇到有括号的時候棧頂的左括号出棧與之比對,比對上了,指針向下走,這時棧頂的第一個左括号已經被删除,當遇到第二個右括号時,棧裡的左括号與之比對,比對上了,指針向下走,當指針指向空時,傳回真,其他情況傳回false.

傳回資料的時候一定要記得銷毀棧,避免記憶體洩漏,因為這個棧是我們realloc出來的。

當遇到隻有一個左括号的時候,左括号入棧,但是指針在向下走的時候,直接跳出循環,得到傳回值,無法得到true結果,這時我們要判斷是否是空,如果是空傳回true,否則為false。

當隻有一個右括号的時候,棧中沒有元素,棧為空,取不到棧頂,我們在上面斷言了棧不能為空,是以要判斷一下棧是否為空,然後傳回false,這個詳情看下面代碼。

typedef char STDataType;
typedef struct Stack
{
    STDataType* a;//數組指針
    int top;//棧頂
    int capacity;//最大容量
}ST;

//初始化數組
void StackInit(ST* ps);
//銷毀數組
void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
//找到棧頂元素
STDataType StackTop(ST* ps);
//棧的大小
int StackSize(ST* ps);
//判斷棧是否為空
bool StackEmpty(ST* ps);//引用頭檔案

void StackInit(ST* ps)
{
    assert(ps);
    ps->a=NULL;
    ps->top=ps->capacity=0;
}

void StackDestroy(ST* ps)
{
    assert(ps);
    free(ps->a);
    ps->a=NULL;
    ps->top=ps->capacity=0;
}

void StackPush(ST* ps, STDataType x)
{
    assert(ps);
    if(ps->top==ps->capacity)
    {
        int newcapacity=ps->capacity==0?4:ps->capacity*2;
        STDataType* tmp=(STDataType*)realloc(ps->a,sizeof(STDataType)*newcapacity);
        if(tmp==NULL)
        {
            printf("realloc fail\n");
            exit(-1);
        }
        ps->a=tmp;
        ps->capacity=newcapacity;
    }
    ps->a[ps->top]=x;
    ps->top++;
}

void StackPop(ST* ps)
{
    assert(ps);
    assert(ps->top>0);
    ps->top--;
}

STDataType StackTop(ST* ps)
{
    assert(ps);
    assert(ps->top>0);
    return ps->a[ps->top-1];
}

int StackSize(ST* ps)
{
    assert(ps);
    return ps->top;
}

bool StackEmpty(ST* ps)
{
    return ps->top==0;
}

bool isValid(char * s){
    ST st;
    StackInit(&st);
    while(*s)
    {
        if(*s=='(' || *s=='[' || *s=='{')
        {
            //入棧
            StackPush(&st,*s);
            ++s;
        }
        else
        {
            //遇到右括号,但是棧裡沒有資料,沒有左括号了,傳回false
            if(StackEmpty(&st))
            {
                StackDestroy(&st);
                return false;
            }
            STDataType top=StackTop(&st);
            StackPop(&st);
            if((*s==')' && top !='(')||
               (*s==']' && top !='[')||
               (*s=='}' && top !='{'))
               {
                   StackDestroy(&st);
                   return false;
               }
            else
            {
                ++s;
            }
        }
    }
    //如果棧不是空,棧中還有左括号未出,沒有比對,傳回的時false
   // bool ret=StackEmpty(&st);
   // return ret;

    if(StackEmpty(&st))
    {
        return true;
    }
    else
    {
        return false;
    }
    StackDestroy(&st);
}           

二、隊列

1.隊列的概念及結構

隊列:隻允許在一端進行插入資料操作,在另一端進行删除資料操作的特殊線性表,隊列具有先進先出FIFO(First In First Out)

入隊列:進行插入操作的一端稱為隊尾

出隊列:進行删除操作的一端稱為隊頭

2.隊列的實作

隊列裡面我們定義一個指針

typedef struct QueueNode
{
    QDataType data;
    struct QueueNode* next;
}QueueNode;           

因為隊列是先進先出,存放資料為尾插,删除資料為頭删,是以為了友善,我們定義兩個指針,一個指向頭一個指向尾,然後放在一個結構體中,這樣我們測試的時候可以不用二級指針,直接通過結構體來改變裡面的資料。如果不定義這樣的一個結構體,通過二級指針傳入指針位址,然後通過一級指針找到資料來改變資料。

typedef struct QueueList
{
    QueueNode* head;
    QueueNode* tail;
}QList;           

棧的初始化和銷毀

void QueueInit(QList* ps)
{
    assert(ps);
    ps->head = NULL;
    ps->tail = NULL;
}           
void QueueDestroy(QList* ps)
{
    assert(ps);
    QueueNode* cur = ps->head;//定義指針周遊連結清單
    QueueNode* next = cur->next;//存放目前指針的下一個
    while (cur)
    {
        free(cur);
        cur = next;
    }
    ps->head = ps->tail = NULL;
}           

判斷隊列是否為空

bool QueueEmpty(QList* ps)
{
    /*if (ps->head == NULL)
    {
        return true;
    }
    else
    {
        return false;
    }*/

    return ps->head == NULL;
}           

尾插和頭删

隻實作尾插和頭删是由于隊列的性質寫出的

**尾插**
void QueuePush(QList* ps, QDataType x)
{
    assert(ps);
    QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
    newnode->data = x;
    newnode->next = NULL;

    if (ps->tail == NULL)
    {
        ps->tail = ps->head = newnode;
    }
    else
    {
        ps->tail->next = newnode;
        ps->tail = newnode;
    }

}
           

頭删

在頭删的同時,頭删到NULL,tail指針并沒有被釋放,它還指向最後一個節點,head釋放掉之後,tail成為野指針,傳回随機值。是以head釋放掉變為NULL的同時,也将tail置為空

void QueuePop(QList* ps)
{
    assert(ps);//判斷結構體不為空
    assert(!QueueEmpty(ps));//判斷隊列不為空
    QueueNode* next = ps->head->next;

    free(ps->head);
    ps->head = next;
    if (ps->head == NULL)
    {
        ps->tail = NULL;
    }
}           

傳回隊尾和隊頭資料

QDataType QueueFront(QList* ps)
{
    assert(ps);
    assert(!QueueEmpty(ps));
    return ps->head->data;
}

QDataType QueueBack(QList* ps)
{
    assert(ps);
    assert(!QueueEmpty(ps));
    return ps->tail->data;
}           

計算隊列大小

int QueueSize(QList* ps)
{
    assert(ps);
    QueueNode* cur = ps->head;
    int count = 0;
    while (cur)
    {
        ++count;
        cur = cur->next;
    }
    return count;
}           

測試一下

test.c

void TestQueue1()
{
    QList q;
    QueueInit(&q);

    QueuePush(&q, 1);
    QueuePush(&q, 2);
    QueuePush(&q, 3);
    QueuePush(&q, 4);

    while (!QueueEmpty(&q))
    {
        QDataType front = QueueFront(&q);
        printf("%d ", front);
        QueuePop(&q);
    }
    printf("\n");

}
int main()
{
    TestQueue1();
    return 0;
}           
資料結構--棧和隊列(C語言)

隊列OJ題

讓我們來做幾道OJ題

1.用隊列實作棧

請你僅使用兩個隊列實作一個後入先出(LIFO)的棧,并支援普通棧的全部四種操作(push、top、pop 和 empty)。

實作 MyStack 類:

void push(int x) 将元素 x 壓入棧頂。

int pop() 移除并傳回棧頂元素。

int top() 傳回棧頂元素。

boolean empty() 如果棧是空的,傳回 true ;否則,傳回false 。

OJ連結

思路:這道題用兩個隊列實作棧,将資料放進一個隊列中,再将資料删除導入到另一個隊列,直到删除到最後一個數字,直接将數字删除,實作後進先出

資料結構--棧和隊列(C語言)

這道題用C語言,是以需要自己實作一些隊列接口。前面我們寫好直接用

這道題的函數接口中,将兩個隊列放在一個結構體中,myStackCreate中調用接口初始化,傳回結構體指針,與我們上面寫的有所差別,我們上面是直接在test.c中建立一個結構體,把結構體的指針傳過去。

typedef struct {           

} MyStack;

MyStack* myStackCreate() {

}

![圖檔.png](https://s2.51cto.com/images/20211105/1636111112941209.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
兩個地方要區分開來。
但是在我們建立結構體傳回指針時,我們不能這樣建立
```c
MyStack* myStackCreate() {
    Mystack st;
    return &st;
}           

這是我們在棧裡面定義的局部變量,除了作用域就會被銷毀,我可以定義全局變量,但是會出問題,是以我們用malloc在堆裡面定義,這樣出了作用域也不會被銷毀。

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

MyStack* myStackCreate() {
    MyStack* st=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&st->q1);
    QueueInit(&st->q2);
    return st;
}
在釋放函數中
```c
void myStackFree(MyStack* obj) {

}           

因為我們的結構是這樣的

資料結構--棧和隊列(C語言)

需要先釋放兩個隊列,再釋放隊列的結構體

void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);
}           

實作代碼

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int QDataType;

typedef struct QueueNode
{
    QDataType data;
    struct QueueNode* next;
}QueueNode;

typedef struct QueueList
{
    QueueNode* head;
    QueueNode* tail;
}QList;

void QueueInit(QList* ps);
void QueueDestroy(QList* ps);
void QueuePush(QList* ps, QDataType x);
void QueuePop(QList* ps);
QDataType QueueFront(QList* ps);
QDataType QueueBack(QList* ps);
int QueueSize(QList* ps);
bool QueueEmpty(QList* ps);

void QueueInit(QList* ps)
{
    assert(ps);
    ps->head = NULL;
    ps->tail = NULL;
}

void QueueDestroy(QList* ps)
{
    assert(ps);
    QueueNode* cur = ps->head;

    while (cur)
    {
        QueueNode* next = cur->next;
        free(cur);
        cur = next;
    }
    ps->head = ps->tail = NULL;
}
void QueuePush(QList* ps, QDataType x)
{
    assert(ps);
    QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
    newnode->data = x;
    newnode->next = NULL;

    if (ps->tail == NULL)
    {
        ps->tail = ps->head = newnode;

    }
    else
    {
        ps->tail->next = newnode;
        ps->tail = newnode;
    }

}

void QueuePop(QList* ps)
{
    assert(ps);//判斷結構體不為空
    assert(!QueueEmpty(ps));//判斷隊列不為空
    QueueNode* next = ps->head->next;

    free(ps->head);
    ps->head = next;
    if (ps->head == NULL)
    {
        ps->tail = NULL;
    }
}

QDataType QueueFront(QList* ps)
{
    assert(ps);
    assert(!QueueEmpty(ps));
    return ps->head->data;
}

QDataType QueueBack(QList* ps)
{
    assert(ps);
    assert(!QueueEmpty(ps));
    return ps->tail->data;
}

int QueueSize(QList* ps)
{
    assert(ps);

    QueueNode* cur = ps->head;
    int count = 0;
    while (cur)
    {
        ++count;
        cur = cur->next;
    }
    return count;
}
bool QueueEmpty(QList* ps)
{
    assert(ps);
    return ps->head == NULL;
}

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

MyStack* myStackCreate() {
    MyStack* st=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&st->q1);
    QueueInit(&st->q2);
    return st;
}

//如果隊列不為空,則放資料
void myStackPush(MyStack* obj, int x) {
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }
}

//當不為空的隊列資料個數大于1,将資料導入空隊列,并删除
int myStackPop(MyStack* obj) {
    QList* emptyQ=&obj->q1;
    QList* noneemptyQ=&obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        emptyQ=&obj->q2;
        noneemptyQ=&obj->q1;
    }

    while(QueueSize(noneemptyQ)>1)
    {
        QueuePush(emptyQ,QueueFront(noneemptyQ));//放入隊列頭的資料
        QueuePop(noneemptyQ);
    }

    QDataType top=QueueFront(noneemptyQ);
    QueuePop(noneemptyQ);
    return top;//帶傳回值,傳回不為空隊列最後一個資料
}

//誰不是空的,傳回誰的隊尾
int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    else
    {
        return QueueBack(&obj->q2);
    }
}

//兩個都是空才是空
bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);
}           

3.用棧實作隊列

請你僅使用兩個棧實作先入先出隊列。隊列應當支援一般隊列支援的所有操作(push、pop、peek、empty):

實作 MyQueue 類:

void push(int x) 将元素 x 推到隊列的末尾
int pop() 從隊列的開頭移除并傳回元素
int peek() 傳回隊列開頭的元素
boolean empty() 如果隊列為空,傳回 true ;否則,傳回 false           
typedef int STDataType;
typedef struct Stack
{
    STDataType* a;
    int top;
    int capacity;
}ST;

void StackInit(ST* ps);
void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty(ST* ps);

void StackInit(ST* ps)
{
    assert(ps);
    ps->a = NULL;
    ps->top = 0;
    ps->capacity = 0;
}

void StackDestroy(ST* ps)
{
    assert(ps);
    free(ps->a);
    ps->a = NULL;
    ps->capacity = ps->top = 0;
}

void StackPush(ST* ps, STDataType x)
{
    assert(ps);
    if (ps->top == ps->capacity)
    {
        int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
        STDataType* tmp = realloc(ps->a, sizeof(STDataType)*newcapacity);
        if (tmp == NULL)
        {
            printf("realloc fail\n");
            exit(-1);
        }
        ps->a = tmp;
        ps->capacity = newcapacity;
    }
    ps->a[ps->top] = x;
    ps->top++;
}

void StackPop(ST* ps)
{
    assert(ps);
    assert(ps->top > 0);

    ps->top--;
}

STDataType StackTop(ST* ps)
{
    assert(ps);
    assert(ps->top > 0);

    return(ps->a[ps->top-1]);
}

int StackSize(ST* ps)
{
    assert(ps);
    return ps->top;
}

bool StackEmpty(ST* ps)
{
    return ps->top == 0;
}

typedef struct {
    ST pushST;
    ST popST;

} MyQueue;

MyQueue* myQueueCreate() {
    MyQueue* q=(MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&q->pushST);
    StackInit(&q->popST);
    return q;
}

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

//當popST不為空,如果pushST不為空,将資料導入popST再進行删除
int myQueuePop(MyQueue* obj) {
    if(StackEmpty(&obj->popST))
    {
        while(!StackEmpty(&obj->pushST))
        {
            StackPush(&obj->popST,StackTop(&obj->pushST));
            StackPop(&obj->pushST);
        }
    }

    STDataType top=StackTop(&obj->popST);
    StackPop(&obj->popST);
    return top;
}

int myQueuePeek(MyQueue* obj) {
    if(StackEmpty(&obj->popST))
    {
        while(!StackEmpty(&obj->pushST))
        {
            StackPush(&obj->popST,StackTop(&obj->pushST));
            StackPop(&obj->pushST);
        }
    }

    return StackTop(&obj->popST);
}

bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->popST)&&StackEmpty(&obj->pushST);
}

void myQueueFree(MyQueue* obj) {
    StackDestroy(&obj->pushST);
    StackDestroy(&obj->popST);
    free(obj);
}           

3.設計循環隊列

typedef struct {
    int* a;
    int front;
    int tail;
    int k;
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* cq=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    cq->a=(int*)malloc(sizeof(int)*(k+1));
    cq->tail=cq->front=0;
    cq->k=k;

    return cq;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    //滿了不能添加,傳回flase
    if(myCircularQueueIsFull(obj))
        return false;

    obj->a[obj->tail]=value;
    ++obj->tail;
    obj->tail%=(obj->k+1);
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    //空了不能删除,傳回false
    if(myCircularQueueIsEmpty(obj))
        return false;

    ++obj->front;
    obj->front%=(obj->k+1);

    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;

    return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;

    if(obj->tail%(obj->k+1)==0)
    {
        return obj->a[obj->k];
    }
    else
    {
        return obj->a[obj->tail-1];
    }
}

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

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

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}
           

繼續閱讀