日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【LeetCode之栈和队列】:关于栈和队列经典的OJ题(用C语言实现,附图详解)

發(fā)布時(shí)間:2023/12/8 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【LeetCode之栈和队列】:关于栈和队列经典的OJ题(用C语言实现,附图详解) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

LeetCode題目

  • 1、括號(hào)匹配問題
  • 2、用隊(duì)列實(shí)現(xiàn)棧
  • 3、用棧實(shí)現(xiàn)隊(duì)列
  • 4、設(shè)計(jì)循環(huán)隊(duì)列

1、括號(hào)匹配問題

LeetCode鏈接: 【20. 有效的括號(hào)】

這道題就是經(jīng)典的利用棧解決問題的例子;思路如下:
遍歷一遍字符串,如果遇倒左括號(hào)就入棧,如果遇倒右括號(hào)取棧頂?shù)脑剡M(jìn)行匹配并出棧頂?shù)脑?#xff0c;如果相匹配就繼續(xù),不匹配就返回false。
但是要注意這樣只能檢驗(yàn)出左右括號(hào)個(gè)數(shù)相等的情況下才可以,如果左右括號(hào)個(gè)數(shù)不相等呢?

  • 如果左括號(hào)多于右括號(hào),并且遍歷結(jié)束后它們都是匹配的,這種情況并不是完全匹配的,因?yàn)闂@镞€有元素剩余;所以遍歷字符串后要加一個(gè)判斷棧是否為空,只要棧為空了才是全部匹配完,沒有剩余。 比如:“[[[[[((()))”
  • 如果右括號(hào)多余左括號(hào),有可能導(dǎo)致棧是空的,棧里面沒有元素可以取了,這種情況也是不匹配的;所以取棧頂元素的前面要加一個(gè)判斷棧是否為空,如果棧為空說明右括號(hào)多余左括號(hào),是不匹配的。比如:”((([[[ ]]]]]]]]]"

代碼實(shí)現(xiàn)如下:

//C語言中沒有棧,我們先實(shí)現(xiàn)一個(gè)棧 //構(gòu)建棧如下: typedef char STDataType; struct Stack {STDataType* a;int top;int capacity; }; typedef struct Stack ST;//初始化棧 void StackInit(ST* ps); //銷毀棧 void StackDestroy(ST* ps); //入棧 void StackPush(ST* ps, STDataType x); //出棧 void StackPop(ST* ps); //獲取棧的元素個(gè)數(shù) int StackSize(ST* ps); //獲取棧頂?shù)脑?/span> STDataType StackTop(ST* ps); //判斷棧是否為空 bool StackEmpty(ST* ps);void StackInit(ST* ps) {ps->a = NULL;ps->capacity = 0;ps->top = 0; }void StackDestroy(ST* ps) {free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0; }void StackPush(ST* ps,STDataType x) {assert(ps);if (ps->capacity == ps->top){ps->capacity = ps->capacity > 0 ? ps->capacity * 2 : 2;STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * sizeof(STDataType));if (tmp == NULL){return;}else{ps->a = tmp;}}ps->a[ps->top] = x;ps->top++; }void StackPop(ST* ps) {assert(ps);assert(ps->top > 0);ps->top--; }int StackSize(ST* ps) {assert(ps);assert(ps->top > 0);return ps->top; }STDataType StackTop(ST* ps) {assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1]; }bool StackEmpty(ST* ps) {assert(ps);return ps->top == 0; }bool isValid(char * s){ST st;StackInit(&st);while(*s!='\0'){switch(*s){//壓棧case '(':case '[':case '{':StackPush(&st,*s);s++;break;//取棧頂?shù)臄?shù)據(jù)進(jìn)行匹配case ')':case ']':case '}'://出棧,從棧里面取做括號(hào),棧里面的元素不能為空,//防止右括號(hào)過多,導(dǎo)致取到棧里面沒有元素可以取,這也是不匹配if(StackEmpty(&st)){StackDestroy(&st);return false;}//取棧頂?shù)臄?shù)據(jù)和字符比較char top=StackTop(&st);StackPop(&st);if(top=='(' && *s==')' || top=='[' && *s==']' ||top=='{' && *s=='}'){s++;}else{StackDestroy(&st);return false;}}}//最后要判斷棧是否為空//棧是空的說明才完全匹配,如果還要剩余說明沒有是左括號(hào)多了,不匹配if(StackEmpty(&st)){StackDestroy(&st);return true;}else{StackDestroy(&st);return false;}}

2、用隊(duì)列實(shí)現(xiàn)棧

LeetCode鏈接: 【225. 用隊(duì)列實(shí)現(xiàn)棧】

思路: 這是要我們利用隊(duì)列的性質(zhì)去實(shí)現(xiàn)棧,隊(duì)列的性質(zhì)是先入先出,而棧的性質(zhì)是后入先出;
所以我們利用兩個(gè)隊(duì)列來實(shí)現(xiàn)棧,一個(gè)為空隊(duì)列,一個(gè)不為空隊(duì)列;入棧:就往不為空的隊(duì)列里面入,而 出棧就是: 只保留不為空的隊(duì)列的最后一個(gè)元素,前面的元素都插入空隊(duì)列中;然后再把最后一個(gè)元素出掉就是出棧了。


代碼實(shí)現(xiàn)如下:

//C語言中沒有隊(duì)列,我們先構(gòu)建一個(gè)隊(duì)列的各種接口 //隊(duì)列實(shí)現(xiàn)如下: typedef int DataType; typedef struct Node {struct Node* next;DataType data; }Node;typedef struct Queue {Node* phead;Node* tail; }Queue;//初始化隊(duì)列 void QueueInit(Queue* pq); //銷毀隊(duì)列 void QueueDestroy(Queue* pq); //隊(duì)列插數(shù)據(jù) void QueuePush(Queue* pq,DataType x); //隊(duì)列出數(shù)據(jù) void QueuePop(Queue* pq); //取隊(duì)尾數(shù)據(jù) DataType QueueBack(Queue* pq); //取隊(duì)頭數(shù)據(jù) DataType QueueFront(Queue* pq); //取隊(duì)列中元素個(gè)數(shù) int QueueSize(Queue* pq); //判斷隊(duì)列是否為空 bool QueueEmpty(Queue* pq);void QueueInit(Queue* pq) {assert(pq);pq->phead = NULL;pq->tail = NULL; }void QueuePush(Queue* pq, DataType x) {Node* tmp = (Node*)malloc(sizeof(Node));if (tmp == NULL){perror("malloc ");exit(-1);}tmp->data = x;tmp->next = NULL;if (pq->tail == NULL){pq->phead = tmp;pq->tail = tmp;}else{pq->tail->next = tmp;pq->tail = tmp;} }void QueuePop(Queue* pq) {assert(pq);assert(pq->phead);// 一個(gè)節(jié)點(diǎn)if (pq->phead->next == NULL){free(pq->phead);pq->phead = NULL;pq->tail = NULL;}//多個(gè)節(jié)點(diǎn)else{Node* tmp = pq->phead->next;free(pq->phead);pq->phead = tmp;} }int QueueSize(Queue* pq) {assert(pq);int count = 0;Node* cur = pq->phead;while (cur != NULL){cur = cur->next;count++;}return count; }bool QueueEmpty(Queue* pq) {assert(pq);return pq->phead == NULL; }DataType QueueFront(Queue* pq) {assert(pq);assert(pq->phead);return pq->phead->data; }DataType QueueBack(Queue* pq) {assert(pq);assert(pq->phead);return pq->tail->data; }void QueueDestroy(Queue* pq) {assert(pq);Node* tmp = pq->phead;while (tmp != NULL){Node* next = tmp->next;free(tmp);tmp = next;}pq->phead = pq->tail = NULL; } //上面都是在實(shí)現(xiàn)隊(duì)列的各種接口//下面是利用兩個(gè)隊(duì)列來實(shí)現(xiàn)棧 //用兩給隊(duì)列來實(shí)現(xiàn)棧,兩個(gè)隊(duì)列不斷倒元素即可 typedef struct {Queue q1;Queue q2; } MyStack;MyStack* myStackCreate() {MyStack* tmp=(MyStack*)malloc(sizeof(MyStack));if(tmp==NULL){perror("erron ");exit(-1);}QueueInit(&tmp->q1);QueueInit(&tmp->q2);return tmp; }//往不為空的隊(duì)列插數(shù)據(jù),如果兩個(gè)隊(duì)列都為空,任意一個(gè)都行 void myStackPush(MyStack* obj, int x) {Queue* empty=&obj->q1;Queue* nonempty=&obj->q2;if(QueueEmpty(&obj->q2)){Queue* empty=&obj->q2;Queue* nonempty=&obj->q1;}QueuePush(nonempty,x);}//先把不為空的隊(duì)列往空隊(duì)列里面倒數(shù)據(jù),倒到只剩下1個(gè)元素 //而這不為空的隊(duì)列最后一個(gè)元素就是棧頂?shù)脑?#xff0c;出掉即可 int myStackPop(MyStack* obj) {Queue* empty=&obj->q1;Queue* nonempty=&obj->q2;if(QueueEmpty(&obj->q2)){empty=&obj->q2;nonempty=&obj->q1;}while(QueueSize(nonempty)>1){QueuePush(empty,QueueFront(nonempty));QueuePop(nonempty);}//最后一個(gè)元素就是棧頂?shù)脑?/span>//出掉即可,保證隊(duì)列有一個(gè)為空隊(duì)列int tmp=QueueBack(nonempty);QueuePop(nonempty);return tmp;}//直接取不為空的隊(duì)列的尾元素即可 int myStackTop(MyStack* obj) {Queue* empty=&obj->q1;Queue* nonempty=&obj->q2;if(QueueEmpty(&obj->q2)){empty=&obj->q2;nonempty=&obj->q1;}return QueueBack(nonempty); }bool myStackEmpty(MyStack* obj) {//兩給隊(duì)列都為空,棧才是空return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2); }void myStackFree(MyStack* obj) {QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj); }

3、用棧實(shí)現(xiàn)隊(duì)列

LeetCode鏈接: 【232. 用棧實(shí)現(xiàn)隊(duì)列】

思路分析如下:

代碼實(shí)現(xiàn)如下:

//C語言中沒有棧,我們先實(shí)現(xiàn)一個(gè)棧 //構(gòu)建棧如下: typedef int STDataType; struct Stack {STDataType* a;int top;int capacity; }; typedef struct Stack ST;//初始化棧 void StackInit(ST* ps); //銷毀棧 void StackDestroy(ST* ps); //入棧 void StackPush(ST* ps, STDataType x); //出棧 void StackPop(ST* ps); //獲取棧的元素個(gè)數(shù) int StackSize(ST* ps); //獲取棧頂?shù)脑?/span> STDataType StackTop(ST* ps); //判斷棧是否為空 bool StackEmpty(ST* ps);void StackInit(ST* ps) {ps->a = NULL;ps->capacity = 0;ps->top = 0; }void StackDestroy(ST* ps) {free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0; }void StackPush(ST* ps,STDataType x) {assert(ps);if (ps->capacity == ps->top){ps->capacity = ps->capacity > 0 ? ps->capacity * 2 : 2;STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * sizeof(STDataType));if (tmp == NULL){return;}else{ps->a = tmp;}}ps->a[ps->top] = x;ps->top++; }void StackPop(ST* ps) {assert(ps);assert(ps->top > 0);ps->top--; }int StackSize(ST* ps) {assert(ps);assert(ps->top > 0);return ps->top; }STDataType StackTop(ST* ps) {assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1]; }bool StackEmpty(ST* ps) {assert(ps);return ps->top == 0; }//兩個(gè)棧,把不為空的棧往為空的棧里面倒過來就是隊(duì)列了 //設(shè)計(jì)兩個(gè)棧,一個(gè)用來入數(shù)據(jù),一個(gè)用來出數(shù)據(jù) //入數(shù)據(jù)就入pushst棧,出數(shù)據(jù)就出popst棧 typedef struct {ST Pushst; //入數(shù)據(jù)棧ST Popst; //出數(shù)據(jù)棧 } MyQueue;MyQueue* myQueueCreate() {MyQueue* tmp=(MyQueue*)malloc(sizeof(MyQueue));if(tmp==NULL){perror("erron ");exit(-1);}StackInit(&tmp->Pushst);StackInit(&tmp->Popst);return tmp; }void myQueuePush(MyQueue* obj, int x) {StackPush(&obj->Pushst,x); }//要檢驗(yàn)出數(shù)據(jù)的棧是否為空,沒有數(shù)據(jù)了就從入數(shù)據(jù)的棧里面取 int myQueuePop(MyQueue* obj) {if(StackEmpty(&obj->Popst)){while(!StackEmpty(&obj->Pushst)){StackPush(&obj->Popst,StackTop(&obj->Pushst));StackPop(&obj->Pushst);}}int tmp=StackTop(&obj->Popst);StackPop(&obj->Popst);return tmp; }//取隊(duì)列的頭元素,檢驗(yàn)出數(shù)據(jù)的棧是否為空,沒有數(shù)據(jù)了就從入數(shù)據(jù)的棧里面取 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->Pushst) && StackEmpty(&obj->Popst); }void myQueueFree(MyQueue* obj) {StackDestroy(&obj->Pushst);StackDestroy(&obj->Pushst);free(obj); }

4、設(shè)計(jì)循環(huán)隊(duì)列

LeetCode鏈接: 【622. 設(shè)計(jì)循環(huán)隊(duì)列】

做這道題之前,我們先來了解什么是循環(huán)隊(duì)列?它的解釋如下:
循環(huán)隊(duì)列是把順序隊(duì)列首尾相連,把存儲(chǔ)隊(duì)列元素的表從邏輯上看成一個(gè)環(huán),成為循環(huán)隊(duì)列。
循環(huán)隊(duì)列就是將隊(duì)列存儲(chǔ)空間的最后一個(gè)位置繞到第一個(gè)位置,形成邏輯上的環(huán)狀空間,供隊(duì)列循環(huán)使用。在循環(huán)隊(duì)列結(jié)構(gòu)中,當(dāng)存儲(chǔ)空間的最后一個(gè)位置已被使用而再要進(jìn)入隊(duì)運(yùn)算時(shí),只需要存儲(chǔ)空間的第一個(gè)位置空閑,便可將元素加入到第一個(gè)位置,即將存儲(chǔ)空間的第一個(gè)位置作為隊(duì)尾。
循環(huán)隊(duì)列可以更簡(jiǎn)單防止偽溢出的發(fā)生,但隊(duì)列大小是固定的。

所以循環(huán)隊(duì)列的結(jié)構(gòu)搞清楚了,寫起來就比較簡(jiǎn)單了,循環(huán)隊(duì)列有兩種實(shí)現(xiàn)方式,可以使用數(shù)組實(shí)現(xiàn),也可以使用循環(huán)鏈表實(shí)現(xiàn)。下面分別來介紹。
鏈表實(shí)現(xiàn)如下:

//先創(chuàng)建一個(gè)結(jié)點(diǎn)類型 typedef struct Node {struct Node* next;int data; }Node;//創(chuàng)建一個(gè)循環(huán)隊(duì)列類型結(jié)構(gòu)體 //里面的頭指針指向鏈表的頭,尾指針指向鏈表的尾 typedef struct {Node* front;Node* tail; } MyCircularQueue;//創(chuàng)建循環(huán)隊(duì)列 MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* tmp=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));//構(gòu)造一個(gè)環(huán)鏈表//要多構(gòu)造一個(gè)結(jié)點(diǎn),不然判斷不了是否滿了Node* head=(Node*)malloc(sizeof(Node));Node* a=head;Node* tail=head;while(k--){a=tail;tail=(Node*)malloc(sizeof(Node));a->next=tail;}tail->next=head;tmp->front=head;tmp->tail=head;return tmp;}//向循環(huán)隊(duì)列插入一個(gè)元素 bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(obj->tail->next==obj->front){return false;}obj->tail->data=value;obj->tail=obj->tail->next;return true;}//從循環(huán)隊(duì)列中刪除一個(gè)元素 bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(obj->front==obj->tail){return false;}obj->front=obj->front->next;return true;}//從隊(duì)首獲取元素 int myCircularQueueFront(MyCircularQueue* obj) {if(obj->front==obj->tail){return -1;}return obj->front->data;}//獲取隊(duì)尾元素 int myCircularQueueRear(MyCircularQueue* obj) {if(obj->front==obj->tail){return -1;}//找隊(duì)尾的前一個(gè)結(jié)點(diǎn)就是隊(duì)尾數(shù)據(jù)Node* cur=obj->front;while(cur->next!=obj->tail){cur=cur->next;}return cur->data;}//檢查循環(huán)隊(duì)列是否為空 bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front==obj->tail;}//檢查循環(huán)隊(duì)列是否已滿。 bool myCircularQueueIsFull(MyCircularQueue* obj) {return obj->tail->next==obj->front;}//釋放內(nèi)存 void myCircularQueueFree(MyCircularQueue* obj) {Node* cur=obj->front;while(cur!=obj->tail){Node* next=cur->next;free(cur);cur=next;}free(cur);free(obj); }

數(shù)組方式實(shí)現(xiàn)如下:

代碼實(shí)現(xiàn)如下:

//在循環(huán)隊(duì)列結(jié)構(gòu)中設(shè)計(jì)一個(gè)指針指向一段連續(xù)的空間 typedef struct {int* a;int maxSize;int head;int tail; } MyCircularQueue;bool myCircularQueueIsFull(MyCircularQueue* obj);//創(chuàng)建循環(huán)隊(duì)列 MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* tmp=(MyCircularQueue*)malloc(sizeof(MyCircularQueue)); //要多開辟一個(gè)空間int* arr=(int*)malloc(sizeof(int)*(k+1));tmp->a=arr;tmp->maxSize=k+1;tmp->head=0;tmp->tail=0;return tmp; }//向循環(huán)隊(duì)列插入一個(gè)元素 bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj)){return false;}obj->a[obj->tail]=value;obj->tail++;//把下標(biāo)tail控制在數(shù)組中,不能越界if(obj->tail==obj->maxSize){obj->tail=0;}return true; }//從循環(huán)隊(duì)列中刪除一個(gè)元素 bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(obj->head==obj->tail){return false;}obj->head++;if(obj->head==obj->maxSize){obj->head=0;}return true; }//從隊(duì)首獲取元素 int myCircularQueueFront(MyCircularQueue* obj) {if(obj->head==obj->tail){return -1;}return obj->a[obj->head];}//獲取隊(duì)尾元素 int myCircularQueueRear(MyCircularQueue* obj) {if(obj->head==obj->tail){return -1;}int i=0;if(obj->tail==0){i=obj->maxSize-1;}else{i=obj->tail-1;}return obj->a[i]; }//檢查循環(huán)隊(duì)列是否為空 bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->head==obj->tail; }//檢查循環(huán)隊(duì)列是否已滿 bool myCircularQueueIsFull(MyCircularQueue* obj) {//方法1判斷是否滿了// return obj->head==(obj->tail+1)%obj->maxSize;//方法2判斷是否滿了int head=0;if(obj->head==0){head=obj->maxSize-1;}else{head=obj->head-1;}return head==obj->tail;}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);free(obj); }

總結(jié)

以上是生活随笔為你收集整理的【LeetCode之栈和队列】:关于栈和队列经典的OJ题(用C语言实现,附图详解)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。