双栈(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;                    //设置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;}//栈顶元素出栈,并将该元素的值保存至xtemplate <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;}//读取栈顶元素,并将该元素的值保存至xtemplate <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~9bool 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~9bool 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型转为模板类型Ttemplate <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;}//栈顶元素出栈,并将该元素的值保存至xtemplate <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;}//读取栈顶元素,并将该元素的值保存至xtemplate <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] 百度搜索关键字:双栈

原创粉丝点击