數據結構與算法之隊列、棧
除了數組、鏈表,線性的數據結構中還有很重要的幾種結構: 隊列、棧 。
隊列,一種先進先出的數據結構(FIFO),其實隊列可以看成是一個兩個口的管道,從一個口進,另一個口出,先進去的必定得在另一個口先出去,否則后面的都出不去;棧,一種后進先出的數據結構(LIFO),棧更像是只有一個口的管道,只有一個開口可以進出,先進去的在底部,所以必須得讓后進去的先出去,它才能出去。
實現隊列和棧可以用順序存儲結構,也可以用鏈式存儲結構。這里采用的是鏈表來實現,同時還有用兩個棧實現一個隊列和用兩個隊列實現一個棧的算法(采用STL中的queue和stack)。
1、隊列
隊列中最常用的操作就是入隊列(push),出隊列(pop),查看隊首的值(front)。入隊列是加入隊列的尾部,出隊列是刪除最前面的節點。
typedef struct ListNode{ int element; int *next; }ListNode; typedef struct LinkedQueue{ int size; ListNode *front; ListNode *back; }LinkedQueue; /* alloc a node.*/ ListNode* allocNode(int element){ ListNode *pNode = (ListNode*)malloc(sizeof(ListNode)); if(pNode){ pNode->element = elemnt; pNode->next = NULL; } return pNode; } /* alloc a queue.*/ LinkedQueue* allocLinkedQueue(){ LinkedQueue *pQueue = (LinkedQueue*)malloc(sizeof(LinkedQueue)); if(pQueue){ pQueue->size = 0; pQueue->front = NULL; pQueue->back = NULL; } return pQueue; } /* pop a node out of the queue.*/ bool pop(LinkedQueue *pQueue){ if(NULL == pQueue) return false; LinkedQueue *pNode = pQueue->front; if(pQueue->front == pQueue->back) pQueue->back = NULL; pQueue->front = pQueue->front->next; free(pNode); pQueue->size --; return true; } /* push a node into the queue.*/ bool push(LinkedQueue *pQueue,int element){ if(NULL == pQueue) return false; pQueue->size ++; if(NULL == pQueue->front){ pQueue->front = pQueue->back = allocNode(element); } else pQueue->back = allocNode(element); return true; } /* get the front element from the queue.*/ bool front(LinkedQueue *pQueue,int *element){ if(pQueue->size){ *element = pQueue->front->element; return true; } else return false; }
2、棧
棧中最常用的操作就是入棧(push),出棧(pop),查看棧頂的值(front)。入棧是加入棧的頂部,出棧刪除棧頂的節點。
typedef struct ListNode{ int element; struct ListNode *next; }ListNode; typedef struct LinkedStack{ ListNode *topNode; ListNode *downNode; int stackLength; }LinkedStack; /* get the top node from the stack.*/ int top(LinkedStack *pStack){ return pStack->topNode->element; } /* pop the top node from the stack.*/ void pop(LinkedStack **pStack){ ListNode *pNode = (*pStack)->topNode->next; free(*pStack); *pStack = pNode; } ListNode* allocNode(int element){ ListNode *pNode = (ListNode*)malloc(sizeof(ListNode)); if(NULL != pNode){ pNode->element = element; pNode->next = NULL; } return pNode; } /* push a node into the stack.*/ void push(LinkedStack **pStack,int element){ ListNode *pNode = allocNode(element); pNode->next = (*pStack)->topNode; (*pStack)->topNode = pNode; }
3、用兩個棧實現一個隊列
隊列是先進先出,而棧是后進先出,怎么在棧中實現讓一個元素先進先出?關鍵是利用好另一個棧。隊列中主要的操作也不過就是push(),pop(),front()。
實現push就跟棧中的push一樣,完全不需要修改。而要實現pop和front呢?這就需要借助另一個棧。首先在棧stack1中 push,當有pop或者front操作時,我們把元素從stack1中出棧并壓入stack2中。這樣stack1中底部的元素就變為stack2頂部的元素了,然后從stack2中執行pop或者front操作。以后的pop或者front操作,都先從stack2中執行,當stack2中元素 size為0時,就從stack1中出棧并壓入stack2中然后執行;而每次pop操作只需要在stack1中執行。
bool pop(){ if(!pQueue.stack2.size() && !pQueue.stack1.size()) return false; if(!pQueue.stack2.size()){ while(pQueue.stack1.size()){ pQueue.stack2.push(pQueue.stack1.top()); pQueue.stack1.pop(); } } pQueue.stack2.pop(); return true; } int front(){ if(!pQueue.stack2.size()){ while(pQueue.stack1.size()){ pQueue.stack2.push(pQueue.stack1.top()); pQueue.stack1.pop(); } } return pQueue.stack2.top(); }
4、用兩個隊列實現一個棧
棧中最主要的操作就是push(),pop(),top()。
push操作每次把元素加入到queue1中即可,而pop和top操作就需要借助另一個隊列了。假設queue1中壓入了5個元素:1,2,3,4,5。則此時需要pop,也就是刪除元素5。那么現在就需要把元素1,2,3,4pop了,才能pop元素5,但是棧操作中元素 1,2,3,4不應該被pop掉,所以,就需要把1,2,3,4push到queue2中。每次pop操作,就先檢查queue1中是否有元素,如果有n 個元素,就把前面的n-1個元素pop,然后push到queue2中,然后執行pop;否則,就先把queue2中的n-1元素轉移到queue1中,然后執行pop操作。top操作與pop操作類似。
bool pop(){ if(!pStack.queue1.size() && !pStack.queue2.size()) return false; if(pStack.queue1.size()) { while(pStack.queue1.size() != 1){ pStack.queue2.push(pStack.queue1.front()); pStack.queue1.pop(); } pStack.queue1.pop(); return true; } else{ while(pStack.queue2.size() != 1){ pStack.queue1.push(pStack.queue2.front()); pStack.queue2.pop(); } pStack.queue2.pop(); return true; } } int top(){ if(pStack.queue1.size()) { while(pStack.queue1.size() != 1){ pStack.queue2.push(pStack.queue1.front()); pStack.queue1.pop(); } return pStack.queue1.front(); } else{ while(pStack.queue2.size() != 1){ pStack.queue1.push(pStack.queue2.front()); pStack.queue2.pop(); } int top = pStack.queue2.front(); pStack.queue2.pop() pStack.queue1.push(top); return top; } }
完整代碼詳見: https://github.com/whc2uestc/DataStructure-Algorithm