课堂内容
引入
链表是一种用于存储数据的线性数据结构,通过如链条一般的指针来连接元素。它的特点是插入与删除数据十分方便,但寻找与读取数据的表现欠佳。
与数组的区别
链表和数组都可用于存储数据。与链表不同,数组将所有元素按次序依次存储。不同的存储结构令它们有了不同的优势:
链表因其链状的结构,能方便地删除、插入数据,操作次数是
O
(
1
)
O(1)
O(1)。但也因为这样,寻找、读取数据的效率不如数组高,在随机访问数据中的操作次数是
O
(
n
)
O(n)
O(n)。
数组可以方便地寻找并读取数据,在随机访问中操作次数是 O ( 1 ) O(1) O(1)。但删除、插入的操作次数是 O ( n ) O(n) O(n) 次。
重点在于删除和插入
删除:p的next赋值为p的next的next
插入:先新节点的next赋值为p的next,后p的next赋值为新节点
数组模拟动态写法
#include <iostream>
#include <string>
using namespace std;
const int N = 1e5 + 10;
struct node {
string name;
int gra;
int nxt;
} a[N]; //内存池
int tot;
int getMey() {
return ++tot;
}
void insert(int pre, int hd) {
a[hd].nxt = a[pre].nxt;
a[pre].nxt = hd;
}
void del(int pre) {
a[pre].nxt = a[a[pre].nxt].nxt;
}
int main() {
int head = getMey();
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
string nm;
int ga;
cin >> nm >> ga;
int hd = getMey();
a[hd] = {nm, ga, 0};
insert(head, hd);
}
for (int hd = a[head].nxt; hd != 0; hd = a[hd].nxt) {
cout << a[hd].name << " " << a[hd].gra << endl;
}
del(head);
cout << endl;
for (int hd = a[head].nxt; hd != 0; hd = a[hd].nxt) {
cout << a[hd].name << " " << a[hd].gra << endl;
}
return 0;
}
指针动态写法
#include <iostream>
#include <string>
#include <list>
using namespace std;
const int N = 1e5 + 10;
struct node {
string name;
int gra;
node *nxt;
};
//int tot;
node *getMey() {
return new node;
}
void insert(node *pre, node *hd) {
// a[hd].nxt = a[pre].nxt;
// a[pre].nxt = hd;
hd->nxt = pre->nxt;
pre->nxt = hd;
}
void del(node *pre) {
// a[pre].nxt = a[a[pre].nxt].nxt;
pre->nxt = pre->nxt->nxt;
}
int main() {
node *head = getMey();
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
string nm;
int ga;
cin >> nm >> ga;
node *hd = getMey();
// a[hd] = {nm, ga, 0};
*hd = {nm, ga, NULL};
insert(head, hd);
}
for (node *hd = head->nxt; hd != NULL; hd = hd->nxt) {
cout << hd->name << " " << hd->gra << endl;
}
del(head);
cout << endl;
for (node *hd = head->nxt; hd != NULL; hd = hd->nxt) {
cout << hd->name << " " << hd->gra << endl;
}
return 0;
}
STL
list<int> l;
l.empty();
l.insert(/*迭代器*/,/*元素*/);
l.size();
l.sort();
l.sort(cmp);
l.begin();
l.end();
l.reverse();
l.clear();
l.unique();
l.erase(/*迭代器*/);
/*尾部*/
l.push_back(/*元素*/);
l.pop_back();
l.back();
/*头部*/
l.front();
l.push_front(/*元素*/);
l.pop_front();
题目讲解
B3631
不要数据,只要节点号
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int nxt[N];
int main() {
int t;
cin >> t;
while (t--) {
int op, x, y;
cin >> op;
if (op == 1) {
cin >> x >> y;
nxt[y] = nxt[x];
nxt[x] = y;
} else if (op == 2) {
cin >> x;
cout << nxt[x] << endl;
} else {
cin >> x;
nxt[x] = nxt[nxt[x]];
}
}
return 0;
}
P1996
双向链表
#include <iostream>
using namespace std;
const int N = 110;
int nxt[N], pre[N], n, m;
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
nxt[i] = i + 1;
pre[i] = i - 1;
}
nxt[n] = 1;
pre[1] = n;
nxt[0] = 1;
int sz = n, p = 0;
while (sz) {
for (int i = 1; i <= m; i++) {
p = nxt[p];
}
cout << p << " ";
nxt[pre[p]] = nxt[p];
pre[nxt[p]] = pre[p];
sz--;
}
return 0;
}
作业
1.P1160
2.把链表的几种写法和STL写法理解透彻并写上注释