第二讲 数据结构

1.单链表

AcWing 826. 单链表

https://www.acwing.com/problem/content/description/828/

点击查看代码
#include <iostream>
using namespace std;

const int N = 100010;
int e[N],ne[N],head = -1,idx; 

//向链表头插入一个数x  O(1)
void add_to_head(int x){ //最后一个元素指向-1
    e[idx] = x;
    ne[idx] = head;
    head = idx;
    idx++;
}
//在第k个插入的数后面插入一个数x  O(1),要用链表那就是O(n)
void add(int k,int x){
    k--; //idx是从0开始的
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx;
    idx++;
}
// 删除第 k 个插入的数后面的数(当 k 为 0 时,表示删除头结点)O(1)
void del(int k){
    if(k == 0) head = ne[head];
    else{
        ne[k-1] = ne[ne[k-1]];
    }
    
}

int main(){
    int M; cin >> M; //M次操作
    while(M--){
        char op; cin >> op;
        int k,x;
        if(op == 'H'){  //H x,表示向链表头插入一个数 x
            cin >> x;
            add_to_head(x);
            
        }else if(op == 'I'){ // I k x,表示在第 k 个插入的数后面插入一个数 x,此操作中 k 均大于 0
            cin >> k >> x;
            add(k,x);
            
        }else if(op == 'D'){ // 表示删除第 k 个插入的数后面的数(当 k 为 0 时,表示删除头结点)
            cin >> k;
            del(k);
        }
    }
    for(int i = head; i != -1; i = ne[i]){
        cout << e[i] << " ";
    }
    return 0;
}

2. 双链表

AcWing 827. 双链表

https://www.acwing.com/problem/content/829/

点击查看代码
#include <iostream>
using namespace std;
const int N = 100010;
int e[N],l[N],r[N],head = - 1,idx;

//在节点a(下标idx)的右边插入一个数
void insert(int a,int x){
    e[idx] = x;
    l[idx] = a, r[idx] = r[a];
    l[r[a]] = idx,r[a] = idx;
    idx++;
}
//删除节点a
void remove(int a){
    l[r[a]] = l[a];
    r[l[a]] = r[a];
}

int main(){
    int M; cin >> M; //M次操作
    
    // 0是左端点,1是右端点
    l[0] = -1, r[1] = -1;
    r[0] = 1, l[1] = 0;
    idx = 2;

    while(M--){
        string op; cin >> op;
        int k,x;
        if(op == "L"){ //在链表的最左端插入数 x
            cin >> x;
            insert(0,x);
        }else if(op == "R"){ // 在链表的最右端插入数 x
            cin >> x;
            insert(l[1],x);
        }else if(op == "D"){ // 表示将第 k 个插入的数删除
            cin >> k;
            remove(k+1);
        }else if(op == "IL"){ // IL k x,表示在第 k 个插入的数左侧插入一个数
            cin >> k >> x;
            insert(l[k+1],x);
            
        }else if(op == "IR"){ // 在第 k 个插入的数右侧插入一个数
            cin >> k >> x;
            insert(k+1,x);
        }
    }
    for(int i = r[0]; i != 1; i = r[i]){
        cout << e[i] << " ";
    }
    return 0;
}


3.栈

AcWing 828. 模拟栈

https://www.acwing.com/problem/content/830/

点击查看代码
#include <iostream>
using namespace std;
const int N = 100010;
int stk[N],idx = -1;

int main(){
    int m; cin >> m;
    while(m--){
        string op;
        cin >> op;
        int x;
        if(op == "push"){
            cin >> x;
            stk[++idx] = x;
        }
        if(op == "pop"){
            idx--;
        }
        if(op == "query"){ // 查询栈顶元素
            cout << stk[idx] << endl;
        }
        if(op == "empty"){
            if(idx == -1) cout << "YES" << endl;
            else cout << "NO" << endl;
        }
    }
    return 0;
}

AcWing 3302. 表达式求值☆

https://www.acwing.com/problem/content/3305/

点击查看代码

4.队列

AcWing 829. 模拟队列

https://www.acwing.com/problem/content/831/

点击查看代码
#include <iostream>
using namespace std;
const int N = 100010;
int q[N],hh,tt = -1;
int main(){
    int M; cin >> M; while(M--){
        string op; cin >> op;
        int x;
        if(op == "push"){ //从队尾插入一个数
            cin >> x;
            q[++tt] = x;        
        }
        if(op == "pop"){ //从队头弹出一个数
            hh++;            
        }
        if(op == "empty"){ 
            if(tt >= hh){
                cout << "NO" << endl;
            }else{
                cout << "YES" << endl;
            }    
        }
        if(op == "query"){ //查询队头元素
            cout << q[hh] << endl;    
        }
    }
    return 0;
}

5.单调栈

AcWing 830. 单调栈

https://www.acwing.com/problem/content/832/

点击查看代码
#include <iostream>
using namespace std;
const int N = 100010;
int stk[N],tt = -1;
int n;
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        int x; cin >> x;
        while(tt >= 0 && stk[tt] >= x) tt--;
        if(tt >= 0) cout << stk[tt] << " ";
        else cout << -1 << " ";
        stk[++tt] = x;
    }
    return 0;
}

6. 单调队列

AcWing 154. 滑动窗口

https://www.acwing.com/problem/content/156/

点击查看代码
#include <iostream>
using namespace std;
const int N = 1000010;
int a[N];
int q[N],hh, tt = -1;
int main(){
    int n,k; cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++){
        if(tt >= 0 &&  q[hh] < i-k+1) hh++; //判断窗口头是否包含在内
        while(tt >= hh && a[q[tt]] > a[i]) tt--; //单调递增队列
        q[++tt] = i;
        if(i-k >= 0) cout << a[q[hh]] << " "; 
    }
    cout << endl;
    //同样的道理
    hh = 0, tt = -1;
    for(int i = 1; i <= n; i++){
       if(tt >= 0 && q[hh] < i-k+1) hh++;
       while(tt >= hh && a[q[tt]] < a[i]) tt--;
       q[++tt] = i;
       if(i-k >= 0) cout << a[q[hh]] << " ";
    }
    
    return 0;
}

7.KMP ⭐️⭐️⭐️⭐️⭐️

AcWing 831. KMP字符串

https://www.acwing.com/problem/content/833/

点击查看代码

8.trie字典树

AcWing 835. Trie字符串统计

https://www.acwing.com/problem/content/description/837/

点击查看代码
#include <iostream>
using namespace std;

const int N = 100010;
int son[N][26],cnt[N],idx;

void insert(string s){
	int p = 0; //从根节点开始向下插入
	for(int i = 0; i < s.length(); i++){
		int t = s[i] - 'a';
		if(son[p][t] == 0) son[p][t] = ++idx; //没有这个节点就创建这个节点,该节点的值为++idx,也是孩子节点的下标
		p = son[p][t];	
	}
	cnt[p]++;
}
int query(string s){
	int p = 0;
	for(int i = 0; i < s.length(); i++){
		int t = s[i] - 'a';
		if(son[p][t] == 0) return 0;
		p = son[p][t];
	}
	return cnt[p];
}


int main(){
	int N; cin >> N; while(N--){
		string op; cin >> op;
		string x;
		if(op == "I"){
			cin >> x;
			insert(x);
		}
		if(op == "Q"){
			cin >> x;
			cout << query(x) << endl;
		}
	}

	return 0;
}

9.并查集

AcWing 836. 合并集合

https://www.acwing.com/problem/content/838/

点击查看代码
#include <iostream>
using namespace std;
const int N = 100010;
int fa[N];
int n,m;

int get(int x){
	if(x == fa[x]) return x;
	return fa[x] = get(fa[x]);
}

void merge(int a,int b){
	fa[get(a)] = get(b);
}



int main(){
	cin >> n >> m;
	for(int i = 1; i <= n; i++) fa[i] = i;
	while(m--){
		char op; cin >> op;
		int a,b;
		if(op == 'M'){
			cin >> a >> b;
			merge(a,b);

		}else{
			cin >> a >> b;
			if(get(a) == get(b)) cout << "Yes" << endl;
			else cout << "No" << endl;
		}
	}
	return 0;

}

10堆

AcWing 838. 堆排序

https://www.acwing.com/activity/content/problem/content/888/

点击查看代码
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 100010;
int h[N],si; // 堆的一维数组,si表示h的最后一个下标size
int m,n;

void down(int u){
    int t = u; // t存放当前节点、左孩子、右孩子三者的最小节点下标
    if(u * 2 <= si && h[u*2] < h[t]) t = u*2; // 左孩子比u节点小
    if(u * 2 + 1 <= si && h[u*2 + 1] < h[t]) t = u*2 + 1;
    if(t != u){
        swap(h[t],h[u]);
        down(t);
    }
}

int main(){
     ios::sync_with_stdio(false); cin.tie(0);
    cin >> n >> m; // n个整数,输出前m个数
    for(int i = 1; i <= n; i++) cin >> h[i];
    si = n;
    for(int i = n/2; i >= 1; i--) down(i); //建堆
    while(m--){
        cout << h[1] << " ";
        h[1] = h[si]; // 最后一节点覆盖一个节点,down(1);
        si--;
        down(1);
    }
    
    return 0;
}

11.哈希表(图的表示方法)

AcWing 840. 模拟散列表

https://www.acwing.com/problem/content/description/842/

点击查看代码
#include <iostream>
#include <cstring>
using namespace std;

const int N = 100010;
int h[N],e[N],ne[N],idx;

void insert(int x){
	int k = (x%N + N) % N;
	e[idx] = x;
	ne[idx] = h[k];
	h[k] = idx++;
}

bool find(int x){
	int k = (x % N + N) % N;
	for(int i = h[k]; i != -1; i = ne[i]){
		if(e[i] == x) return true;
	}
	return false;
}

int main(){
	int n; cin >> n;
	memset(h,-1,sizeof(h));
	while(n--){
		char op; cin >> op;
		int x;
		if(op == 'I'){
			cin >> x;
			insert(x);
		}else{
			cin >> x;
			if(find(x)) cout << "Yes" << endl;
			else cout << "No" << endl;
		}
	}
}

字符串哈希⭐️⭐️⭐️

posted @   超级氯化钾  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示