前言
编辑器:codeblocks
链接:https://pan.baidu.com/s/1Hywq6hxzxMzX1-22ig2HdA
提取码:kd65
相关网站:
1.单链表
(1)单链表插入:
(2)单链表删除:
(3)基本代码:
#include<iostream>
using namespace std;
//采用头插法
//e[N]表示数值,ne表示下一个节点的位置,idx表示数量,h表示头结点
int e[N], ne[N], idx, h;
void init() {
h = -1;
idx = 0;
}
void insert(int n) {
e[idx] = n;
ne[idx] = h;
h = idx++;
}
//删除n后一个节点
void remove(int n) {
ne[n] = ne[ne[n]];
}
void add(int n, int x) {
e[idx] = x;
ne[idx] = ne[n];
ne[n] = idx++;
}
int main() {
return 0;
}
(4)例题
https://www.acwing.com/problem/content/828/
#include<iostream>
using namespace std;
const int N = 100000+10;
int e[N], ne[N], idx, head;
void Init() {
head = -1;
idx = 0;
}
void add_head(int x) {
e[idx] = x;
ne[idx] = head;
head = idx++;
}
void remove(int k) {
ne[k-1] = ne[ne[k-1]];
}
void add(int k, int x) {
e[idx] = x;
ne[idx] = ne[k-1];
ne[k-1] = idx++;
}
int main() {
int m, k, x;
cin>>m;
Init();
while(m--) {
char ch;
cin>>ch;
if(ch == 'H') {
cin>>x;
add_head(x);
} else if(ch == 'D') {
cin>>k;
if(k == 0) {
head = ne[head];
} else {
remove(k);
}
} else {
cin>>k>>x;
add(k, x);
}
}
for(int i = head; i != -1; i = ne[i]) {
cout<<e[i]<<' ';
}
return 0;
}
总结
这个是用数组实现的,所以实际上并没有删除,只是逻辑上的删除,所以index的值一直都是++1
修改的只是head值,和en[N]的值
2.双链表
(1)头插法插入、删除
(2)增加结点
#include<iostream>
#include<string.h>
using namespace std;
const int N = 100000;
int l[N], r[N], e[N], idx;
void Init() {
//l[1]存储 左边(前驱)开始头结点的位置
//r[0]存储 右边(后继)开始头结点的位置
l[1] = 0;
r[0] = 1;
idx = 2;
}
//头插法
void insert_L(int x) {
//新增的节点的左右节点
e[idx] = x;
l[idx] = 0;
r[idx] = r[0];
//将头指针指向idx
r[0] = idx;
//将原来的头结点的后继节点指向idx
//先把idx赋值,在自增
l[r[idx]] = idx;
idx++;
}
void insert_R(int x) {
//新增节点的左右节点
e[idx] = x;
r[idx] = 1;
l[idx] = l[1];
//将尾指针指向idx
l[1] = idx;
//将原来的头结点的前驱节点指向idx
//先把idx赋值,再自增
r[l[idx]] = idx;
idx++;
}
void remove(int k){
//k表示第k次输入,要对题目中输入的初始化,满足编程条件
//因为idx是从2开始,但是输入的k是从1开始
//k输入的值比idx小1,所以k+1才能获取对应idx的值
//那么先对k进行初始化
k = k + 1;
//将idx的前驱结点的指针,指向idx的后驱结点
r[l[k]] = r[k];
//将idx的后驱结点的指针,指向idx的前驱结点
l[r[k]] = l[k];
}
//在k结点的左边加入一个结点
//k表示第k个插入,x表示数值
void add_k_l(int k, int x) {
//k表示第k次输入
//因为idx是从2开始,但是输入的k是从1开始
//k输入的值比idx小1,所以k+1才能获取对应idx的值
//那么先对k进行初始化
k = k + 1;
//将idx的值设置为x
//将插入结点的前驱指针:指向原来k的前驱结点
//将插入结点的后继指针:指向k
e[idx] = x;
l[idx] = l[k];
r[idx] = k;
//将k的前驱结点(idx的前驱结点)的后继指针:指向idx
r[l[idx]] = idx;
//将k的前驱指针设置为idx
//idx自增
l[k] = idx++;
}
//在k结点的右边插入
void add_k_r(int k, int x) {
k++;
e[idx] = x;
r[idx] = r[k];
l[idx] = k;
r[k] = idx;
l[r[idx]] = idx;
idx++;
}
int main() {
int m, k, x;
string s;
Init();
cin>>m;
while(m--){
cin>>s;
if(s == "L") {
cin>>x;
insert_L(x);
}
else if(s == "R") {
cin>>x;
insert_R(x);
}
else if(s == "D") {
cin>>x;
remove(x);
}
else if(s == "IL") {
cin>>k>>x;
add_k_l(k, x);
}
else if(s == "IR") {
cin>>k>>x;
add_k_r(k, x);
}
}
for(int i = r[0]; i != 1; i = r[i]) {
cout<<e[i]<<' ';
}
return 0;
}
无注释
#include<iostream>
#include<string.h>
using namespace std;
const int N = 100000;
int l[N], r[N], e[N], idx;
void Init(){
r[0]=1;
l[1]=0;
idx=2;
}
void add_L(int x){
e[idx]=x;
l[idx]=0;
r[idx]=r[0];
r[0]=idx;
l[r[idx]]=idx;
idx++;
}
void add_R(int x){
e[idx]=x;
r[idx]=1;
l[idx]=l[1];
l[1]=idx;
r[l[idx]]=idx;
idx++;
}
void remove(int k) {
r[l[k+1]]=r[k+1];
l[r[k+1]]=l[k+1];
}
void add_k_l(int k, int x) {
k++;
e[idx] = x;
l[idx] = l[k];
r[idx] = k;
r[l[idx]] = idx;
l[k] = idx++;
}
void add_k_r(int k, int x) {
k++;
e[idx] = x;
r[idx] = r[k];
l[idx] = k;
l[r[idx]] = idx;
r[k] = idx++;
}
int main() {
int m, k, x;
string s;
Init();
cin>>m;
while(m--){
cin>>s;
if(s=="L"){
cin>>x;
add_L(x);
}
else if(s == "R"){
cin>>x;
add_R(x);
}
else if(s == "D") {
cin>>k;
remove(k);
}
else if(s == "IL") {
cin>>k>>x;
add_k_l(k, x);
}
else{
cin>>k>>x;
add_k_r(k, x);
}
}
for(int i = r[0]; i != 1; i = r[i]) {
cout<<e[i]<<' ';
}
return 0;
}
3.栈和队列
(1)知识点
#include<iostream>
using namespace std;
const int N = 1000010;
//栈 先进后出
int stk[N], tt;
//入栈 先自增,再赋值
stk[++tt] = x;
//出栈
tt--
//判空
if(tt == 0) true
//栈顶元素
stk[tt]
//队列 先进先出
//队头初始化0;队尾初始化-1
int q[N], hh, tt = -1;
//入队
q[++tt] = x;
//出队
hh++;
//获取队头和队尾的元素
q[hh]
q[tt]
//判空
if(tt>=hh) false
else true
(2)习题
题目求解:
求解过程:
#include<iostream>
#include<cstdio>
using namespace std;
const int N=3000000+10;
//int x 要是不赋值默认为:x=0
//stk[i]:表示一个栈
//tt:表示stk的栈顶
//e[i]:存放i所在的序号
//a[i]:存放数列
//q[i]:用来存放输出结果
//qq:表示q的栈顶
int stk[N], tt, e[N], a[N], q[N], qq;
int main() {
int n;
scanf("%d", &n);
//将输入的数值存在数组a中
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for(int i = n; i > 0; i--) {
//有栈顶元素,并且栈顶元素小于a[i]
//则 把栈顶元素弹出
while(tt && stk[tt] <= a[i]) {
tt--;
}
//最后一个元素一定没有可比的,那结果一定是0
if(tt == 0) {
q[qq++] = 0;
}
//只要不是最后一个元素
//就把e[i]中保存的栈顶元素的序号,赋值给q
else {
q[qq++] = e[tt];
}
//将a[i]入栈
stk[++tt] = a[i];
//将栈顶元素的序号保存在数组e中
e[tt] = i;
}
for(int i = qq - 1; i > -1; i--) {
printf("%d ", q[i]);
}
return 0;
}
4.树
(1)图解
(2)代码
#include<iostream>
using namespace std;
const int N = 1e5+10;
//假设都是小写字母
//N:第idx个数字所在的行
//27表示字母是否存在
//cnt表示标记
//idx表示地址,唯一
int p[N][27], cnt[N], idx = 1;
char s[N];
//增加字符串
void add(char *s){
//j用来存放最后一个字符的地址
int j = 0;
for(int i = 0; s[i]; i++) {
//将s[i]对应的序号算出,范围是0~26
int u = s[i] - 'a';
//如果p对应的值为0,说明以前没有出现过,那么需要将地址赋值给它
if(p[j][u] == 0) {
p[j][u] = idx++;
}
//将s[i]的最后一个字符的地址idx赋值给j
j = p[j][u];
}
cnt[j]++;
}
//查询字符串
int insert(char *s){
int j = 0;
for(int i = 0; s[i]; i++) {
int u = s[i] - 'a';
if(p[j][u] == 0) {
return 0;
}
j = p[j][u];
}
//返回s[j]的标记
return cnt[j];
}