双栈(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;                    //设置n=2个栈共有一个栈空间

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 优点
两栈的大小不是固定不变的,在实际运算过程中,一个栈有可能进栈元素多而体积大些,另一个则可能小些。
两个栈共用一个栈空间,相互调剂,灵活性强。
3.2 缺点
运算较为复杂。
长度为定值,中途不易扩充。
注:n(n>2)个栈的情况更有所不同,采用多个栈共享栈空间的顺序存储表示方式,处理十分复杂,在插入时元素的移动量很大,因而时间代价较高。特别是当整个存储空间即将充满时,这个问题更加严重。
解决上述问题的办法就是采用链接方式作为栈的存储表示方式。
3.3 双栈的适用情况
当栈满时要发生溢出,为了避免这种情况,需要为栈设立一个足够大的空间。但如果空间设置得过大,而栈中实际只有几个元素,也是一种空间浪费。此外,程序中往往同时存在几个栈,因为各个栈所需的空间在运行中是动态变化着的。如果给几个栈分配同样大小的空间,可能实际运行时,有的栈膨胀得快,很快就产生了溢出,而其他的栈可能此时还有许多空闲空间。这时就可以利用双栈,两个栈共用一个栈空间,相互调剂,灵活性强。
参考文献: 
[1]《数据结构(用面向对象方法与C++语言描述)(第2版)》殷人昆——第三章 
[2]《C/C++常用算法手册》秦姣华、向旭宇——第二章 
[3] 百度搜索关键字:双栈
————————————————
版权声明:本文为CSDN博主「Cainv89」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cainv89/article/details/51398148

双栈(Dual Stack)相关推荐

  1. SAP PI - 单栈与双栈

    在PI初次发布的时候,不是所有的组件都是在同一个平台上构建的.集成引擎和业务处理引擎由ABAP构建,然而适配器引擎.集成构建器.SL.CM和Mapping Runtime由Java构建.因此PI需要J ...

  2. P1155 双栈排序(二分图染色)

    P1155 双栈排序(二分图染色) 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一 ...

  3. Leetcode224 基本加减计算器-双栈和状态转换

    题目 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 . 示例 1: 输入: "1 + 1&quo ...

  4. NOIP2008 双栈排序

    https://www.luogu.org/problem/show?pid=1155 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输 ...

  5. 单调队列 Monotonic Queue / 单调栈 Monotonic Stack

    2018-11-16 22:45:48 一.单调队列 Monotone Queue 239. Sliding Window Maximum 问题描述: 问题求解: 本题是一个经典的可以使用双端队列或者 ...

  6. 【每日一题】8月7日题目精讲—双栈排序

    来源:牛客网 文章目录 题目描述 题意: 题解: 代码: 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言262144K 64bit IO Format: %l ...

  7. [剑指offer][JAVA]面试题第[30]题[包含min函数的栈][双栈辅助栈][单栈]

    [问题描述][中等] 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min.push 及 pop 的时间复杂度都是 O(1).示例:MinStack min ...

  8. LeetCode 716. 最大栈(双栈 / list+map)

    文章目录 1. 题目 2. 解题 2.1 双栈解法 2.2 list+map 1. 题目 设计一个最大栈,支持 push.pop.top.peekMax 和 popMax 操作. push(x) -- ...

  9. LeetCode 1472. 设计浏览器历史记录(双栈)

    1. 题目 你有一个只支持单个标签页的 浏览器 ,最开始你浏览的网页是 homepage ,你可以访问其他的网站 url ,也可以在浏览历史中后退 steps 步或前进 steps 步. 请你实现 B ...

最新文章

  1. no python application found_用Nginx部署Django服务no python application found
  2. Apache+Openssl
  3. Python之禅 by Tim Peters
  4. 剑指Offer - 面试题12. 矩阵中的路径(DFS回溯)
  5. 嵌入式操作系统内核原理和开发(事件)
  6. Team Foundation Server
  7. 斐讯k2 怎么开虚拟服务器,求助各位大神,K2P怎么开启SSH
  8. BeanAir无线传感器方案
  9. 区块链开发用什么语言好?
  10. 一个amp;quot;现象级amp;quot;大数据公司的蜕变
  11. 电脑桌面运维工程师考证
  12. linux下proc文件夹详解
  13. 都是古人抓紧时间发奋苦读的典范
  14. 姐姐半夜不睡觉,既然偷偷在被窝里偷看HTML基础⭐
  15. imvu为什么显示无法连接服务器,IMVU服务器错误怎么办 服务器无法连接解决办法...
  16. 【软考中级】多媒体应用设计师复习笔记第十章
  17. Flask04_模板语法
  18. 网页版在线聊天java Socket实现
  19. 企微管家营销红包:给客户发红包,给客户群发红包均支持
  20. 一篇文章让你瞬间知道Mybatis框架是如何使用的

热门文章

  1. Python定义常量,设置config.py文件
  2. xss labs 挑战之旅
  3. Reasoning with Sarcasm by Reading In-between
  4. HTTP协议演进与各版本特性
  5. HI3520DV200+GV7601采集1080P视频
  6. Sun公司JES服务器软件已支持更多操作系统
  7. 【计算机图形学基础】学习笔记 02 图形系统
  8. python :SyntaxError: Non-ASCII character '\xe5' in file 错误
  9. SQL查询语句逻辑执行顺序
  10. c# datatable数据合并方法