vector模拟链表,栈,单调栈,队列,单调队列

262 阅读4分钟

目录

单链表

双链表

例题:

队列:

单调栈:

单调队列


单链表

问题:用vector模拟单链表,实现三种操作

(1)向链表头插入一个数;                      H 
(2)删除第 k  个插入的数后面的数;      D        K        X
(3)在第 k 个插入的数后插入一个数        I         K        X

n表示共有n次操作,以上是命令,执行结束后,打印链表

本质:idx是核心,idx:链表尾节点的索引

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

const int N = 10010;
int e[N], ne[N];
int idx, head;

void init()
{
	head = -1;//头节点初始化尾-1
	idx = 0;//当前位置索引初始化为0
}

void add_to_head(int x)//头插
{
	e[idx] = x;//存储值
	ne[idx] = head;//将idx的下一个位置连接为head
	head = idx;//此时换头
	idx++;//当前操作索引++
}

void del(int k)
{
	ne[k] = ne[ne[k]];//即将这个点的存的下一个位置的地址改为后两个的地址
	//next=next->next;
}

void add(int k, int x)
{
	e[idx] = x;
	ne[idx] = ne[k];//将k位置的下一个地址存储入新节点,
	//相当于新节点此时指向原来k节点指向的下一个位置
	ne[k] = idx;//将k的下一个位置指向新开的节点
	idx++;//当前操作位置索引++
}

int main()
{
	init();
	int n;
	cin >> n;
	while (n--)
	{
		char op;
		int x;
		cin >> op;
		if (op == 'H')
		{
			cin >> x;
			add_to_head(x);
		}
		else if (op == 'D')
		{
			cin >> x;
			if (!x) head = ne[head];
			else del(x - 1);
		}
		else if (op == 'I')
		{
			int k;
			cin >> k >> x;
			add(k - 1, x);
		}
	}
	for (int i = head; i != -1; i = ne[i])
	{
		cout << e[i] << " ";
	}

	return 0;
}

双链表

问题:

实现一个双链表,双链表初始为空,支持 5种操作:

在最左侧插入一个数;
在最右侧插入一个数;
将第 k个插入的数删除;
在第 k 个插入的数左侧插入一个数;
在第 k个插入的数右侧插入一个数

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

const int N = 10010;
int m;
int e[N], l[N], r[N];
int idx;

void init()
{
	l[1] = 0;
	r[0] = 1;
	idx = 2;
}

void add(int k, int x)
{
	e[idx] = x;
	l[idx] = k;
	r[idx] = r[k];
	l[r[k]] == idx;
	r[k] = idx;
	idx++;
}

void remove(int k)
{
	r[l[k]] = r[k];
	l[r[k]] = l[k];
}

int main(void)
{
    ios::sync_with_stdio(false);
    cin >> m;

    init();

    while (m--)
    {
        string op;
        cin >> op;
        int k, x;
        if (op == "R")
        {
            cin >> x;
            add(l[1], x); //!   0和 1 只是代表 头和尾  所以   最右边插入 只要在  指向 1的 那个点的右边插入就可以了
        }
        else if (op == "L")//! 同理  最左边插入就是 在指向 0的数的左边插入就可以了   也就是可以直接在 0的 有右边插入
        {
            cin >> x;
            add(0, x);
        }
        else if (op == "D")
        {
            cin >> k;
            remove(k + 1);
        }
        else if (op == "IL")
        {
            cin >> k >> x;
            add(l[k + 1], x);
        }
        else
        {
            cin >> k >> x;
            add(k + 1, x);
        }
    }
    for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << ' ';

    return 0;
}

题目:实现一个栈,栈初始为空,支持四种操作

  1. push x – 向栈顶插入一个数 xx;
  2. pop – 从栈顶弹出一个数;
  3. empty – 判断栈是否为空;
  4. query – 查询栈顶元素

有n个操作,其中操作4返回栈顶元素,操作3表示yes or no

#include<iostream>
#include<vector>
using namespace std;
const int N = 10010;
int stk[N];
int hh = -1;
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		string op;
		int x;
		cin >> op;
		if (op == "push")
		{
			cin >> x;
			stk[++hh] = x;
		}
		else if (op == "pop")
		{
			hh--;
		}
		else if(op == "empty")
		{
			if (hh == -1) cout << "YES" << endl;
			else cout << "NO" << endl;
		}
		else if (op == "query")
		{
			cout << stk[hh] << endl;
		}
	}

	return 0;
}

例题:

AcWing 3302. 表达式求值:多图讲解运算符优先级+详细代码注释 - AcWingAcWing,题解,表达式求值:多图讲解运算符优先级+详细代码注释,https://www.acwing.com/solution/content/40978/


#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<iostream>
#include<vector>
using namespace std;

const int N = 10010;
int hh = -1, tt = -1;
int qu[N];

int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		string op;
		int x;
		cin >> op;
		if (op == "push")
		{
			cin >> x;
			qu[++tt] = x;
		}
		else if (op == "pop")
		{
			hh++;
		}
		else if (op == "empty")
		{
			if (hh <= tt) cout << "No" << endl;
			else cout << "Yes" << endl;
		}
		else if (op == "query")
		{
			cout << qu[hh] << endl;
		}
	}

	return 0;
}

单调栈:

问题:

给定一个长度为 N NN 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出-1

#include<iostream>
using namespace std;
const int N=100010;
int n;
int stk[N],tt;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
	cin>>n;
    for(int i=0;i<n;i++){
        int x;
        cin>>x;
        while(tt && stk[tt]>=x) tt--;//一直出栈,直到找到第一个比栈顶小的元素
        if(tt) cout<<stk[tt]<<" ";//栈不空,直接输出栈顶
        else cout<<-1<<' ';//不存在
        stk[++tt]=x;//该数入栈
    }
    return 0;
}

单调队列

154. 滑动窗口 - AcWing题库

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

const int N = 10010;
int a[N], q[N];
int hh = -1, tt = -1;

int main()
{

	int n, k;
	cin >> n >> k;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
		if (i - k + 1 > q[hh]) ++hh;
		while (hh <= tt && a[i] <= a[q[tt]]) --tt;
		q[++tt] = i;
		if (i + 1 >= k) cout << a[q[hh]];
	}
	cout << endl;
	hh = 0, tt = -1;
	for (int i = 0; i < n; i++)
	{
		if (i - k + 1 > q[hh])++hh;
		while (hh <= tt && a[i] >= a[q[tt]]) --tt;
		q[++tt] = i;
		if (i + 1 >= k) cout << a[q[hh]];
	}

	return 0;
}