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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

LeetCode題目

  • 1、括號匹配問題
  • 2、用隊列實現棧
  • 3、用棧實現隊列
  • 4、設計循環隊列

1、括號匹配問題

LeetCode鏈接: 【20. 有效的括號】

這道題就是經典的利用棧解決問題的例子;思路如下:
遍歷一遍字符串,如果遇倒左括號就入棧,如果遇倒右括號取棧頂的元素進行匹配并出棧頂的元素,如果相匹配就繼續,不匹配就返回false。
但是要注意這樣只能檢驗出左右括號個數相等的情況下才可以,如果左右括號個數不相等呢?

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

代碼實現如下:

//C語言中沒有棧,我們先實現一個棧 //構建棧如下: 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); //獲取棧的元素個數 int StackSize(ST* ps); //獲取棧頂的元素 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;//取棧頂的數據進行匹配case ')':case ']':case '}'://出棧,從棧里面取做括號,棧里面的元素不能為空,//防止右括號過多,導致取到棧里面沒有元素可以取,這也是不匹配if(StackEmpty(&st)){StackDestroy(&st);return false;}//取棧頂的數據和字符比較char top=StackTop(&st);StackPop(&st);if(top=='(' && *s==')' || top=='[' && *s==']' ||top=='{' && *s=='}'){s++;}else{StackDestroy(&st);return false;}}}//最后要判斷棧是否為空//棧是空的說明才完全匹配,如果還要剩余說明沒有是左括號多了,不匹配if(StackEmpty(&st)){StackDestroy(&st);return true;}else{StackDestroy(&st);return false;}}

2、用隊列實現棧

LeetCode鏈接: 【225. 用隊列實現棧】

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


代碼實現如下:

//C語言中沒有隊列,我們先構建一個隊列的各種接口 //隊列實現如下: typedef int DataType; typedef struct Node {struct Node* next;DataType data; }Node;typedef struct Queue {Node* phead;Node* tail; }Queue;//初始化隊列 void QueueInit(Queue* pq); //銷毀隊列 void QueueDestroy(Queue* pq); //隊列插數據 void QueuePush(Queue* pq,DataType x); //隊列出數據 void QueuePop(Queue* pq); //取隊尾數據 DataType QueueBack(Queue* pq); //取隊頭數據 DataType QueueFront(Queue* pq); //取隊列中元素個數 int QueueSize(Queue* pq); //判斷隊列是否為空 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);// 一個節點if (pq->phead->next == NULL){free(pq->phead);pq->phead = NULL;pq->tail = NULL;}//多個節點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; } //上面都是在實現隊列的各種接口//下面是利用兩個隊列來實現棧 //用兩給隊列來實現棧,兩個隊列不斷倒元素即可 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; }//往不為空的隊列插數據,如果兩個隊列都為空,任意一個都行 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);}//先把不為空的隊列往空隊列里面倒數據,倒到只剩下1個元素 //而這不為空的隊列最后一個元素就是棧頂的元素,出掉即可 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);}//最后一個元素就是棧頂的元素//出掉即可,保證隊列有一個為空隊列int tmp=QueueBack(nonempty);QueuePop(nonempty);return tmp;}//直接取不為空的隊列的尾元素即可 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) {//兩給隊列都為空,棧才是空return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2); }void myStackFree(MyStack* obj) {QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj); }

3、用棧實現隊列

LeetCode鏈接: 【232. 用棧實現隊列】

思路分析如下:

代碼實現如下:

//C語言中沒有棧,我們先實現一個棧 //構建棧如下: 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); //獲取棧的元素個數 int StackSize(ST* ps); //獲取棧頂的元素 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; }//兩個棧,把不為空的棧往為空的棧里面倒過來就是隊列了 //設計兩個棧,一個用來入數據,一個用來出數據 //入數據就入pushst棧,出數據就出popst棧 typedef struct {ST Pushst; //入數據棧ST Popst; //出數據棧 } 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); }//要檢驗出數據的棧是否為空,沒有數據了就從入數據的棧里面取 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; }//取隊列的頭元素,檢驗出數據的棧是否為空,沒有數據了就從入數據的棧里面取 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、設計循環隊列

LeetCode鏈接: 【622. 設計循環隊列】

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

所以循環隊列的結構搞清楚了,寫起來就比較簡單了,循環隊列有兩種實現方式,可以使用數組實現,也可以使用循環鏈表實現。下面分別來介紹。
鏈表實現如下:

//先創建一個結點類型 typedef struct Node {struct Node* next;int data; }Node;//創建一個循環隊列類型結構體 //里面的頭指針指向鏈表的頭,尾指針指向鏈表的尾 typedef struct {Node* front;Node* tail; } MyCircularQueue;//創建循環隊列 MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* tmp=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));//構造一個環鏈表//要多構造一個結點,不然判斷不了是否滿了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;}//向循環隊列插入一個元素 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;}//從循環隊列中刪除一個元素 bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(obj->front==obj->tail){return false;}obj->front=obj->front->next;return true;}//從隊首獲取元素 int myCircularQueueFront(MyCircularQueue* obj) {if(obj->front==obj->tail){return -1;}return obj->front->data;}//獲取隊尾元素 int myCircularQueueRear(MyCircularQueue* obj) {if(obj->front==obj->tail){return -1;}//找隊尾的前一個結點就是隊尾數據Node* cur=obj->front;while(cur->next!=obj->tail){cur=cur->next;}return cur->data;}//檢查循環隊列是否為空 bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front==obj->tail;}//檢查循環隊列是否已滿。 bool myCircularQueueIsFull(MyCircularQueue* obj) {return obj->tail->next==obj->front;}//釋放內存 void myCircularQueueFree(MyCircularQueue* obj) {Node* cur=obj->front;while(cur!=obj->tail){Node* next=cur->next;free(cur);cur=next;}free(cur);free(obj); }

數組方式實現如下:

代碼實現如下:

//在循環隊列結構中設計一個指針指向一段連續的空間 typedef struct {int* a;int maxSize;int head;int tail; } MyCircularQueue;bool myCircularQueueIsFull(MyCircularQueue* obj);//創建循環隊列 MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* tmp=(MyCircularQueue*)malloc(sizeof(MyCircularQueue)); //要多開辟一個空間int* arr=(int*)malloc(sizeof(int)*(k+1));tmp->a=arr;tmp->maxSize=k+1;tmp->head=0;tmp->tail=0;return tmp; }//向循環隊列插入一個元素 bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj)){return false;}obj->a[obj->tail]=value;obj->tail++;//把下標tail控制在數組中,不能越界if(obj->tail==obj->maxSize){obj->tail=0;}return true; }//從循環隊列中刪除一個元素 bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(obj->head==obj->tail){return false;}obj->head++;if(obj->head==obj->maxSize){obj->head=0;}return true; }//從隊首獲取元素 int myCircularQueueFront(MyCircularQueue* obj) {if(obj->head==obj->tail){return -1;}return obj->a[obj->head];}//獲取隊尾元素 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]; }//檢查循環隊列是否為空 bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->head==obj->tail; }//檢查循環隊列是否已滿 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); }

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。