双栈(Dual Stack)

双栈(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

发布了6 篇原创文章 · 获赞 189 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/newbie_xymt/article/details/103180326