前言
链表是数据结构中十分重要的一个内容,我们应该熟练掌握他们基本的内容,接下来我将用数组模拟的方式为大家来进行讲解!!!
一、单链表
模拟过程:
我们用e[N]来表示某个点的值是多少,ne[N]来表示某个点的next指针是多少,e跟ne用下标关联起来的,空节点用-1来表示,e[0]==某个值,ne[0]=1(next指针),以此类推...
如图:
例题及代码讲解:
例题:
AC代码及讲解:
//链表
//struct Node{
// int val;
// Node *next;
//};
//竞赛中最常用的是邻接表
//邻接表用的最多的是 存储图 和 树
//双链表用来优化某些问题
#include <iostream>
using namespace std;
const int N = 100010;
//head表示头结点的下标
//e[i]表示节点i的值
//ne[i]表示节点i的next指针是多少,或者说下一个节点i的地址是什么
//idx存储当前已经用到了哪个点
int head, e[N], ne[N], idx;
//初始化
void init() {
head = -1;
idx = 0;
}
//将x插入到头结点:
//1.将x的next指针指向head节点指向的下一个位置
//2.将head指针删掉,然后指向x节点
void add_to_head(int x) {
e[idx] = x; //把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() {
int m;
cin >> m;
init();//初始化
while (m--) {
int k, x;
char op;
cin >> op;
if (op == 'H') {
cin >> x;
add_to_head(x);
} else if (op == 'D') {
cin >> k;
if (!k)
head = ne[head];
else
remove(k - 1);
} else {
cin >> k >> x;
add(k - 1, x);
}
}
for (int i = head; i != -1; i = ne[i])
cout << e[i] << ' ';
cout << endl;
return 0;
}
二、双链表
模拟过程:
1、用两个数组来代表左单链表和右单链表,即为l[N],r[N]
2、l[N]数组为指向右边的链表,r[N]为指向左边的链表
3、e[N]为当前结点的值
4、设r[0]=1,l[1]=0,因为是相互指向
5、同样用一个idx来储存当前结点用到了哪一点
图例:
例题及代码讲解:
例题:
AC代码及讲解:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100010;
//e用来存储数值,
//l[]用来存储前驱(左边数的下标),
//r[]用来存储后继(右边数的下标)
//idx用来记录当前下标
int e[N], l[N], r[N], idx;
//初始化
void init() {
//0表示左端点,1表示右端点
r[0] = 1;
l[0] = 0;
idx = 2;//因为0和1已经被占用了
}
//在第k点的右边插入x
void add_to_right(int k, int x) {
e[idx] = x;//将x存入当前下标的数值数组中
r[idx] = r[k];//当前下标的后继为k的后继
l[idx] = k;//当前下标的前驱为k
l[r[k]] = idx;//k的后继节点的前驱为idx
r[k] = idx++;//k的后继节点为idx,idx++
}
//在k点的左边插入x,等价于在l[k]的右边插入x,也就是add_to_right(l[k],x);
void add_to_left(int k, int x) {
add_to_right(l[k], x);
}
//删除第k个点
void remove(int k) {
r[l[k]] = r[k];//k的前驱的后继为k的后继
l[r[k]] = l[k];//k的后继的前驱为k的前驱
}
//在链表的最左端插入数x
void add_to_head(int x) {
add_to_right(0, x);//在0后面插入x
}
//在链表的最右端插入数x
void add_to_tail(int x) {
add_to_right(l[1], x);
}
int main() {
int m;
init();
cin >> m;
int k, x;
while (m--) {
string op;
cin >> op;
if (op == "L") {
cin >> x;
add_to_head(x);
} else if (op == "R") {
cin >> x;
add_to_tail(x);
} else if (op == "D") {
cin >> k;
remove(k + 1);
} else if (op == "IL") {
cin >> k >> x;
add_to_left(k + 1, x);
} else {
cin >> k >> x;
add_to_right(k + 1, x);
}
}
for (int i = r[0]; i != 1; i = r[i]) {
cout << e[i] << ' ';
}
cout << endl;
return 0;
}