栈的定义
这里有个思想,函数执行得怎么样了用返回值表示,真正要返回的东西放在参数列表里(用传入引用的方式实现返回)
栈的实现
Tool.h
#pragma once
enum Error_Type
{
Success,Overflow, Underflow
};
enum Ret_Type
{
Str,Num,End
};
Stack.h
#pragma once
#include"iostream"
#include"tool.h"//存的是Error_Type
using namespace std;
/*
enum Error_Type
{
Success, Overflow, Underflow
};
*/
template <class T1>
class Stack
{public:
virtual bool isempty() = 0 ;//是否为空
virtual Error_Type pop(T1& ret)=0;//出栈
virtual Error_Type push(const T1 &input) = 0;//入栈
virtual Error_Type get_Top(T1& ret) = 0;//获取栈顶元素
};
数组实现
Stack_arr.h
#pragma once
#include "Stack.h"
template<class T1>
class Stack_arr :
public Stack<T1>//存的东西
{
public:
int get_Count()const;//获取栈中元素个数
Stack_arr();//构造函数
bool isfull()const;//栈是否已满
T1 data_arr[28]{0};//存数据的数组
bool isempty() ;
Error_Type pop(T1& ret) ;
Error_Type push(const T1& input) ;
Error_Type get_Top(T1& ret) ;
private:
int count;
int top;
};
template<class T1>
bool
Stack_arr<T1>::isempty()
{
if (count == 0)return 1;//空的返回1
else return 0;//非空返回0
}
template<class T1>
int
Stack_arr<T1>::get_Count()const//获取栈中数据个数
{
return count;
}
template<class T1>
Stack_arr<T1>::Stack_arr()
{
count = 0;
top = 0;
}
template<class T1>
bool
Stack_arr<T1>::isfull()const
{
if (count == 28)return 1;//满了返回1
else return 0;
}
template<class T1>
Error_Type
Stack_arr<T1>::pop(T1& ret)
{
if (count == 0)//栈为空则打印信息,返回下溢错误类型
{
cout << "栈已空无法出栈" << endl;
return Underflow;
}
else//非空则计数,栈顶调整,并输出被pop的东西,返回Success
{
count--;
top--;
ret = data_arr[top];
return Success;
}
}
template<class T1>
Error_Type
Stack_arr<T1>::push(const T1& input)
{
if (count == 28)//满了就打印信息返回上溢错误
{
cout << "栈已满无法入栈" << endl;
return Overflow;
}
else//没满就计数增加,top后移,返回成功
{
count++;
data_arr[top] = input;
top++;
return Success;
}
}
template<class T1>
Error_Type
Stack_arr<T1>::get_Top(T1& ret)
{
if (count == 0)
{
cout << "栈为空!" << endl;
return Underflow;
}
else
{
ret = data_arr[top - 1];
return Success;
}
}
链实现
Stack_node.h
#pragma once
#include "Stack.h"
template<class T1>
class Stack_node :
public Stack<T1>//存的东西
{
public:
Stack_node();
class Node
{
public:
T1 data;
Node* next;
};
Node* top;
bool isempty() ;
Error_Type pop(T1& ret) ;
Error_Type push(const T1& input) ;
Error_Type get_Top(T1& ret) ;
private:
int count;
};
template<class T1>
bool
Stack_node<T1>::isempty()//栈是否为空
{
if (top == NULL)return 1;
else return 0;
}
template<class T1>
Stack_node<T1>::Stack_node()//初始化
{
count = 0;
top = NULL;
}
template<class T1>
Error_Type
Stack_node<T1>::get_Top(T1& ret)//取栈顶元素
{
if (count == 0)
{
cout << "栈是空的!" << endl;
return Underflow;
}
else
{
ret = top->data;
return Success;
}
}
template<class T1>
Error_Type
Stack_node<T1>::push(const T1& input)//入栈
{
auto node = new Node;
node->data = input;
node->next = top;
top = node;
count++;
return Success;
}
template<class T1>
Error_Type
Stack_node<T1>::pop(T1& ret)//出栈
{
if (count == 0)
{
cout << "栈已空!" << endl;
return Underflow;
}
else
{
ret = top->data;
auto top_tem = top;
top = top->next;
delete top_tem;
count--;
return Success;
}
}
栈的应用
计算器(顺便完成括号配对)
理论:
代码:
Calc.h
#pragma once
#include"Stack_node.h"
#include<String>
class Calc
{
public:
bool execute();//执行函数
Ret_Type get_Str_Num(char &str, double &num);//逐个提取数字和字符
bool doCalc(double& ret);//计算
bool doCheckParentheses();//检查括号配对
string input;//存输入的算式
double doEachTypeCalc(char sign, double num1, double num2);//进行数字的加减乘除运算
int n = 0;
};
bool
Calc::execute()//执行函数
{
double ret;
cout<<"请输入算式,注意括号要配对"<<endl;
cin >> input;
//检查括号
a: if (doCheckParentheses())
{
//运算
doCalc(ret);
cout << "结果是" << ret <<endl;
return 1;
}
else
{
cout<<"请重新输入"<<endl;
cin >> input;
goto a;
}
}
Ret_Type
Calc::get_Str_Num(char& str, double& num)
{
double ret_num = 0;
if ('0' <= input[n] && input[n] <= '9')//对数字进行处理
{
while ('0' <= input[n] && input[n] <= '9')
{
ret_num = ret_num * 10 + input[n] - '0';
n++;
}
num = ret_num;
return Num;
}
else if (input[n] != '\0')//对符号进行处理
{
ret_num = 0;
n++;
str = input[n-1];
return Str;
}
else//结束
return End;
}
bool
Calc::doCheckParentheses()
{
Stack_node<char> stack;
int n = 0;
char tmp;
while (input[n]!='\0')
{
if (input[n] == '(')stack.push(input[n]);//遇到(入栈
else if (input[n] == ')')//遇到)先判断栈是否为空再出栈
{
if (stack.isempty())
return 0;
else
{
stack.pop(tmp);
}
}
n++;
}
//cout<<"能出来吗?"<<endl;
if (!stack.isempty())return 0;//有没配对左括号,返回false
else return 1;
}
double
Calc::doEachTypeCalc(char sign, double num1, double num2)
{
switch (sign)
{case'+':
return num1 + num2;
case'-':
return num1 - num2;
case'*':
return num1 * num2;
case'/':
return num1 / num2;
}
}
bool
Calc::doCalc(double& ret)
{
double num,test;//接收读取到的数字,找bug
char str;//接收读取到的符号
char str_tmp;//存从栈中取出的符号
double num_calc1,num_calc2;//用于存计算的两个数字
Stack_node<char> stack_char;//字符栈
Stack_node<double> stack_num;//数字栈
Ret_Type rettype;
while ( (rettype=get_Str_Num(str, num))!=End)
{
if (rettype == Str)//读取到字符
{
if (stack_char.isempty())stack_char.push(str);//若符号栈为空直接入栈
else
{
switch (str)
{
case '+':case'-'://加减法
if (stack_char.get_Top(str_tmp) == Success)//读取栈顶符号
{
if (str_tmp != '(')//不是括号就把它进行运算,再放入新进的符号
{
//计算后把结果入栈
stack_num.pop(num_calc2);
stack_num.pop(num_calc1);
stack_num.push(doEachTypeCalc(str_tmp, num_calc1, num_calc2));
//stack_num.get_Top(test);
//cout<<test<<endl;
stack_char.pop(str_tmp);//算完后出栈,这里str_tmp无意义
stack_char.push(str);
}
else//是括号就入栈
stack_char.push(str);
}
break;
case '/':
case '*':
if (stack_char.get_Top(str_tmp) == Success)//读取栈顶符号
{
if (str_tmp != '('&& str_tmp != '+'&& str_tmp != '-')//不是括号就把它进行运算,再放入新进的符号
{
//计算后把结果入栈
stack_num.pop(num_calc2);
stack_num.pop(num_calc1);
stack_num.push(doEachTypeCalc(str_tmp, num_calc1, num_calc2));
//stack_num.get_Top(test);
//cout << test << endl;
stack_char.pop(str_tmp);//算完后出栈,这里str_tmp无意义
stack_char.push(str);
}
else//是括号,加减号就入栈
stack_char.push(str);
}
break;
case '(':
stack_char.push('(');
break;
case')':
while (stack_char.get_Top(str_tmp)==Success&&str_tmp != '(')//符号栈一直出栈,直到遇到(为止
{
stack_num.pop(num_calc2);
stack_num.pop(num_calc1);
stack_num.push(doEachTypeCalc(str_tmp, num_calc1, num_calc2));
stack_char.pop(str_tmp);
}
stack_char.pop(str_tmp);//(出栈
break;
}
}
}
else if (rettype == Num)//读取到数字
{
stack_num.push(num);//直接入栈
}
else//结束后返回true
{
return 1;
}
}
while (!stack_char.isempty())
{
stack_char.get_Top(str_tmp);
stack_num.pop(num_calc2);
stack_num.pop(num_calc1);
stack_num.push(doEachTypeCalc(str_tmp, num_calc1, num_calc2));
//stack_num.get_Top(test);
//cout << test << endl;
stack_char.pop(str_tmp);//算完后出栈,这里str_tmp无意义
}
stack_num.get_Top(ret);
return 1;
火车调度问题(合法序列检查)
练习
上面的策略一有误,“比他们都小“改为比max后面的数都小
代码
就展示CheckLegalSequence.h和源.cpp,其他上次展示过了
CheckLegalSequence.h
#pragma once
#include"Stack_node.h"
#include<String>
class CheckLegalSequence
{
public:
bool execute();
bool checkIntegrity();//数据完整性检查
bool strategy_Normal();//常规方式检查
bool stratepy_Stack();//用栈检查
private:
string input;//输入的序列
};
bool CheckLegalSequence::execute()
{
cout<<"请输入序列,由大于0的整数组成的个位数"<<endl;
cin >> input;
//cout << input.length();
if (!checkIntegrity())
{
cout<<"不是合法序列,有数字缺失或重复"<<endl;
return 0;
}
else
{
if (!stratepy_Stack())
{
cout << "不是合法序列(用stack查出)" << endl;
}
if (!strategy_Normal())
{
cout << "不是合法序列(用其他方法查出)" << endl;
return 0;
}
}
cout<<"是合法序列"<<endl;
return 1;
}
bool CheckLegalSequence::checkIntegrity()
{
int n = 0,length=0;
for (n = 0; n < input.length(); n++)
{
if (input[n] - '0' > length)length = input[n] - '0';
}
if (length != input.length())return 0;
int* check = new int[length]{0};
for (n = 0; n < input.length(); n++)
{
check[input[n]-'1'] = 1;
}
for (n = 0; n < input.length(); n++)
{
if (check[n] == 0)return 0;
}
return 1;
}
bool CheckLegalSequence::strategy_Normal()
{
int min = 0, max = 0, n;
for (n = 1; n < input.length(); n++)
{
if (input[min] > input[n])min = n;
else if (input[max] < input[n])
{
min=n;
max = n;
}
else
{
return 0;
}
}
return 1;
}
bool CheckLegalSequence::stratepy_Stack()
{
Stack_node<int> stack;
int n = 0,inttmp,n_input=0;
for (n = 0; n < input.length(); n++)
{
if (input[n_input]-'0' != n + 1)//不相等就入栈
{
stack.push(n + 1);
}
else
{
n_input++;//相等就去看下一个,然后把栈里的能出的出掉
while (!stack.isempty()&&stack.get_Top(inttmp)==Success&& inttmp == input[n_input] - '0')
{
n_input++;
stack.pop(inttmp);
}
}
}
if (!stack.isempty())return 0;
return 1;
}
源.cpp
#include"CheckLegalSequence.h"
int main()
{
CheckLegalSequence().execute();
return 0;
}
代替递归(后面递归会介绍,这里简单提一下)
1. 用栈代替递归来完成快速排序
代码:
#include<iostream>
using namespace std;
struct shuju
{
int a;
int b;
};
template<class T>
class stack
{
public:
stack() {};
stack(T b) :shu(b) {}
T shu;
stack* next = NULL;
T pop();
void push(T b);
T top();
bool isempty();
void bianli();
};
template<class T>
stack<T>* ptop = NULL;
template<class T>
T stack<T>::pop()
{
T b;
stack* gj1 = ptop<T>;
b = ptop<T>->shu;
ptop<T> = ptop<T>->next;
delete gj1;
return b;
}
template<class T>
void stack<T>::push(T b)
{
stack* gj1 = new stack(b);
gj1->next = ptop<T>;
ptop<T> = gj1;
}
template<class T>
T stack<T>::top()
{
return ptop->shu;
}
template<class T>
bool stack<T>::isempty()
{
if (ptop<T> == NULL)
return 0;
else return 1;
}
template<class T>
void stack<T>::bianli()
{
stack* gj1 = ptop;
while (gj1 != NULL)
{
cout << gj1->shu << " ";
gj1 = gj1->next;
}
cout << endl;
}
int sort(int* a, int b, int c);
int main()
{
int a[128] = { 0 }, i = 0, n = 0, l = 0, g = 0, m = 0, first, end;
stack<shuju> li;
cout << "请输入需要排序的数据" << endl;
while (cin >> a[i]) { i++; n++; }
g = n - 1;
l = 0;
shuju t, gj1;
t.a = l;
t.b = g;
li.push(t);
while (li.isempty())
{
gj1 = li.pop();
first = gj1.a;
end = gj1.b;
m = sort(a, first, end);
sort(a, first, end);
if (first - m > 1)
{
gj1.b = m - 1;
li.push(gj1);
}
if (end - m > 1)
{
gj1.a = m + 1;
li.push(gj1);
}
}
for (i = 0; i < n; i++)
{
cout << a[i] << " ";
}
return 0;
}
int sort(int* a, int b, int c)
{
int p = a[b];
while (c > b)
{
while (a[c] > p)
{
c--;
}
a[b] = a[c];
while (a[b] < p)
{
b++;
}
a[c] = a[b];
}
a[c] = p;
return c;
}