双栈(Dual Stack)
来源:互联网 发布:中午跑步 知乎 编辑:程序博客网 时间:2024/06/06 08:53
双栈(Dual Stack)
1. 双栈的概念
1.1 双栈的定义
1.2 双栈中各元素的逻辑及存储关系
- 双栈共享一个地址连续的存储单元。即程序同时需要两个栈时,可以定义一个足够大的栈空间,该空间的两端分别设为两个栈的栈底,用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)栈空的条件: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; const int stackIncreament = 20; const int n = 2; template <class T>class DualStack{public: DualStack(int sz = defaultSize); ~DualStack(); public: bool Push(const T& x, int d) ; bool Pop(T& x, int d); bool getTop(T& x, int d) const; 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;} 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;}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;}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; for (int i = 0; i <= s.top[0]; i++) { os << "[" << i << "]" << " : " << s.Vector[i] << endl; } os << "top[1]=" << s.top[1] << endl; 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 #define POP 2 #define GETTOP 3 #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;}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;}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;}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;}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;}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;}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;}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: { push(dualStack); break; } case POP: { pop(dualStack); break; } case GETTOP: { 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 优点
- 两栈的大小不是固定不变的,在实际运算过程中,一个栈有可能进栈元素多而体积大些,另一个则可能小些。
- 两个栈共用一个栈空间,相互调剂,灵活性强。
3.2 缺点
- 运算较为复杂。
- 长度为定值,中途不易扩充。
- 注:n(n>2)个栈的情况更有所不同,采用多个栈共享栈空间的顺序存储表示方式,处理十分复杂,在插入时元素的移动量很大,因而时间代价较高。特别是当整个存储空间即将充满时,这个问题更加严重。
- 解决上述问题的办法就是采用链接方式作为栈的存储表示方式。
3.3 双栈的适用情况
- 当栈满时要发生溢出,为了避免这种情况,需要为栈设立一个足够大的空间。但如果空间设置得过大,而栈中实际只有几个元素,也是一种空间浪费。此外,程序中往往同时存在几个栈,因为各个栈所需的空间在运行中是动态变化着的。如果给几个栈分配同样大小的空间,可能实际运行时,有的栈膨胀得快,很快就产生了溢出,而其他的栈可能此时还有许多空闲空间。这时就可以利用双栈,两个栈共用一个栈空间,相互调剂,灵活性强。
参考文献:
[1]《数据结构(用面向对象方法与C++语言描述)(第2版)》殷人昆——第三章
[2]《C/C++常用算法手册》秦姣华、向旭宇——第二章
[3] 百度搜索关键字:双栈