算法相关整理(蓝桥杯)

前言

编辑器: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.双链表

习题:https://www.acwing.com/problem/content/description/829/

(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)习题

题目:https://www.luogu.com.cn/problem/P5788

题目求解:

求解过程:

#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];
}

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值