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