双栈(Dual Stack)
来源:互联网 发布:淘宝婚庆四件套 编辑:程序博客网 时间:2024/06/01 23:37
双栈(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_ */
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;}
3. 双栈的优缺点
3.1 优点
- 两栈的大小不是固定不变的,在实际运算过程中,一个栈有可能进栈元素多而体积大些,另一个则可能小些。
- 两个栈共用一个栈空间,相互调剂,灵活性强。
3.2 缺点
- 运算较为复杂。
- 长度为定值,中途不易扩充。
- 注:n(n>2)个栈的情况更有所不同,采用多个栈共享栈空间的顺序存储表示方式,处理十分复杂,在插入时元素的移动量很大,因而时间代价较高。特别是当整个存储空间即将充满时,这个问题更加严重。
- 解决上述问题的办法就是采用链接方式作为栈的存储表示方式。
3.3 双栈的适用情况
- 当栈满时要发生溢出,为了避免这种情况,需要为栈设立一个足够大的空间。但如果空间设置得过大,而栈中实际只有几个元素,也是一种空间浪费。此外,程序中往往同时存在几个栈,因为各个栈所需的空间在运行中是动态变化着的。如果给几个栈分配同样大小的空间,可能实际运行时,有的栈膨胀得快,很快就产生了溢出,而其他的栈可能此时还有许多空闲空间。这时就可以利用双栈,两个栈共用一个栈空间,相互调剂,灵活性强。
参考文献:
[1]《数据结构(用面向对象方法与C++语言描述)(第2版)》殷人昆——第三章
[2]《C/C++常用算法手册》秦姣华、向旭宇——第二章
[3] 百度搜索关键字:双栈
2 0
- 双栈(Dual Stack)
- 双栈(Dual Stack)
- dual
- dual
- dual
- stack
- stack
- stack
- stack
- Stack
- Stack
- Stack
- Stack
- stack
- Stack
- stack
- stack
- Stack
- leetcode.207. Course Schedule
- 线程的3种创建方式
- 导航栏标题文字不居中
- 例4.10 POJ3525/LA3890离海最远的点 半平面交 + 二分法 + double小数点后有效位数处理方式/printf与g++、c++的问题
- 计算机图形学(二)输出图元_10_多边形填充区_4_多边形表
- 双栈(Dual Stack)
- JAVA第三方库
- Android 学习笔记之七 Application类
- Java线程池核心类ThreadPoolExecutor
- Android内核开发:系统启动速度优化
- qt中的TabWidget应用程序框架
- 长连接的几种实现方式
- 探索推荐引擎内部的秘密,第 3 部分: 深入推荐引擎相关算法 - 聚类
- json解析