链表
链表一般需要设置结点并分配结点空间,这个动态分配空间的过程非常慢,所以一般在笔试中不用链表,在面试中有可能会问到,在笔试和上机中都用数组来模拟链表。
用数组模拟单链表
单链表在算法、笔试题中用的最多的是邻接表。邻接表最多的应用是存储图和树。(eg:最短路径、最小生成树)
用e[N]表示value,用ne[N]表示next指针。(如果是顺序链,那么 ne[0] = 1, ne[1] = 2, ne[2] = 3, … , ne[n] = -1)
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
// head 表示头结点的下标
// e[i] 表示结点i的值
// ne[i] 表示结点i的next指针是多少
// idx 存储当前已经用到了哪个点
int head, e[N], ne[N], idx;
// 初始化
void init(){
head = -1;
idx = 0;
}
// 将x插到头结点
void add_to_head(int x){
e[idx] = x, ne[idx] = head, head = idx, idx++;
}
//将x插到下标是k的点后面
void add(int k,int x){
e[idx] = x;
ne[idx] = ne[k];
ne[k] = idx;
idx++;
}
// 将下标是k的点后面的点删除
void remove(int k){
ne[k] = ne[ne[k]];
}
int main(){
}
用数组模拟双链表
双链表最多的应用是用来优化某些问题。
双链表需要记录前边的一个结点和后边的一个结点,所以定义数组 l[N], r[N],
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int m;
int e[N], l[N], r[N], idx;
//初始化
void init(){
// 0 表示左端点, 1 表示右端点
r[0] = 1, l[1] = 0;
idx = 2;
}
// 在下标是k的点的右边,插入x
void add(int k, int x){
e[idx] = x;
r[idx] = r[k];
l[idx] = k;
l[r[k]] = idx;
r[k] = idx;
}
// 删除第k个点
void remove(int k){
r[l[k]] = r[k];
l[r[k]] = l[k];
}
栈、队列
用数组模拟栈
栈:先进后出
#include<iostream>
using namespace std;
const int N = 1e5+10;
int stk[N], tt;
//插入
stk[ ++t ] = x;
//弹出
tt--;
//判断栈是否为空
if(tt>0) not empty
else empty
//栈顶
stk[tt];
例题:表达式求值。
eg:计算(2+2)*(1+1)的结果
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <unordered_map>
using namespace std;
stack<int> num;
stack<char> op;
void eval()
{
auto b = num.top(); num.pop();
auto a = num.top(); num.pop();
auto c = op.top(); op.pop();
int x;
if (c == '+') x = a + b;
else if (c == '-') x = a - b;
else if (c == '*') x = a * b;
else x = a / b;
num.push(x);
}
int main()
{
unordered_map<char, int> pr{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};
string str;
cin >> str;
for (int i = 0; i < str.size(); i ++ )
{
auto c = str[i];
if (isdigit(c))
{
int x = 0, j = i;
while (j < str.size() && isdigit(str[j]))
x = x * 10 + str[j ++ ] - '0';
i = j - 1;
num.push(x);
}
else if (c == '(') op.push(c);
else if (c == ')')
{
while (op.top() != '(') eval();
op.pop();
}
else
{
while (op.size() && op.top() != '(' && pr[op.top()] >= pr[c]) eval();
op.push(c);
}
}
while (op.size()) eval();
cout << num.top() << endl;
return 0;
}
用数组模拟队列
队列:先进先出
// 在队尾插入元素, 在队头弹出元素
int q[N], hh, tt = -1;
//插入
q[++ tt] = x;
//弹出
hh++;
//判断队列是否为空
if(hh<=tt) not empty
else empty
//取出队头元素
q[hh]
//取出队尾元素
q[tt]