算法(5)双链表+模拟栈+中缀表达式(表达式求值)+模拟队列

本文介绍了如何使用C++编程语言实现双链表数据结构,以及栈和队列的概念和数组模拟方法,包括插入、删除和查询操作,同时展示了表达式求值中栈的运用。
摘要由CSDN通过智能技术生成

双链表:

概念:

链表形式于单链表差不多,只是每个结点多了一个指向前一个元素的指针

图:

数组实现:

e数组为链表存值,0和1分别表示头和尾,所以数从下标2开始储存

l数组和r数组的下标于e数组下标一一对应,l数组存该节点左边结点的下标(地址),调用方法:e[ l [ i ] ];

同理,r数组的调用方法:e[ r [ i ] ]

idx:为指向标,表示e数组中已经储存了idx-1个数

#include<iostream>

using namespace std;

const int N = 100010;

int e[N], l[N], r[N], idx;//index file索引文件

//初始化
void init()
{
	//0表示最左端,左端点,1表示右端点
	r[0] = 1, l[1] = 0;
	idx = 2;//idx从2开始=>k要加1
}

//在下标是k的点的右边插入一个x;在左边插入时用add(l[k],x)
void add(int k, int x)
{
	e[idx] = x;
	r[idx] = r[k];
	l[idx] = k;//此时k=l[r[k]]
	l[r[k]] = idx;
	r[k] = idx;
	idx++;
}

//删除第k个点
void remove(int k)
{
	r[l[k]] = r[k];
	l[r[k]] = l[k];
}

int main()
{
	int m;
	cin >> m;

	init();//初始化

	while (m--)
	{
		string op;
		cin >> op;
		int k, x;
		if (op == "L")
		{
			cin >> x;
			add(0, x);
		}
		if (op == "R")
		{
			cin >> x;
			add(l[1], x);
		}
		if (op == "D")
		{
			cin >> k;
			remove(k + 1);
		}
		if (op == "IL")
		{
			cin >> k >> x;
			add(l[k + 1], x);
		}
		if (op == "IR")
		{
			cin >> k >> x;
			add(k + 1, x);
		}
	}
	for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << ' ';
	cout << endl;
	return 0;
}

栈:

概念:

栈是一个先进后出的空间 => 先插入的元素会后弹出来

图:

数组模拟栈:

st数组(stack:栈)表示栈,top指向最后存入数组的元素(栈顶)

#include<iostream>

using namespace std;

const int N = 100010;

int st[N];
int top = -1;


//向栈顶插入一个数X
void push(int x)
{
    st[++top] = x;
}
//栈顶弹出一个数
void pop()
{
    top--;
}
//查询是否为空
void empty()
{
    string x;
    x = top >= 0 ? "NO" : "YES";//空是,非空,否
    cout << x << endl;
}
//查询栈顶的元素
void query()
{
    cout << st[top] << endl;
}

int main()
{
    int m;
    cin >> m;
    while (m--)
    {
        string op;
        int x;
        cin >> op;
        if (op == "push")
        {
            cin >> x;
            push(x);
        }
        else if (op == "pop")
        {
            pop();
        }
        else if (op == "empty")
        {
            empty();
        }
        else if (op == "query")
        {
            query();
        }
    }
    return 0;
}

表达式求值(栈的运用): 

如果是跟在两个操作数之间,那么这个表达式就是中缀表达式

要求:输入表达式如:(1+2)*(2+3),求其值

方法:

  1. 设置两个栈,一个数字栈numStack,储存表达式中涉及到的数字,一个符号栈operatorStack(operator:运算符,操作员)储存表达式中涉及到的运算符

  2. 逐个分析表达式,直到全部的字符都已分析完

    1. 若当前字符为数字,则判断后续字符是否也为数字,若为数字则进行拼接,直到下一个为运算符为止,此时将拼接好的数字压入数字栈中。(如果已经是最后一个字符则直接压入栈中)

    2. 若当前字符为算数运算符

      1. 如果运算栈为空,则直接压入栈中

      2. 如果运算栈不为空,则对运算符进行优先级判断

        1. 如果当前运算符的优先级大于栈顶运算符则直接压入栈中

        2. 如果优先级低于或等于栈顶运算符,则,从数字栈中取出两个数据,将当前栈顶运算符弹出进行运算,将结果压入数字栈中,将当前运算符压入运算符栈中。

    3. 此时数字与运算符都已压入栈中,此时运算符栈中都是优先级相同的运算符,需要进行收尾操作,如果与算法栈不为空,则依次从数字栈中弹出两个数据与当前栈顶的运算符进行运算。将结果压入数字栈中,最后数字栈中的数字即为结果

代码:

#include <iostream>
#include <stack>
#include <string>
#include <unordered_map>
using namespace std;

stack<int> num;
stack<char> op;

//优先级表
unordered_map<char, int> h{ {'+', 1}, {'-', 1}, {'*',2}, {'/', 2} };


void eval()//求值
{
    int a = num.top();//第二个操作数
    num.pop();

    int b = num.top();//第一个操作数
    num.pop();

    char p = op.top();//运算符
    op.pop();

    int r = 0;//结果 

    //计算结果
    if (p == '+') r = b + a;
    if (p == '-') r = b - a;
    if (p == '*') r = b * a;
    if (p == '/') r = b / a;

    num.push(r);//结果入栈
}

int main()
{
    string s;//读入表达式
    cin >> s;

    for (int i = 0; i < s.size(); i++)
    {
        if (isdigit(s[i]))//数字入栈
        {
            int x = 0, j = i;//计算数字
            while (j < s.size() && isdigit(s[j]))
            {
                x = x * 10 + s[j] - '0';
                j++;
            }
            num.push(x);//数字入栈
            i = j - 1;
        }
        //左括号无优先级,直接入栈
        else if (s[i] == '(')//左括号入栈
        {
            op.push(s[i]);
        }
        //括号特殊,遇到左括号直接入栈,遇到右括号计算括号里面的
        else if (s[i] == ')')//右括号
        {
            while(op.top() != '(')//一直计算到左括号
                eval();
            op.pop();//左括号出栈
        }
        else
        {
            while (op.size() && h[op.top()] >= h[s[i]])//待入栈运算符优先级低,则先计算
                eval();
            op.push(s[i]);//操作符入栈
        }
    }
    while (op.size()) eval();//剩余的进行计算
    cout << num.top() << endl;//输出结果
    return 0;
}

相关代码解释:

 #include <stack>:引入栈头文件

#include <unordered_map>:引入无序键值对,例如h [ '+' ] == 1

模拟队列:

概念:

先进先出,先插入的元素先弹出来,类似羽毛球筒

数组模拟:

#include<iostream>
#include<cstring>

using namespace std;

const int N = 100010;

int q[N], t = 0, f = 0;//t表示下一个将用到的位置,f表示头的位置


//队尾插入x
void push(int x)
{
	q[t++] = x;
}

//对头弹出一个数
void pop()
{
	f++;
}
//查询是否为空
void empty()
{
	if (f == t) cout << "YES" << endl;
	else cout << "NO" << endl;
}
//查询队头元素
int query()
{
	return q[f];
}
int main()
{
	int m;
	cin >> m;
	while (m--)
	{
		string op;
		int x;
		cin >> op;
		if (op == "push")
		{
			cin >> x;
			push(x);
		}
		else if (op == "pop")
		{
			pop();
		}
		else if (op == "empty")
		{
			empty();
		}
		else if (op == "query")
		{
			cout << query() << endl;
		}
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值