【数据结构-栈和队列】详解栈和队列(代码+STL+原理)
一、棧的應(yīng)用
棧是一種先進(jìn)后出(FILO)的數(shù)據(jù)結(jié)構(gòu)
1.1 棧的操作實(shí)現(xiàn)
清空(clear):
// 棧的清空操作就是把棧頂top置為-1 void clear(){top=-1; } // 清空棧,由于沒有直接用于清空棧的元素,所以使用while和pop組合 while(!st.size()) st.pop();獲取棧內(nèi)元素個(gè)數(shù)(size):
// 由于棧頂指針top始終指向棧頂元素,而下標(biāo)是從0開始的,所以棧內(nèi)元素要把top+1 int size(){return top+1; }判空(empty):
// 由棧頂指針top判斷的定義可知,僅當(dāng)top==-1是為空,返回true,否則返回false bool empty(){if(top==-1) return true; //棧空else return false; //棧非空 }進(jìn)棧(push):
// push(x)操作將元素x置于棧頂,由于top始終指向棧頂元素,所以需要把top+1然后再把x存入top位置 void push(int x){st[++top]=x; }出棧(pop):
// pop()操作將棧頂元素出棧,而事實(shí)上可以將棧頂指針-1來實(shí)現(xiàn)這個(gè)效果 void pop(){top--; }取棧頂元素(top):
// 由于棧頂指針top始終指向棧頂元素,所以st[top]就是棧頂元素 int top(){return st[top]; }1.2 STL中stack的常見用法
棧,后進(jìn)先出(FILO)
stack的定義:
// 定義一個(gè)stack需要添加頭文件#include <stack> stack<int> st;stack容器內(nèi)的元素訪問:
// 只能通過top()函數(shù)來訪問棧頂元素 st.top();push()函數(shù):
// push(x)將x入棧 st.push(1);top()函數(shù):
// top()函數(shù)獲得棧頂元素 st.top();pop()函數(shù):
// 使用pop()函數(shù)彈出棧頂元素 st.pop();empty()函數(shù):
// empty()可以檢測stack內(nèi)是否為空,true為空,false為非空 if(st.enpty()==true)size()函數(shù):
// 通過size()函數(shù)來獲得棧的元素個(gè)數(shù) st.size();1.3 使用隊(duì)列實(shí)現(xiàn)棧
class MyStack { public:/** Initialize your data structure here. */MyStack() {}/** Push element x onto stack. */void push(int x) {queue<int> tempQ;tempQ.push(x);while(!data.empty()) {tempQ.push(data.front());data.pop();}while(!tempQ.empty()){data.push(tempQ.front());tempQ.pop();}}/** Removes the element on top of the stack and returns that element. */int pop() {int ans = data.front();data.pop();return ans;}/** Get the top element. */int top() {return data.front();}/** Returns whether the stack is empty. */bool empty() {return data.empty();} private:queue<int> data; };二、隊(duì)列
隊(duì)列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),通常用一個(gè)隊(duì)首元素front指向 隊(duì)首元素的前一個(gè)位置, 而使用隊(duì)尾指針來指向隊(duì)尾元素。
初始狀態(tài)(隊(duì)空條件)∶$Q.front() ==Q.rear()==0 $
進(jìn)隊(duì)操作∶隊(duì)不滿時(shí),先送值到隊(duì)尾元素,再將隊(duì)尾指針加1
出隊(duì)操作∶隊(duì)不空時(shí),先取隊(duì)頭元素值,再將隊(duì)頭指針加1
但 Q.rear()==sizeQ.rear() == sizeQ.rear()==size 不能作為隊(duì)滿的條件。
如下圖所示,Q.rear()==sizeQ.rear() == sizeQ.rear()==size 滿足前面的條件,但是顯然,整個(gè)隊(duì)列還有可以添加的其他元素的(未滿)
2.1 隊(duì)列的操作實(shí)現(xiàn)
清空(clear):
// 使用數(shù)組來實(shí)現(xiàn)隊(duì)列是,初始狀態(tài)為front=-1,rear=-1 void clear(){front=rear=-1; }獲得隊(duì)列中的元素個(gè)數(shù)(size):
// rear-front是隊(duì)列內(nèi)元素的個(gè)數(shù) int size(){return rear-front; }判空(empty):
// 若rear等于front,則隊(duì)列為空 bool empty(){if(front==rear) return true;else return false; }入隊(duì)(push):
// 入隊(duì),由于指針rear指向隊(duì)尾元素,因此把元素入隊(duì)時(shí),需要先把rear+1,在存放到rear指向的位置 void push(int x){q[++rear]=x; }出隊(duì)(pop):
// 直接把隊(duì)首指針加1來實(shí)現(xiàn)出隊(duì)效果 void pop(){front++; }取隊(duì)首元素(get_front):
// 由于隊(duì)首指針front指向的隊(duì)首元素的前一個(gè)元素,因此front+1才是隊(duì)首元素的位置 int get_front(){return q[front+1]; }取隊(duì)尾元素(get_rear):
// 由于隊(duì)尾指針rear指向的隊(duì)尾元素,因此直接訪問rear是隊(duì)尾元素的位置 int get_rear(){return q[rear]; }2.2 STL中queue的常見用法
2.3 使用棧實(shí)現(xiàn)隊(duì)列
class MyQueue { public:/** Initialize your data structure here. */MyQueue() {}/** Push element x to the back of queue. */void push(int x) {stack<int> tempS;while(!data.empty()) {tempS.push(data.top());data.pop();}tempS.push(x);while(!tempS.empty()){data.push(tempS.top());tempS.pop();}}/** Removes the element from in front of queue and returns that element. */int pop() {int ans = data.top();data.pop();return ans;}/** Get the front element. */int peek() {return data.top();}/** Returns whether the queue is empty. */bool empty() {return data.empty();} private:stack<int> data; };2.4 循環(huán)隊(duì)列
如前面所講,隊(duì)列在判斷隊(duì)滿的情況下力有不逮,所以就引出了循環(huán)隊(duì)列。
將循環(huán)隊(duì)列想象成一個(gè)環(huán)狀的空間,即在邏輯上視為一個(gè)環(huán)。
初始時(shí):Q.front==Q.rear==0Q.front==Q.rear==0Q.front==Q.rear==0
隊(duì)首指針進(jìn)1:Q.front=(Q.front+1)%MaxSizeQ.front=(Q.front+1)\%MaxSizeQ.front=(Q.front+1)%MaxSize
隊(duì)尾指針進(jìn)1:Q.rear=(Q.rear+1)%MaxSizeQ.rear=(Q.rear+1)\%MaxSizeQ.rear=(Q.rear+1)%MaxSize
隊(duì)列長度:len=(Q.rear+MaxSize?Q.front)%MaxSizelen=(Q.rear+MaxSize-Q.front)\%MaxSizelen=(Q.rear+MaxSize?Q.front)%MaxSize
為了區(qū)分隊(duì)空還是隊(duì)滿的情況,有三種處理方式∶
犧牲一個(gè)單元來區(qū)分隊(duì)空和隊(duì)滿,入隊(duì)時(shí)少用一個(gè)隊(duì)列單元,這是一種較為普遍的做法,約定以**“隊(duì)頭指針在隊(duì)尾指針的下一位置作為隊(duì)滿的標(biāo)志”**,如圖下圖e所示。
隊(duì)滿條件:(Q.rear+1)%MaxSize==Q.front(Q.rear+1)\%MaxSize==Q.front(Q.rear+1)%MaxSize==Q.front
隊(duì)空條件仍:Q.front==Q.rearQ.front==Q.rearQ.front==Q.rear
隊(duì)列中元素的個(gè)數(shù):(Q.rear?Q.front+MaxSize)%MaxSize(Q.rear-Q.front+MaxSize)\% MaxSize(Q.rear?Q.front+MaxSize)%MaxSize
類型中增設(shè)表示元素個(gè)數(shù)的數(shù)據(jù)成員。這樣,隊(duì)空的條件為 Q.size==0Q.size==0Q.size==0;隊(duì)滿的條件為 Q.size==MaxSizeQ.size==MaxSizeQ.size==MaxSize;這兩種情況都有 Q.front==Q.rearQ.front==Q.rearQ.front==Q.rear 。
類型中增設(shè) tag 數(shù)據(jù)成員,以區(qū)分是隊(duì)滿還是隊(duì)空。tag==0tag == 0tag==0 時(shí),若因刪除導(dǎo)致 Q.front==Q.rearQ.front==Q.rearQ.front==Q.rear,則為隊(duì)空;tag==1tag==1tag==1 時(shí),若因插入導(dǎo)致 Q.front==Q.rearQ.front==Q.rearQ.front==Q.rear,則為隊(duì)滿。
2.5 雙端隊(duì)列
雙端隊(duì)列是指允許兩端都可以進(jìn)行入隊(duì)和出隊(duì)操作的隊(duì)列,
輸出受限的雙端隊(duì)列∶允許在一端進(jìn)行插入和刪除,但在另一端只允許插入的雙端隊(duì)列稱為輸出受限的雙端隊(duì)列,如下圖
輸入受限的雙端隊(duì)列∶允許在一端進(jìn)行插入和刪除,但在另一端只允許刪除的雙端隊(duì)列稱為輸入受限的雙端隊(duì)列,如下圖
三、STL容器中的queue和priority queue的實(shí)現(xiàn)方式
priority_queue<int> big_heap;//默認(rèn)構(gòu)造是最大堆 priority_queue<int, vector<int>, greate<int> > small_heap; //最小堆構(gòu)造方法 priority_queue<int, vector<int>, less<int> > big_heap2;//最大堆構(gòu)造方法big_heap.empty() // 判斷堆是否為空 big_heap.pop() // 彈出堆頂元素(最大值) big_heap.push(x) // 將元素x添加至二叉堆 big_heap.top() // 返回堆頂元素(最大值) big_heap.size() // 返回堆中元素個(gè)數(shù)總結(jié)
以上是生活随笔為你收集整理的【数据结构-栈和队列】详解栈和队列(代码+STL+原理)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【数据结构-树】4.图解平衡二叉树和哈夫
- 下一篇: 【数据结构-线性表】顺序表和链表(几种链