在學完鏈表後,接下來我們就開始學習棧和隊列了,因爲棧與隊列的實現是基於鏈表的(也可以是數組),所以要先學鏈表,然後緊接着學棧與隊列。
一. 棧(鏈表實現)
1. 棧的簡介
- 在生活中,我們會碰到這樣一種情況,在往球桶裏面放球的時候,最先放進去的球,只能在最後取出。
- 爲了模擬上述的情況,於是就出現了棧這種數據結構。
- 一般棧可以就行如下操作
- 入棧push,往棧裏面存放元素。
- 出棧pop,取出棧的頂部元素。
- 清空棧pop_all,將棧裏面的全部元素都出棧。
- 判斷棧是否爲空。
- 返回棧的頂部元素,但不出棧。
2. 棧的實現
- 入棧
void push(int i)
{
Node* q = new Node;
q->data = i;
if (tail != NULL)
{
q->next = tail;
tail = q;
}
else
{
tail = q;
q->next = NULL;
}
}
- 出棧
bool pop()
{
if (tail != NULL)
{
Node*q = tail;
tail = tail->next;
delete q;
return true;
}
else
return false;
}
- 判斷棧是否爲空
bool empty()
{
if (tail != NULL)
return false;
else
return true;
}
- 返回頂部元素
int top()
{
if (tail != NULL)
return tail->data;
else
return 0;
}
- 清空棧
void pop_all()
{
Node * p = tail, *q;
while (p->next)
{
q = p->next;
delete p;
p = q;
}
delete p;
tail = NULL;
}
- 完整實現
#include<iostream>
using namespace std;
class Node
{
public:
int data;
Node *next;
};
class Stack {
private:
Node *tail;
public:
Stack()
{
tail = NULL;
}
Stack(int i)
{
Node *q = new Node;
q->data = i;
tail = q;
q->next = NULL;
}
~Stack()
{
Node * p = tail, *q;
while (p)
{
q = p->next;
delete p;
p = q;
}
delete p;
}
//入棧
void push(int i)
{
Node* q = new Node;
q->data = i;
if (tail != NULL)
{
q->next = tail;
tail = q;
}
else
{
tail = q;
q->next = NULL;
}
}
//出棧
bool pop()
{
if (tail != NULL)
{
Node*q = tail;
tail = tail->next;
delete q;
return true;
}
else
return false;
}
//返回頂部元素
int top()
{
if (tail != NULL)
return tail->data;
else
return 0;
}
//判斷棧是否爲空
bool empty()
{
if (tail != NULL)
return false;
else
return true;
}
//清空棧
void pop_all()
{
Node * p = tail, *q;
while (p->next)
{
q = p->next;
delete p;
p = q;
}
delete p;
tail = NULL;
}
};
二. 隊列
1. 隊列簡介
- 在日常中,我們又會遇到另外一種非常常見的情況,那就是排隊。在排隊的時候,最先來的,業務就可以就先處理完。
- 在這種情況下,我們就使用隊列這種數據結構來模擬這種情況。
- 隊列一般可以進行的操作。
clear清空隊列
isEmpty判斷隊列是否爲空
enqueue在隊列尾部加入元素
dequeue取出隊列的第一個元素
firstE返回隊列的第一個元素,但不刪除
2. 隊列的實現
- 完整代碼,基於庫中的列表
#include<list>
template<class T>
class Queue {
private:
list<T> lst;
public:
Queue()
{
}
void clear()
{
lst.clear();
}
bool isEmpty() const {
return lst.empty();
}
T& front()
{
return lst.front();
}
T dequeue()
{
T e1 = lst.front();
lst.pop_front();
return e1;
}
void enqueue(const T& e1)
{
lst.push_back(e1);
}
};
三. 課後習題
- 將棧S中的元素的順序倒過來
1-a 使用兩個額外的棧
int main()
{
stack<int > q1;
stack<int > q2;
stack<int > q3;
q1.push(1);
q1.push(2);
q1.push(3);
q2.push(q1.top());
q1.pop();
q2.push(q1.top());
q1.pop();
q2.push(q1.top());
q1.pop();
q3.push(q2.top());
q2.pop();
q3.push(q2.top());
q2.pop();
q3.push(q2.top());
q2.pop();
q1.push(q3.top());
q3.pop();
q1.push(q3.top());
q3.pop();
q1.push(q3.top());
q3.pop();
while (!q1.empty())
{
cout << q1.top();
q1.pop();
}
return 0;
}
1-b 使用額外的一個隊列
int main()
{
stack<int> q;
list<int> m;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty())
{
m.push_back(q.top());
q.pop();
}
while (!m.empty())
{
q.push(m.front());
m.pop_front();
}
while (!q.empty())
{
cout << q.top();
q.pop();
}
return 0;
}
1-c 使用額外的一個棧和幾個額外的非數組變量
int main()
{
stack<int> q;
stack<int> q2;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty())
{
q2.push(q.top());
q.pop();
}
q.swap(q2);
while (!q.empty())
{
cout << q.top();
q.pop();
}
}
- 使用一個額外的棧和幾個額外的非數組變量,將棧S中的元素按升序排列
int main()
{
stack<int> q;
stack<int> q2;
int a=0, b=0,c = -10, min = 9999;
q.push(2), q.push(5), q.push(1),q.push(4),q.push(7),q.push(10),q.push(8),q.push(3);
for (int i = 0; i < 7; i++)
{
min = 999;
while (!q.empty())
{
if (q.top() == c)
break;
if (q.top() < min)
min = q.top();
q2.push(q.top());
q.pop();
}
c =min;
q.push(min);
while (!q2.empty())
{
if (q2.top() == min)
{
q2.pop();
continue;
}
q.push(q2.top());
q2.pop();
}
b = 0;
}
while (!q.empty())
{
cout << q.top()<<" ";
q.pop();
}
return 0;
}
- 將棧S1中的元素轉換到棧S2中,使S2中元素的順序與S1中元素的順序相同
3-a 使用一個額外的棧
int main()
{
stack<int> S1;
stack<int> S2;
stack<int> q;
S1.push(2), S1.push(3), S1.push(4), S1.push(5);
while (!S1.empty())
{
q.push(S1.top());
S1.pop();
}
while (!q.empty())
{
S2.push(q.top());
q.pop();
}
while (!S2.empty())
{
cout << S2.top() << " ";
S2.pop();
}
return 0;
}
3-b 不使用額外的棧,只使用幾個額外的非數組變量
int main()
{
stack<int> S1, S2;
int a, b=0, c = 1, d;
S1.push(1);
S1.push(2);
S1.push(3);
S1.push(4);
a = S1.size();
while (a)
{
// 寫出 i<S1.size() - 1 會出現錯誤
for (int i = 0; i <a - c; i++)
{
S2.push(S1.top());
S1.pop();
}
d = S1.top();
S1.pop();
for (int i = 0; i < 3-b; i++)
{
S1.push(S2.top());
S2.pop();
}
S2.push(d);
b++;
a--;
}
while (!S2.empty())
{
cout << S2.top() << " ";
S2.pop();
}
return 0;
}
- 使用額外的非數組變量及下面的條件,將隊列中的所有元素排序
5-a 兩個額外的隊列
int main()
{
queue<int> q1 , q2, q3;
q1.push(4), q1.push(1), q1.push(7), q1.push(10), q1.push(2), q1.push(6), q1.push(8);
int min;
int a = q1.size();
for (int i = 0; i < a; i++)
{
min = 999;
while (!q1.empty())
{
if (q1.front() < min)
{
min = q1.front();
}
q2.push(q1.front());
q1.pop();
}
while (!q2.empty())
{
if (q2.front() == min)
{
q2.pop();
continue;
}
q1.push(q2.front());
q2.pop();
}
q3.push(min);
}
while (!q3.empty())
{
cout << q3.front()<<" " ;
q3.pop();
}
return 0;
}
以上就是棧和隊列的大部分內容。
ps:以上知識學習於《C++數據結構與算法》Adam Drozdek 著, 徐丹,吳偉敏 譯。
Thank for your reading !!!