隊列是一種 先進先出(first in - first out, FIFO)的數據結構,隊列中的元素都從后端(rear)入隊(push),從前端(front)出隊(pop)。
實現隊列最直觀的方法是用鏈表,但在這篇文章里我會介紹另一個方法 - 使用棧。
棧是一種 后進先出(last in - first out, LIFO)的數據結構,棧中元素從棧頂(top)壓入(push),也從棧頂彈出(pop)。
為了滿足隊列的 FIFO 的特性,我們需要用到兩個棧,用它們其中一個來反轉元素的入隊順序,用另一個來存儲元素的最終順序。
方法一(使用兩個棧 入隊 - O(n)O(n), 出隊 - O(1)O(1))
算法
入隊(push)思路:考慮入隊的元素是先進先出,后進后出,而你的棧是后進先出,那么你最新壓入的元素(后進的)應該在棧底,也就是只要保證后進后出即可
一個隊列是 FIFO 的,但一個棧是 LIFO 的。這就意味着最新壓入的元素必須得放在棧底。為了實現這個目的,我們首先需要把 s1 中所有的元素移到 s2 中,接着把新元素壓入 s2。最后把 s2 中所有的元素彈出,再把彈出的元素壓入 s1。
出隊(pop)
直接從 s1 彈出就可以了,因為 s1 的棧頂元素就是隊列的隊首元素。同時我們把彈出之后 s1 的棧頂元素賦值給代表隊首元素的 front 變量。
以上圖片以及文字來自https://leetcode-cn.com/problems/implement-queue-using-stacks/solution/yong-zhan-shi-xian-dui-lie-by-leetcode/
#include <stdio.h>
#include <stdlib.h>
#define maxsize 100
//創建棧
struct Stack{
int data[maxsize];
int top;
};
typedef struct Stack MyStack;
//隊列定義為雙棧
typedef struct {
MyStack s1; //S1為主棧
MyStack s2; //S2為用來反轉的棧
} MyQueue;
/** Initialize your data structure here. */
MyQueue* myQueueCreate() {
MyQueue * tempQueue =(MyQueue *)malloc(sizeof(MyQueue));
tempQueue->s1.top = -1 ;
tempQueue->s2.top = -1 ;
return tempQueue ;
}
/** Push element x to the back of queue. */
void myQueuePush(MyQueue* obj, int x) {
if(obj->s1.top<maxsize)
{
while(obj->s1.top!=-1) //棧是否滿
{
obj->s2.data[++(obj->s2.top)]=obj->s1.data[(obj->s1.top)--];////把S1棧中元素壓入S2實現反轉
}
obj->s1.data[++(obj->s1.top)]= x ; ////把push的元素壓入S1棧(此時S1為空棧,因為它的元素已經全部給S2啦)
while(obj->s2.top!=-1)
{
obj->s1.data[++(obj->s1.top)]=obj->s2.data[(obj->s2.top)--];//再把S2棧中的元素全部反轉壓入S1
}
}
}
void show_myQueue(MyQueue * obj)
{
int temp =obj->s1.top ;
while(temp!=-1)
{
printf("%d ",obj->s1.data[temp--]);
}
printf("\n");
}
/** Removes the element from in front of queue and returns that element. */
int myQueuePop(MyQueue* obj) {
if(obj->s1.top!=-1)
{
return obj->s1.data[obj->s1.top--] ;
}
// return NULL ;
}
/** Get the front element. */
int myQueuePeek(MyQueue* obj) {
if(obj->s1.top!=-1)
{
return obj->s1.data[obj->s1.top] ;
}
// return NULL ;
}
/** Returns whether the queue is empty. */
bool myQueueEmpty(MyQueue* obj) {
if(obj->s1.top == -1)
return true ;
return false ;
}
void myQueueFree(MyQueue* obj) {
free(obj);
}
int main()
{
int i ;
MyQueue * myQueue =NULL;
myQueue =myQueueCreate();
for(i=0;i<3;i++)
{
myQueuePush(myQueue,i);
}
show_myQueue(myQueue);
printf("出隊的元素是:%d\n",myQueuePop(myQueue));
printf("此時隊列內的首個的元素是:%d\n",myQueuePeek(myQueue));
}
/**
* 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);
*/