C++栈类、火车调度问题、MFC栈类

先看一下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;
}

 C++栈类、火车调度问题、MFC栈类_第1张图片

然后看火车调度问题;

这题大概是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

栈和车是如下示意的;

C++栈类、火车调度问题、MFC栈类_第2张图片

可以全部开进栈,再往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;
}

但是程序还有点小问题;目前没时间看;输出有些问题,

C++栈类、火车调度问题、MFC栈类_第3张图片

 C++栈类、火车调度问题、MFC栈类_第4张图片

 总之要理解题目、数据结构栈才能做;

然后看一下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);	
}

 输出如下;

C++栈类、火车调度问题、MFC栈类_第5张图片

看上去这个类可用;下回继续;

你可能感兴趣的:(VC++,算法,mfc,栈,火车调度)