关于栈的定义什么的不多赘述,直接上代码:
用链表实现动态栈
//栈
#include<iostream>
using namespace std;
//使用链表实现动态栈
struct Node {
int data;
Node* next;
};
struct Stack{
Node* top;
};
//初始化栈
void initStack(Stack& s) {
s.top = NULL;
}
//入栈
void pushStack(Stack& s, int data) {
Node* newnode=new Node;
newnode->data = data;
//就是链表的next指针的指向s.top,也就是原本的栈顶
newnode->next = s.top;
//更新栈顶
s.top = newnode;
}
//出栈
void popStack(Stack& s) {
if (s.top == NULL) {
cout << "栈为空" << endl;
return;
}
Node* temp=s.top;
int data=s.top->data;
//这里的s.top->next就是原本的栈顶的下一个元素
s.top=s.top->next;
delete temp;
cout << "出栈元素为:" << data << endl;
}
void readTop(Stack& s) {
if (s.top == NULL) {
cout << "栈为空" << endl;
}
cout << "栈顶元素为:" << s.top->data << endl;
}
int main(){
Stack s;
initStack(s);
pushStack(s, 1);
pushStack(s, 2);
pushStack(s, 3);
readTop(s);
//删
popStack(s);
readTop(s);
//删
popStack(s);
readTop(s);
return 0;
}
两栈实现共享空间
//两栈共享空间
#include <iostream>
#define MAXSIZE 10 //数组最大容量
using namespace std;
//就是用一个数组作为两个栈的共同储存空间
struct TwoStacks
{
int data[MAXSIZE]; //数组
int top1, top2; //栈顶指针
};
//初始化
//因为数组的第一个变量对应的位数为0,所以我们空栈取-1
void initStacks(TwoStacks& s) {
s.top1 = -1; //栈1的栈顶指针
s.top2 = MAXSIZE; //栈2的栈顶指针
}
//判断栈是否为空/满
int judgeStacks(TwoStacks& s){
if(s.top1==-1&&s.top2==MAXSIZE){
cout<<"两个栈都为空"<<endl;
return 1;
}
if(s.top1+1==s.top2){
cout<<"两个栈都满了"<<endl;
return 2;
}
if(s.top1==-1&&s.top2!=MAXSIZE){
cout<<"栈1为空"<<endl;
return 3;
}
if(s.top2==MAXSIZE&&s.top1!=-1){
cout<<"栈2为空"<<endl;
return 4;
}
else{
return 0;
}
}
//入栈(左侧)
void pushlift(TwoStacks& s,int data){
if(judgeStacks(s)==2)
{
cout<<"无法插入数据"<<endl;
}
else
{
s.data[++s.top1]=data;
}
}
//入栈(右侧)
void pushright(TwoStacks& s,int data){
if(judgeStacks(s)==2)
{
cout<<"无法插入数据"<<endl;
}
else{
s.data[--s.top2]=data;
}
}
//出栈(左侧)
void poplist(TwoStacks& s){
if(judgeStacks(s)==1||judgeStacks(s)==3)
{
cout<<"无法删除数据"<<endl;
}
else
{
cout<<"要删除的数据为"<<s.data[s.top1]<<endl;
s.data[s.top1]=0;//删除数据,置0
s.top1--;
}
}
//出栈(右侧)
void popright(TwoStacks& s){
if(judgeStacks(s)==1||judgeStacks(s)==4){
cout<<"无法删除数据"<<endl;
}
else{
cout<<"要删除的数据为"<<s.data[s.top2]<<endl;
s.data[s.top2]=0;
s.top2++;
}
}
void printTwoStacks(TwoStacks& s){
for(int i=0;i<=s.top1;i++){
cout<<"这是栈左侧的第"<<i+1<<"个数据"<<endl;
cout<<s.data[i]<<endl;
}
for(int i=MAXSIZE-1;i>=s.top2;i--){
cout<<"这是栈右侧的第"<<MAXSIZE-i<<"个数据"<<endl;
cout<<s.data[i]<<endl;
}
for(int i=0;i<MAXSIZE;i++){
cout<<"这是栈的第"<<i+1<<"个数据"<<endl;
cout<<s.data[i]<<endl;
}
}
int main(){
TwoStacks s;
initStacks(s);
pushlift(s,1);
pushlift(s,2);
pushlift(s,3);
pushright(s,4);
pushright(s,5);
pushright(s,6);
printTwoStacks(s);
cout<<"从左侧出栈"<<endl;
poplist(s);
cout<<"从右侧出栈"<<endl;
popright(s);
printTwoStacks(s);
return 0;
}
判断写的有点不成熟,但是基本的功能是有了,这里发现了一个很有思意的东西
我设定的数组max为10,但是我填充的时候只填充了4个值,那么我便利输出整个数组的时候,
中间没有赋值的会显示什么呢?
307696905、32759、59 等数据是未初始化的内存中的随机值,在 C/C++ 中访问未赋值的数组元素时会读取这些“垃圾值”
操作系统和编译器为了性能优化,不会每次分配局部变量时都清空内存
so,你访问到的是前一次程序运行后遗留的数据,每次运行程序时这些值可能不同,甚至在同一台机器上重启调试也可能变化
四则运算
这里是通过把中缀表达式转化为后缀表达式
//四则运算
#include<iostream>
#include<stack>
#include<string>
#include<sstream>
#include<cctype>
using namespace std;
//可以通过栈来实现,这里直接调用stack库
//举个例子:比如 1+(4-3)*5+6/2 我们称之为中缀表达式
//我们可以将其转化为后缀表达式:1 4 3 - 5 * + 6 2 / +
//首先来看看怎么转化吧:
//判断是否为数字
bool is_digit(char c) {
//indigit传入的不能是char,我们要先把他转化为unsigned char类型
return isdigit(static_cast<unsigned char>(c));
}
//判断运算符优先级
int judge_prior(char c){
if (c == '+' || c == '-')
return 1;
else if (c == '*' || c == '/')
return 2;
else
return 0;
}
//infix:中缀
//postfix:后缀
string infix_to_postfix(string infix) {
stack<char> s;
//记录输出
stringstream output;
for(int i = 0; i < int(infix.length()); i++){
char c = infix[i];
if(c==' ')
{
continue;
}
//如果是数字,直接输出
if(is_digit(c)){
output << c << " ";
}
//如果是左括号,直接入栈
if(c=='('){
s.push(c);
}
//如果是右括号,将栈中的元素弹出,直到遇到左括号
if(c==')'){
while(!s.empty()&&s.top()!='('){
output<<s.top()<<" ";
s.pop();
}
s.pop();//弹出左括号
}
//操作符处理
//如果栈顶元素大于当前的元素,则将栈中元素弹出,直到新的栈顶小于当前元素或为空,然后将当前元素入栈
if(c=='+'||c=='-'||c=='*'||c=='/'){
while(!s.empty()&&judge_prior(c)<=judge_prior(s.top())){
output<<s.top()<<" ";
s.pop();
}
s.push(c);//将操作符入栈
}
}
//最后将栈中的元素弹出
while(!s.empty()){
output<<s.top()<<" ";
s.pop();
}
return output.str();
}
/*通过后缀表达式来计算,原理就是每碰到一个数字就把数字入栈,每碰到一个操作符就从栈中弹出靠经栈顶的两个数字,进行运算,
然后再把结果入栈,以此类推,知道后缀表达式结束,最后栈中剩下的就是结果
*/
int calculate(string postfix){
stack<int> s;
for(int i=0;i<int(postfix.length());i++){
char c=postfix[i];
if(c==' '){
continue;
}
//如果是数字,直接入栈
if(is_digit(c)){
//把字符转化为数字,没有这一步存的是ascii码
s.push(c-'0');
}
if(c=='+'||c=='-'||c=='*'||c=='/'){
//外面
int num2=s.top();
s.pop();
//里面
int num1=s.top();
s.pop();
switch(c){
case '+':
s.push(num1+num2);
break;
case '-':
s.push(num1-num2);
break;
case '*':
s.push(num1*num2);
break;
case '/':
s.push(num1/num2);
break;
}
}
}
return s.top();
}
int main(){
string infix=" 1+(4-3)*5+6/2";
cout<<"原始表达式为:"<<infix<<"结果为:"<<"9"<<endl;
string postfix=infix_to_postfix(infix);
//1 4 3 - 5 * + 6 2 / +
cout<<"后缀表达式为:"<<postfix<<endl;
int result=calculate(postfix);
cout<<"结果为:"<<result<<endl;
return 0;
}
这里我截取程杰老师的《大话数据结构》书中的这部分讲解内容来方便理解: