线性表——栈 & 队列

栈无法随机访问。

1 函数实现栈

#include <iostream>
using namespace std;
int s[1000];
int t;
void Push(int x){
    s[++t]=x;
}
void Pop(){
    t--;
}
void Print()
{
    for (int i=0; i<=t; i++){
        cout<<s[i]<<" ";
    }
    cout<<endl;
}
void Top(){
    cout<<"top = "<<s[t]<<endl;
}
int main(){
    Push(1);
    Push(3);
    Push(5);
    Push(7);
    Print();
    Top();
    Pop();
    Top();
}

运行结果:
在这里插入图片描述

2 宏定义实现栈

#include <iostream>
using namespace std;
int s[1000];
int t=0;
#define push(x) s[++t]=x
#define pop() t--
#define size() t
#define top() cout<<"top = "<<s[t]<<endl;
void print(){
    for(int i=0; i<=t; i++){
        cout<<s[i]<<" ";
    }
    cout<<endl;
}
int main(){
    push(1);
    push(3);
    push(5);
    push(7);
    print();
    top();
    pop();
    top();
}

运行结果:
在这里插入图片描述

3 STL实现栈

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

int main(){
    stack<int>s;
    for(int i=0; i<5; i++){
        s.push(i);
    }
    cout<<"top = "<<s.top()<<endl;
    cout<<"size = "<<s.size()<<endl;
    while(!s.empty()){
        cout<<"top = "<<s.top()<<endl;
        s.pop();
    }
    return 0;
}

运行结果:
在这里插入图片描述

4 示例

4.1 括号序列

//给定一个字符串,里边可能包含“()”和其他字符,请编写程序检查该字符串中的括号是否成对出现。
#include <iostream>
#include <stack>
using namespace std;

bool isValid(string str)
{
    stack<char> s;
    char c;
    int len = str.length();
    for (int i = 0; i < len; i++)
    {
        if (str[i] == '(' || str[i] == '[' || str[i] == '{')
        {
            s.push(str[i]); 
        }
        else if (str[i] == ')')
        {
            if (s.empty()){
                return false;
            }
            else if ((c = s.top())&&(c == '('))
                s.pop();
            else{
                return false;
            }
        }
        else if (str[i] == ']')
        {
            if (s.empty()){
                return false;
            }
            else if ((c = s.top())&&(c == '['))
                s.pop();
            else{
                return false;
            }
        }
        else if (str[i] == '}')
        {
            if (s.empty()){
                return false;
            }
            else if ((c = s.top())&&(c == '{'))
                s.pop();
            else{
                return false;
            }
        }
    }
    if (s.empty())
        return true;
    else
        return false;
}
int main()
{
    string str = "y={x+[x(x+2)]}";
    bool check=true;
    check = isValid(str);
    if (check == true)
        cout << "Valid."<<endl;
    else
        cout << "Not valid."<<endl;
    return 0;
}

4.2 后缀表达式

题目描述

所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。

如: 3*(5-2)+7 \texttt{3*(5-2)+7} 3*(5-2)+7 对应的后缀表达式为: 3.5.2.-*7.+@ \texttt{3.5.2.-*7.+@} 3.5.2.-*7.+@。在该式中,@ 为表达式的结束符号。. 为操作数的结束符号。

输入格式

输入一行一个字符串 s s s,表示后缀表达式。

输出格式

输出一个整数,表示表达式的值。

样例

样例输入

3.5.2.-*7.+@

样例输出

16
代码
// 后缀表达式(逆波兰表达式)
#include <iostream>
#include <string>
#include <stack>
using namespace std;

int caculate(string &notation)
{
    // 1 创建一个栈对象oprands存储操作数
    stack<int> oprands;
    int result = 0;
    // 2 从左往右遍历表达式,如果为操作数就入栈,如果是运算符,就从栈中弹出两个操作数进行计算,并将计算结果压入栈中
    for (int i = 0; i < notation.length(); i++)
    {
        char current = notation[i];
        int o1, o2;

        switch (current)
        {
        case '+':
            o1 = oprands.top();
            oprands.pop(); // pop不返回任何值,无法直接进行o1=oprands.pop()操作
            o2 = oprands.top();
            oprands.pop();
            result = o2 + o1;
            oprands.push(result);
            break;
        case '-':
            o1 = oprands.top();
            oprands.pop(); // pop不返回任何值,无法直接进行o1=oprands.pop()操作
            o2 = oprands.top();
            oprands.pop();
            result = o2 - o1; // o1-o2的后缀表达式为o1 o2 -,出栈顺序为o2 o1,除法同理
            oprands.push(result);
            break;
        case '*':
            o1 = oprands.top();
            oprands.pop(); // pop不返回任何值,无法直接进行o1=oprands.pop()操作
            o2 = oprands.top();
            oprands.pop();
            result = o2 * o1;
            oprands.push(result);
            break;
        case '/':
            o1 = oprands.top();
            oprands.pop(); // pop不返回任何值,无法直接进行o1=oprands.pop()操作
            o2 = oprands.top();
            oprands.pop();
            result = o2 / o1;
            oprands.push(result);
            break;
        default:
            int c = current - '0'; //将char current转为int c
            oprands.push(c);       //用c而不是current入栈
            // oprands.push(current);  //此处是'3'而不是数字3,入栈的是'3'的ACSII码51,后续计算都是按照51进行的,故计算错误!!

            break;
        }
    }
    result = oprands.top();
    return result;
}

int main()
{
    string test = "352-*7+";
    cout << "test = 352-*7+ = " << caculate(test) << endl;
    getchar();
    return 0;
}

*注: 字符型char与整型int的转换

char c = '6';
int num = c - '0';	//num=6

int num = 5;
char c = num + '0';	//c='6'

字符串型转整型:

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    string str = "123456";
    int n = stoi(str); //转换为整型 n = 123456(转换失败时发生异常)
    cout << n << endl;
    // int n = atoi(str);   //作用同stoi(),区别在于转换失败时返回0 
    getchar();
    return 0;
}

队列

1 宏定义实现

#include <iostream>
#define push(x) d[++end]=x
#define pop() fnt++
#define front() s[fnt]
#define size() end-fnt+1

2 STL实现

queue是STL中的队列模板。

#include <iostream>
#include <queue>
using namespace std;

int main()
{
    queue<int>q;
    for(int i=0; i<5; i++){
        q.push(i);
    }
    q.pop();	//删除队头
    cout<<q.front()<<endl;	//返回队头
    cout<<q.back()<<endl;	//返回队尾
    getchar();
    return 0;
}

3 示例:约瑟夫问题

题目描述

n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号.
输入格式
n m
输出格式
出圈的编号

输入输出样例

输入

10 3

输出

3 6 9 2 7 1 8 5 10 4

代码求解

//约瑟夫问题
#include <iostream>
#include <queue>
using namespace std;
void solve(){
    queue<int>q;
    int n,m;
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        q.push(i);
    }
    int curr=1;
    while(!q.empty()){
        if(curr==m){
            cout<<q.front()<<" ";
            q.pop();
            curr=1;
        }
        else{
            q.push(q.front());  //环
            q.pop();
            curr++;
        }
    }
    cout<<endl;
}
int main(){
    solve();
    getchar();
    return 0;
}

4 双端队列

在这里插入图片描述

STL实现

deque是STL中双端队列模板。

#include <iostream>
#include <deque>
using namespace std;
int main(){
	deque<int>d;
	d.push_front(1);
	d.push_front(2);
	d.push_back(10);
	d.push_back(20);
	cout<<d.front()<<endl;
	cout<<d.back()<<endl;
	cout<<d[2]<<endl;	//支持随机访问,但是时间复杂度较高O(n)
	d.pop_front();
	cout<<d.front()<<endl;
	getchar();
	return 0;
}

5 优先队列priority_queue

优先队列是一种特殊的队列,特性在于自动排序
和队列不一样的是,优先队列没有front()back()函数,只有top()函数,可以访问队首元素(堆顶元素),也就是优先级最高的元素。

#include <iostream>
#include <queue>
using namespace std;
int main(){
    priority_queue<int>pq;
    pq.push(6),pq.push(23),pq.push(2),pq.push(12),pq.push(9);
    while(!pq.empty()){
        cout<<pq.top()<<" ";
        pq.pop();
    }
    cout<<endl;
    getchar();
    return 0;
}

//输出23 12 9 6 2

结构体,重载小于

#include <iostream>
#include <queue>
using namespace std;
struct node
{
    int x, y;
    bool operator<(const node &a) const
    {
        return y < a.y; //按照y的大小从大到小排序
    }
} k;
int main()
{
    priority_queue<node> q;
    k.x = 10, k.y = 100;
    q.push(k);
    k.x = 12, k.y = 60;
    q.push(k);
    k.x = 14, k.y = 40;
    q.push(k);
    k.x = 6, k.y = 80;
    q.push(k);
    k.x = 8, k.y = 20;
    q.push(k);
    while (!q.empty())
    {
        node m = q.top();
        q.pop();
        cout << "(" << m.x << ", " << m.y << ") ";
    }
    cout << endl;
    getchar();
    return 0;
}

//输出结果:(10, 100) (6, 80) (12, 60) (14, 40) (8, 20)

less和greater优先队列

#include <iostream>
#include <queue>
using namespace std;
int main()
{
    int a[7] = {6, 9, 2, 8, 1, 14, 5};
    priority_queue<int, vector<int>, less<int>> p_less;	//从大到小
    priority_queue<int, vector<int>, greater<int>> p_greater;	//从小到大
    for (int i = 0; i < 7; i++)
    {
        p_less.push(a[i]);
        p_greater.push(a[i]);
    }
    cout << "less<int>: " << endl;
    while (!p_less.empty())
    {
        cout << p_less.top() << " ";
        p_less.pop();
    }
    cout << endl;

    cout << "greater<int>: " << endl;
    while (!p_greater.empty())
    {
        cout << p_greater.top() << " ";
        p_greater.pop();
    }
    cout << endl;

    getchar();
    return 0;
}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值