先看一下C++基本栈类的使用;
#include "stdafx.h"
#include
#include
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
stack s;
s.push(0);
s.push(303);
s.push(909);
s.pop();
cout << s.top() << endl;
return 0;
}
然后看火车调度问题;
这题大概是ACM里的基础题;题目描述如下;
设有编号为1,2,3,4,5,6~~~n的n辆列车,顺序进入一个栈式结构的站台。列出这n辆车的所有可能出站的顺序。
Input:
输入列车辆数和编号
Output:
输入所有列车出站的序列用空格隔开车编号
Sample Input:
3
1 2 3
Sample OutPut:
1 2 3
1 3 2
2 3 1
2 1 3
3 2 1
栈和车是如下示意的;
可以全部开进栈,再往B端出;或先进去3个、2个、1个,再调度往B端出;
某些排列是不可能的;
编程实现起来用栈比较方便;
网上找到一个程序,它的样例输入输出如下;
Input
5 2
1 2 3 5 4
Output
push
pop
push
pop
push
pop
push
push
pop
pop
第一行输入2个整数:车数量,先进到栈里的车数量;
第二行输入一种排列;
如果排列可行,则输出操作序列,如果排列不可行,则输出no;
代码如下;
// hcddtest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int a[50], c[50];
bool operation[50];
int i = 0;
int t, t1, m, m1 = 0, n, i1 = 0;
cin >> t;
for (t1 = 0; t1 < t; t1++) {
cin >> n >> m;
for (i = 0; i < n; i++) {
cin >> a[i];
}
int step = 0, b = 1;
stacks;
s.push(0);
for (i = 0; i < n; i++) {
while (s.top() < a[i]) {
s.push(b++);
operation[step++] = true;
}
if (s.size()>m + 1) {
cout << "no\n";
i1 = 1;
break;
}
if (s.top() == a[i]) {
s.pop();
operation[step++] = false;
}
}
if (i1 != 1) {
if (s.size() == 1 && s.top() == 0)
for (i = 0; i < step; i++) {
if (operation[i] == true) cout << "push\n";
else cout << "pop\n";
}
else cout << "no\n";
}
}
return 0;
}
但是程序还有点小问题;目前没时间看;输出有些问题,
总之要理解题目、数据结构栈才能做;
然后看一下MFC里面,可能没有栈类;网上找到一个栈类;
#pragma once
#ifndef STACK_H_
#define STACK_H_
#include
//结点结构体,双向栈
template
struct StackNode
{
T _tData; //数据域
StackNode* _pNext; //指针域,指向下一结点
StackNode* _pLast; //指针域,指向上一结点(为了行编辑器函数的实现)
StackNode(StackNode* next = nullptr,
StackNode* last = nullptr) { //用指针构造函数
this->_pNext = nullptr;
this->_pLast = nullptr;
}
StackNode(T data, StackNode* next = nullptr,
StackNode* last = nullptr) { //用指针构造函数
this->_tData = data;
this->_pNext = next;
this->_pLast = last;
}
};
template
class Stack {
private:
StackNode* _pTop; //栈顶指针
StackNode* _pBottom; //栈底指针,为了方便行编辑器使用
int _iConuntOfElement; //结点数量
public:
Stack(); //构造函数
Stack(Stack& copy); //构造函数
~Stack(); //析构函数
bool IsEmpty(); //判断栈是否为空
void MakeEmpty(); //将栈中的元素全部删除
void Put(const T data); //顶端插入数据
int Size() { return _iConuntOfElement; } //返回栈中的结点数
void GetTop(T& data); //获取顶端结点
void Pop(T& data); //顶端弹出结点,并将元素传至参数中
void Traverse(); //逆序栈中的结点
void DisPlay(bool forward = true); //输出函数,默认正向输出
};
//构造函数,为栈顶和栈底分配内存
template
Stack::Stack() {
_pTop = _pBottom = nullptr;
this->_iConuntOfElement = 0;
}
//拷贝构造函数
//缺少此函数,在传参与析构的时候容易出问题
template
Stack::Stack(Stack& copy) {
StackNode* pCur = this->_pTop; //建立指针,用于遍历本对象中的结点
while (pCur) { //遍历本对象的结点
T data = pCur->_tData; //依此取出结点值
copy.Put(data); //插入到copy栈中
pCur = pCur->_pNext;
}
}
//析构函数
template
Stack::~Stack() {
MakeEmpty(); //释放结点内存
this->_pTop = this->_pBottom = nullptr; //将指针指向空,避免出现野指针
}
//判断栈是否为空
template
bool Stack::IsEmpty() {
if (!this->_pTop) //如果栈对象没有头节点,那么栈就为空
return true;
return false;
}
//将栈中的元素全部删除
template
void Stack::MakeEmpty(){
StackNode* pDel = nullptr; //建立临时结点指针,用于释放结点内存
while (_pTop) { //循环依此从顶端删除
pDel = this->_pTop;
this->_pTop = _pTop->_pNext;
delete pDel;
}
_iConuntOfElement = 0; //栈结点数量置零
}
//顶端插入数据
template
void Stack::Put(const T data) {
StackNode* newData = new StackNode(data); //为新结点分配内存,新结点的并确定结点指针指向
if (!newData) { //如果内存分配错误
std::cerr << "内存分配错误!" << std::endl;
exit(-1);
}
if (this->IsEmpty()) { //如果插入的是第一个结点
newData->_pLast = nullptr; //将这个结点的指向上一下一结点的指针都赋空值
newData->_pNext = nullptr;
this->_pTop = newData; //将栈顶和栈底指针都指向这个结点
this->_pBottom = newData;
++this->_iConuntOfElement; //节点数加1
return;
}
this->_pTop->_pLast = newData; //栈顶的上一结点指针指向新结点
newData->_pNext = this->_pTop; //将新结点的下一结点指针指向栈顶
this->_pTop = newData; //新结点作为栈顶
++this->_iConuntOfElement;
}
//获取顶端结点
template
void Stack::GetTop(T& data) {
if (this->IsEmpty()) //栈为空,直接返回
return;
data = this->_pTop->_tData; //获取栈顶元素,赋值给返回参数
return;
}
//顶端弹出元素,并将元素传至参数中
template
void Stack::Pop(T& data) {
if (this->IsEmpty()) //栈为空,直接返回
return;
data = this->_pTop->_tData; //先取出栈顶的值
StackNode* pDel = this->_pTop;
if (this->_pTop->_pNext) { //如果有后继结点,就将后继结点的上一个指针指向空
this->_pTop->_pNext->_pLast = nullptr;
this->_pTop = this->_pTop->_pNext;
delete pDel; //释放原栈顶内存
--this->_iConuntOfElement; //栈结点数量递减
return;
}
delete pDel; //如果就只有一个结点,直接释放原栈顶的空间
this->_pTop = this->_pBottom = nullptr; //没有后继结点,释放栈顶空间,将指针指向空,避免出现野指针
--this->_iConuntOfElement; //栈结点数量递减
return;
}
//逆序栈中的结点
template
void Stack::Traverse() {
StackNode* pCur = this->_pTop;
StackNode* pTmp = nullptr; //临时指针,循环要用
while (pCur) { //循环将栈中结点的前驱与后继指针对调
pTmp = pCur->_pLast;
pCur->_pLast = pCur->_pNext;
pCur->_pNext = pTmp;
pCur = pCur->_pLast; //这个是很值得细细品味的
}
//将栈顶与栈顶指针对调
pTmp = this->_pTop;
this->_pTop = this->_pBottom;
this->_pBottom = pTmp;
return;
}
//输出函数
template
void Stack::DisPlay(bool forward = true) {
StackNode* pCur;
if(forward == true)
pCur = this->_pTop;
else
pCur = this->_pBottom;
while (pCur) { //如果当前指针不为空,就一直循环遍历
std::cout << pCur->_tData; //为了照顾
//if (iCount % 10 == 0) //每隔十个换一行,以免输出的太长
// std::cout << std::endl;
if (forward == true)
pCur = pCur->_pNext;
else
pCur = pCur->_pLast;
}
std::cout << std::endl;
}
#endif // !STACK_H_
调用的代码如下;
void CssView::OnDraw(CDC* pDC)
{
CssDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
CString str1;
Stack mystack;
mystack.Put(_T("AAA"));
mystack.Put(_T("BBB"));
mystack.Put(_T("CCC"));
mystack.Put(_T("DDD"));
mystack.GetTop(str1);
pDC->TextOutW(50,50, str1);
str1.Format(_T("%d"), mystack.Size());
pDC->TextOutW(50,80, str1);
CString strTopOfInfix = _T("");
mystack.Pop(strTopOfInfix);
mystack.GetTop(str1);
pDC->TextOutW(50,110, str1);
}
输出如下;
看上去这个类可用;下回继续;