以下算法均为用数组替代迭代器来进行(除了最后的stl),是针对算法竞赛而使用的,使用数组进行代码实现时间复杂度比用stl少,但会浪费部分空间,因此不考虑实际项目.
单链表
一.主体思想
使用value[N]数组储存当前位置的值,用nex[N]数组存储当前位置的下一个指向下一个位置,head存储头节点的指向,flag为当前位置.
二.重要代码
(1).链表初始化
当前位置为0,头结点指向空
代码:
void init()
{
head = -1;
flag = 0;
}
(2).表头插入
插入的数字指向表头的指向,表头指向插入的数字
代码:
void remove(int x)
{
ne[x] = ne[ne[x]];
}
(3).删除
让指向删除的数的数指向删除的数指向的数(多读几遍qwq)
代码:
void insert(int k, int x)
{
val[flag] = x;
ne[flag] = ne[k];
ne[k] = flag;
flag++;
}
(4).任意位置后插入一个数
让插入的数字指向被插入的数的指向,被插入的数指向插入的数字
代码:
void insert(int k, int x)
{
val[flag] = x;
ne[flag] = ne[k];
ne[k] = flag;
flag++;
}
三.整体代码
#include<iostream>
using namespace std;
const int N = 10010;
int val[N], ne[N];
int head, flag;
void init()
{
head = -1;
flag = 0;
}
void add_head(int x)
{
val[flag] = x;
ne[flag] = head;
head = flag;
flag++;
}
void insert(int k, int x)
{
val[flag] = x;
ne[flag] = ne[k];
ne[k] = flag;
flag++;
}
void remove(int x)
{
ne[x] = ne[ne[x]];
}
int main()
{
int round;
cin >> round;
init();
while (round--)
{
char order;
int k, x;
cin >> order;
if (order == 'H')
{
cin >> x;
add_head(x);
}
else if (order == 'D')
{
cin >> k;
if (!k) head = ne[head];
remove(k - 1);
}
else
{
cin >> k >> x;
insert(k-1, x);
}
for (int i = head; i != -1; i = ne[i])
{
cout << i << " " << val[i] << " "<<endl;
}
cout << endl;
}
return 0;
}
四.例题
AcWing——826单链表
双链表
一.主体思想
val[N]数组存储当前位置的值,用l[N]存储当前位置左边的指向,用r[N]存储当前位置右边的指向,flag为当前位置.
二.重要函数
(1)重置链表
用0代替头结点,用1代替尾节点,则最开始l[0]指向最右边1,r[1]指向最左边0,则flag从2开始
代码:
void init()
{
r[0] = 1;
l[1] = 0;
flag = 2;
}
(2)头插入数据
当前位置右边指向表头的右指向向,左边指向表头,表头的右指向的位置左边指向当前位置,表头右指向表头
代码:
void add_head(int x)
{
val[flag] = x;
l[flag] = 0;
r[flag] = r[0];
l[r[flag]] = flag;
r[0] = flag;
flag++;
}
(3)尾插入数据
当前位置左边指向表尾的左指向,右边指向标为,表尾的左指向的位置向右指向当前位置,表尾向左指向当前位置
代码:
void add_end(int x)
{
val[flag] = x;
l[flag] = l[1];
r[flag] = 1;
r[l[flag]] = flag;
l[1] = flag;
flag++;
}
(4)任意位置后方或前方插入一个数字
*1.后方插入:
当前位置向右指向被插入位置的右指向,向左指向被插入的位置,被插入位置的右指向向左指向当前位置,被插入的位置向右指向当前位置.
代码:
void insert(int k,int x)
{
val[flag] = x;
r[flag] = r[k];
l[flag] = k;
r[k] = flag;
l[r[flag]] = flag;
flag++;
}
*2.前方插入:
同理与向右插入,相当于插入位置的左指向位置的右边插入一个位置.
重要代码:
之前的k替换成r[l[k]].
(5)删除某一位置
需要删除的位置左指向向右指向删除位置的右指向,需要删除的位置的右指向向左指向删除位置的左指向.
代码:
void remove(int k)
{
l[r[k]] = l[k];
r[l[k]] = r[k];
}
三.整体代码:
#include<iostream>
using namespace std;
const int N = 100010;
int l[N], r[N],val[N];
int flag;
void init()
{
l[1] = 0;
r[0] = 1;
flag = 2;
}
void insert(int k,int x)
{
val[flag] = x;
r[flag] = r[k];
l[flag] = k;
r[k] = flag;
l[r[flag]] = flag;
flag++;
}
void add_head(int x)
{
val[flag] = x;
l[flag] = 0;
r[flag] = r[0];
l[r[flag]] = flag;
r[0] = flag;
flag++;
}
void add_end(int x)
{
val[flag] = x;
l[flag] = l[1];
r[flag] = 1;
r[l[flag]] = flag;
l[1] = flag;
flag++;
}
void remove(int k)
{
l[r[k]] = l[k];
r[l[k]] = r[k];
}
int main()
{
int round;
cin >> round;
init();
while (round--)
{
int k, x;
string order;
cin >> order;
if (order == "L")
{
cin >> x;
insert(0, x);
}
else if(order=="R")
{
cin >> x;
insert(l[1],x);
}
else if(order=="D")
{
cin >> k;
remove(k+1);
}
else if (order == "IL")
{
cin >> k >> x;
insert(l[k+1], x);
}
else if (order == "IR")
{
cin >> k >> x;
insert(k+1, x);
}
}
for (int i = r[0]; i != 1; i = r[i])
{
cout << val[i] << " ";
}
return 0;
}
栈
一.主要思想
用stk[N]数组存储栈的值,用tt表示栈顶的位置,通过tt的改变来进行栈的变化
二.主要代码:
1.插入
每存一个数让tt加一,从而做到先入后出
void insert(int x)
{
stk[++tt] = x;
}
2.删除
直接让tt加一,栈顶位置往前缩一位,此位置有新的数据输入时被更新.
void remove()
{
tt--;
}
3.判断栈是否为空
对栈顶的位置进行判断,如果栈顶位置为0则为空
bool judge()
{
if (tt > 0)
{
return false;
}
else
{
return true;
}
}
单调栈
例题:
牛客竞赛 Early Orders
AcWing 单调栈
题解:
牛客竞赛 Early Orders
队列
一.主要思想
用q[N]数组代替队列,用hh指向队首,用tt指向队尾,通过队首hh的变化从而达到队列的效应
二.关键代码
(1)插入数据
每存一个数让tt(队尾)加一,每次取数从hh(队首)取,从而达到先入先出.
代码:
void insert(int x)
{
q[++tt] = x;
}
(2)删除数据
直接让hh(队首)加一,此位置抛弃.
代码:
void remove()
{
hh++;
}
(3)判断队列是否为空
如果hh(队首)大于tt(队尾)即为空
代码:
bool judge()
{
if (hh <= tt)
{
return false;//非空
}
else
{
return true;
}
}
(4)输出队首元素
直接输出hh(队首)的数据
代码:
int check_head()
{
return q[hh];
}