双栈(Dual Stack)
雙棧(Dual Stack)
1. 雙棧的概念
1.1 雙棧的定義
雙棧是指兩個順序棧,是一種特殊的順序棧。
1.2 雙棧中各元素的邏輯及存儲關系
雙棧共享一個地址連續的存儲單元。即程序同時需要兩個棧時,可以定義一個足夠大的??臻g,該空間的兩端分別設為兩個棧的棧底,用bottom[0]=-1和bottom[1]=maxSize指示。
壓入數據時,讓兩個棧的棧頂top[0]和top[1]都向中間伸展,如果指示棧頂的指針top[0]+1等于另一個棧頂的指針top[1]時兩棧已滿。
每次進棧時top[0]加1或top[1]減1,而退棧時top[0]減1或top[1]加1。
如果top[0] == -1且top[1] == maxSize兩棧為空。
雙棧的模型:?
在雙棧的情形下:?
(1)棧的初始化語句:bottom[0]=top[0]=-1,bottom[1]=top[1]=maxSize。?
(2)棧滿的條件:top[0]+1 == top[1]。?
(3)??盏臈l件:bottom[0]==top[0]==-1且bottom[1]==top[1]==maxSize。
2. 雙棧的實現
2.1 雙棧的類定義及其操作的實現
文件:DualStack.h
#ifndef DUAL_STACK_H_
#define DUAL_STACK_H_
#include <iostream>
#include <string>
#include <strstream>
using namespace std;
const int defaultSize = 50; ? ? ? ? //默認??臻g大小
const int stackIncreament = 20; ? ? //棧溢出時擴展空間的增量
const int n = 2; ? ? ? ? ? ? ? ? ? ?//設置n=2個棧共有一個??臻g
template <class T>
class DualStack
{
public:
? ? DualStack(int sz = defaultSize); ? ? ? ?//構造函數
? ? ~DualStack(); ? ? ? ? ? ? ? ? ? ? ? ? ? //析構函數
public:
? ? bool Push(const T& x, int d) ; ? ? ?//新元素x進棧
? ? bool Pop(T& x, int d); ? ? ? ? ? ? ?//棧頂元素出棧,并將該元素的值保存至x
? ? bool getTop(T& x, int d) const; ? ? //讀取棧頂元素,并將該元素的值保存至x
? ? bool IsEmpty() const; ? ? ? ? ? ? ? //判斷棧是否為空
? ? bool IsFull() const; ? ? ? ? ? ? ? ?//判斷棧是否為滿
? ? int getSize() const; ? ? ? ? ? ? ? ?//計算棧中元素個數
? ? void MakeEmpty(); ? ? ? ? ? ? ? ? ? //清空棧的內容
? ? void overflowProcess(); ? ? ? ? ? ? //棧的溢出處理
public:
? ? template <class T>
? ? friend ostream& operator<<(ostream& os, const DualStack<T>& s); //輸出棧中元素的重載操作<<
private:
? ? T *Vector; ? ? ?//存放棧中元素的棧數組
? ? int top[n]; ? ? //棧頂指針
? ? int maxSize; ? ?//棧最大可容納元素個數
};
//構造函數
template <class T>
DualStack<T>::DualStack(int sz)
{
? ? cout << "$ 執行構造函數" << endl;
? ? if (sz >= 0)
? ? {
? ? ? ? maxSize = sz; ? ? ? ? ??
? ? ? ? top[0] = -1;
? ? ? ? top[1] = maxSize;
? ? ? ? Vector = new T[maxSize];
? ? }
} ? ? ? ? ? ? ? ? ? ? ??
//析構函數
template <class T>
DualStack<T>::~DualStack()
{
? ? cout << "$ 執行析構函數" << endl;
? ? delete[] Vector;
? ? Vector = NULL;
} ??
//新元素x進棧
template <class T>
bool DualStack<T>::Push(const T& x, int d)
{
? ? if (true == IsFull())
? ? {
? ? ? ? return false;
? ? }
? ? if (0 == d)
? ? {
? ? ? ? top[0]++;
? ? }
? ? else
? ? {
? ? ? ? top[1]--;
? ? }
? ? Vector[top[d]] = x;
? ? return true;
}
//棧頂元素出棧,并將該元素的值保存至x
template <class T>
bool DualStack<T>::Pop(T& x, int d)
{
? ? if (true == IsEmpty())
? ? {
? ? ? ? return false;
? ? }
? ? x = Vector[top[d]];
? ? if (0 == d)
? ? {
? ? ? ? top[0]--;
? ? }
? ? else
? ? {
? ? ? ? top[1]++;
? ? }
? ? return true;
}
//讀取棧頂元素,并將該元素的值保存至x
template <class T>
bool DualStack<T>::getTop(T& x, int d) const
{
? ? if (true == IsEmpty())
? ? {
? ? ? ? return false;
? ? }
? ? x = Vector[top[d]];
? ? return true;
}
//判斷棧是否為空
template <class T>
bool DualStack<T>::IsEmpty() const
{
? ? return ((-1 == top[0]) && (maxSize == top[1])) ? true : false;
}
//判斷棧是否為滿
template <class T>
bool DualStack<T>::IsFull() const
{
? ? return (top[0] + 1 == top[1]) ? true : false;
}
//計算棧中元素個數
template <class T>
int DualStack<T>::getSize() const
{
? ? return (top[0] + 1) + (maxSize - top[1]);
}
//清空棧的內容
template <class T>
void DualStack<T>::MakeEmpty()
{
? ? delete[] Vector;
? ? top[0] = -1;
? ? top[1] = maxSize;
? ? Vector = new T[maxSize];
}
//棧的溢出處理
template <class T>
void DualStack<T>::overflowProcess()
{
? ? int newSize = maxSize + stackIncreament;
? ? T *neweVector = new T[newSize];
? ? for (int i = 0; i <= top[0]; i++)
? ? {
? ? ? ? neweVector[i] = Vector[i];
? ? }
? ? for (int i = maxSize - 1; i >= top[1]; i--)
? ? {
? ? ? ? neweVector[i + stackIncreament] = Vector[i];
? ? }
? ? delete[] Vector;
? ? Vector = neweVector;
? ? maxSize = newSize;
? ? top[1] += stackIncreament;
}
//輸出棧中元素的重載操作<<
template <class T>
ostream& operator<<(ostream& os, const DualStack<T>& s)
{
? ? os << "top[0]=" << s.top[0] << endl; ? ?//輸出棧1頂位置
? ? for (int i = 0; i <= s.top[0]; i++)
? ? {
? ? ? ? os << "[" << i << "]" << " : " << s.Vector[i] << endl;
? ? }
? ? os << "top[1]=" << s.top[1] << endl; ? ?//輸出棧2頂位置
? ? for (int i = s.maxSize - 1; i >= s.top[1]; i--)
? ? {
? ? ? ? os << "[" << i << "]" << " : " << s.Vector[i] << endl;
? ? }
? ? return os;
}
#endif /* DUAL_STACK_H_ */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
2.2 主函數(main函數)的實現
文件:main.cpp
#include "DualStack.h"
#define EXIT 0 ? ? ? ? ? ? ?//退出
#define PUSH 1 ? ? ? ? ? ? ?//新元素x進棧
#define POP ?2 ? ? ? ? ? ? ?//棧頂元素出棧,并將該元素的值保存至x
#define GETTOP 3 ? ? ? ? ? ?//讀取棧頂元素,并將該元素的值保存至x
#define ISEMPTY ?4 ? ? ? ? ?//判斷棧是否為空
#define ISFULL 5 ? ? ? ? ? ?//判斷棧是否為滿
#define GETSIZE 6 ? ? ? ? ? //計算棧中元素個數
#define MAKEEMPTY 7 ? ? ? ? //清空棧的內容
#define OPERATOR_OSTREAM 8 ?//輸出棧中元素的重載操作<<
#define OVERFLOWPROCESS 9 ? //棧的溢出處理
void print_description()
{
? ? cout << "------------------------------>雙棧<------------------------------" << endl;
? ? cout << "功能選項說明:" << endl;
? ? cout << "#0: 退出" << endl;
? ? cout << "#1: 新元素x進棧" << endl;
? ? cout << "#2: 棧頂元素出棧,并將該元素的值保存至x" << endl;
? ? cout << "#3: 讀取棧頂元素,并將該元素的值保存至x" << endl;
? ? cout << "#4: 判斷棧是否為空" << endl;
? ? cout << "#5: 判斷棧是否為滿" << endl;
? ? cout << "#6: 計算棧中元素個數" << endl;
? ? cout << "#7: 清空棧的內容" << endl;
? ? cout << "#8: 輸出棧中元素的重載操作<<" << endl;
? ? cout << "#9: 棧的溢出處理" << endl;
? ? cout << "--------------------------------------------------------------------" << endl;
}
//判斷輸入的字符串每個字符是否都是數值0~9
bool IsStackNumber(const string& s_num)
{
? ? if (s_num.size() > 1)
? ? {
? ? ? ? return false;
? ? }
? ? if ((s_num[0] != '0') && (s_num[0] != '1'))
? ? {
? ? ? ? return false;
? ? }
? ? return true;
}
//判斷輸入的字符串每個字符是否都是數值0~9
bool IsNumber(const string& s_num)
{
? ? for (size_t i = 0; i < s_num.size(); i++)
? ? {
? ? ? ? if ((s_num[i] < '0') || (s_num[i] > '9'))
? ? ? ? {
? ? ? ? ? ? return false;
? ? ? ? }
? ? }
? ? return true;
}
//類型轉換——將string型轉為模板類型T
template <class T>
T StrToTtype(const string& s_num)
{
? ? T n_num;
? ? strstream ss_num;
? ? ss_num << s_num;
? ? ss_num >> n_num;
? ? return n_num;
}
//輸入棧編號
template <class T>
int get_item()
{
? ? cout << "> 請輸入棧編號,item = ";
? ? string s_item;
? ? cin >> s_item;
? ? while (false == IsStackNumber(s_item))
? ? {
? ? ? ? cout << "* 輸入有誤,請重新輸入:";
? ? ? ? cin >> s_item;
? ? }
? ? return atoi(s_item.c_str());
}
//輸入數據值
template <class T>
T get_data()
{
? ? cout << "> 請輸入數據值,data = ";
? ? string s_data;
? ? cin >> s_data;
? ? return StrToTtype<T>(s_data);
}
//輸入數組的最大長度
template <class T>
int get_maxsize()
{
? ? cout << "> 請輸入數組的最大長度,maxsize = ";
? ? string s_maxsize;
? ? cin >> s_maxsize;
? ? while (false == IsNumber(s_maxsize))
? ? {
? ? ? ? cout << "* 輸入有誤,請重新輸入:";
? ? ? ? cin >> s_maxsize;
? ? }
? ? return atoi(s_maxsize.c_str());
}
//構造雙棧
template <class T>
DualStack<T>* construct_dualstack()
{
? ? cout << "\n==> 創建雙棧" << endl;
? ? int n_maxsize = get_maxsize<T>();
? ? DualStack<T> *dualStack = new DualStack<T>(n_maxsize);
? ? return dualStack;
}
//析構雙棧
template <class T>
void destory_seqstack(DualStack<T>* dualStack)
{
? ? cout << "\n==> 釋放雙棧在堆中申請的空間,并將指向該空間的指針變量置為空" << endl;
? ? delete dualStack;
? ? dualStack = NULL;
}
//新元素x進棧
template <class T> ? ? ? ? ? ? ?
void push(DualStack<T>* dualStack)
{
? ? cout << "$ 執行新元素x進棧函數" << endl;
? ? T data = get_data<T>();
? ? int d = get_item<T>();
? ? if (false == dualStack->Push(data, d))
? ? {
? ? ? ? cout << "* 進棧失敗" << endl;
? ? ? ? return;
? ? }
? ? cout << "* 進棧成功,data = " << data << endl;
}
//棧頂元素出棧,并將該元素的值保存至x
template <class T> ?
void pop(DualStack<T>* dualStack)
{
? ? cout << "$ 執行棧頂元素出棧并將該元素的值保存至x函數" << endl;
? ? T data;
? ? int d = get_item<T>();
? ? if (false == dualStack->Pop(data, d))
? ? {
? ? ? ? cout << "* 出棧失敗" << endl;
? ? ? ? return;
? ? }
? ? cout << "* 出棧成功,data = " << data << endl;
}
//讀取棧頂元素,并將該元素的值保存至x
template <class T> ?
void gettop(DualStack<T>* dualStack)
{
? ? cout << "$ 執行讀取棧頂元素并將該元素的值保存至x函數" << endl;
? ? T data;
? ? int d = get_item<T>();
? ? if (false == dualStack->getTop(data, d))
? ? {
? ? ? ? cout << "* 讀取棧頂元素失敗" << endl;
? ? ? ? return;
? ? }
? ? cout << "* 讀取棧頂元素成功,data = " << data << endl;
}
//判斷棧是否為空
template <class T> ?
void isempty(DualStack<T>* dualStack)
{
? ? cout << "$ 執行判斷棧是否為空函數,IsEmpty = " << dualStack->IsEmpty() << endl;
}
//判斷棧是否為滿
template <class T> ?
void isfull(DualStack<T>* dualStack)
{
? ? cout << "$ 執行判斷棧是否為滿函數,IsFull = " << dualStack->IsFull() << endl;
}
//計算棧中元素個數
template <class T> ?
void getsize(DualStack<T>* dualStack)
{
? ? cout << "$ 執行計算棧中元素個數函數,Size = " << dualStack->getSize() << endl;
}
//清空棧的內容
template <class T> ?
void makeempty(DualStack<T>* dualStack)
{
? ? cout << "$ 執行清空棧的內容函數" << endl;
? ? dualStack->MakeEmpty();
}
//輸出棧中元素的重載操作<<
template <class T> ?
void operator_ostream(DualStack<T>* dualStack)
{
? ? cout << "$ 執行輸出棧中元素的重載操作<<函數" << endl;
? ? cout << *dualStack;//或operator<<(cout, *dualStack);
}
//棧的溢出處理
template <class T>
void overflowprocess(DualStack<T>* dualStack)
{
? ? cout << "$ 執行棧的溢出處理函數" << endl;
? ? dualStack->overflowProcess();
}
//雙棧操作選擇
template <class T>
void select_operation(DualStack<T>* dualStack)
{
? ? if (NULL == dualStack)
? ? {
? ? ? ? cout << "* 沒有構造雙棧,請先構造雙棧。" << endl;
? ? ? ? return;
? ? }
? ? string s_operation;
? ? while (s_operation != "0")
? ? {
? ? ? ? cout << "\n==> 請輸入功能選項編號(按\"0\"退出程序):";
? ? ? ? cin >> s_operation;
? ? ? ? while (false == IsNumber(s_operation))
? ? ? ? {
? ? ? ? ? ? cout << "* 輸入有誤,請重新輸入:";
? ? ? ? ? ? cin >> s_operation;
? ? ? ? }
? ? ? ? int n_operation = atoi(s_operation.c_str());
? ? ? ? switch (n_operation)
? ? ? ? {
? ? ? ? ? ? case EXIT://退出
? ? ? ? ? ? {
? ? ? ? ? ? ? ? cout << "$ 退出程序" << endl;
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? case PUSH://新元素x進棧
? ? ? ? ? ? {
? ? ? ? ? ? ? ? push(dualStack);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? case POP://棧頂元素出棧,并將該元素的值保存至x
? ? ? ? ? ? {
? ? ? ? ? ? ? ? pop(dualStack);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? case GETTOP://讀取棧頂元素,并將該元素的值保存至x
? ? ? ? ? ? {
? ? ? ? ? ? ? ? gettop(dualStack);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? case ISEMPTY://判斷棧是否為空
? ? ? ? ? ? {
? ? ? ? ? ? ? ? isempty(dualStack);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? case ISFULL://判斷棧是否為滿
? ? ? ? ? ? {
? ? ? ? ? ? ? ? isfull(dualStack);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? case GETSIZE://計算棧中元素個數
? ? ? ? ? ? {
? ? ? ? ? ? ? ? getsize(dualStack);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? case MAKEEMPTY://清空棧的內容
? ? ? ? ? ? {
? ? ? ? ? ? ? ? makeempty(dualStack);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? case OPERATOR_OSTREAM://輸出棧中元素的重載操作<<
? ? ? ? ? ? {
? ? ? ? ? ? ? ? operator_ostream(dualStack);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? case OVERFLOWPROCESS://棧的溢出處理
? ? ? ? ? ? {
? ? ? ? ? ? ? ? overflowprocess(dualStack);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? default:
? ? ? ? ? ? {
? ? ? ? ? ? ? ? cout << "* 請輸入正確的功能選項編號" << endl;
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
int main(int argc, char* argv[])
{
? ? print_description();
? ? DualStack<int> *dualStack = construct_dualstack<int>();
? ? select_operation(dualStack);
? ? destory_seqstack(dualStack);
? ? system("pause");
? ? return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
3. 雙棧的優缺點
3.1 優點
兩棧的大小不是固定不變的,在實際運算過程中,一個棧有可能進棧元素多而體積大些,另一個則可能小些。
兩個棧共用一個??臻g,相互調劑,靈活性強。
3.2 缺點
運算較為復雜。
長度為定值,中途不易擴充。
注:n(n>2)個棧的情況更有所不同,采用多個棧共享??臻g的順序存儲表示方式,處理十分復雜,在插入時元素的移動量很大,因而時間代價較高。特別是當整個存儲空間即將充滿時,這個問題更加嚴重。
解決上述問題的辦法就是采用鏈接方式作為棧的存儲表示方式。
3.3 雙棧的適用情況
當棧滿時要發生溢出,為了避免這種情況,需要為棧設立一個足夠大的空間。但如果空間設置得過大,而棧中實際只有幾個元素,也是一種空間浪費。此外,程序中往往同時存在幾個棧,因為各個棧所需的空間在運行中是動態變化著的。如果給幾個棧分配同樣大小的空間,可能實際運行時,有的棧膨脹得快,很快就產生了溢出,而其他的??赡艽藭r還有許多空閑空間。這時就可以利用雙棧,兩個棧共用一個棧空間,相互調劑,靈活性強。
參考文獻:?
[1]《數據結構(用面向對象方法與C++語言描述)(第2版)》殷人昆——第三章?
[2]《C/C++常用算法手冊》秦姣華、向旭宇——第二章?
[3]?百度搜索關鍵字:雙棧
————————————————
版權聲明:本文為CSDN博主「Cainv89」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/cainv89/article/details/51398148
總結
以上是生活随笔為你收集整理的双栈(Dual Stack)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 远程桌面.第三方
- 下一篇: 虚幻引擎外部模型及动画导入