基础算法与数据结构模板

1.排序算法

快速排序

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int Arr[N]; 
void qsort(int l,int r){
	int t = Arr[l];
	int i = l;
	int j = r;
	while(i<j){
		while(Arr[j]>=t&&i<j) j--;
		while(Arr[i]<=t&&i<j) i++;
		swap(Arr[i],Arr[j]);
	}
	swap(Arr[l],Arr[i]);
	if(i<r) qsort(i+1,r);
	if(j>l) qsort(l,j-1);
}
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++) cin>>Arr[i];
	qsort(0,n-1);
	for(int i=0;i<n;i++) cout<<Arr[i]<<" ";
	return 0;
}

归并排序

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int Arr[N],temp[N];
void merge_sort(int l,int r){
	if(l>=r) return ;
	int mid = l + r >> 1;
	int i = l;
	int j = mid + 1;
	int k = 0;
	merge_sort(l,mid);
	merge_sort(mid+1,r);
	while(i<=mid&&j<=r){
		if(Arr[i]<=Arr[j]) temp[k++] = Arr[i++];
		else temp[k++] = Arr[j++];
	}
	while(i<=mid) temp[k++] = Arr[i++];
	while(j<=r) temp[k++] = Arr[j++];
	for(i=0;i<k;i++) Arr[l+i] = temp[i];
}
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++) cin>>Arr[i];
	merge_sort(0,n-1);
	for(int i=0;i<n;i++) cout<<Arr[i]<<" ";
	return 0;
}

堆排序

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int heap[N];
int n,k;
void down_adjust(int pos){
	int i = pos;
	int j = i * 2;
	while(j<=n){
		if(j+1<=n&&heap[j]>heap[j+1]) j = j + 1;
		if(heap[i]>heap[j]) {
			swap(heap[i],heap[j]);
			i = j;
			j = i * 2;
		}
		else break;
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>heap[i];
	for(int i=n/2;i>=1;i--) down_adjust(i);
	while(n){
		cout<<heap[1]<<" ";
		heap[1] = heap[n--];
		down_adjust(1);
	}
	return 0;
}

2.高精度

加法高精度

#include<bits/stdc++.h>
using namespace std;
void add(vector<int>&A,vector<int>&B){
	vector<int> C;
	int t = 0;
	for(int i=0;i<A.size()||i<B.size();i++){
		if(i<A.size()) t+=A[i];
		if(i<B.size()) t+=B[i];
		C.push_back(t%10);
		t/=10;
	}
	if(t) C.push_back(1);
	for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
int main(){
	string a,b;
	vector<int> A,B;
	cin>>a>>b;
	for(int i=a.length()-1;i>=0;i--) A.push_back(a[i]-'0');
	for(int i=b.length()-1;i>=0;i--) B.push_back(b[i]-'0');
	add(A,B);
	return 0;
}

减法高精度

#include<bits/stdc++.h>
using namespace std;
bool cmp(string a,string b){
	if(a.length()<b.length()) return false;
	for(int i=0;i<a.length();i++){
		if(a[i]<b[i]) return false;
	} 
	return true;
}
void minu(vector<int>&A,vector<int>&B){
	int t = 0;
	vector<int> C;
	for(int i=0;i<A.size();i++){
		t = A[i] - t;
		if(i<B.size()) t -= B[i];
		C.push_back((t+10)%10);
		if(t<0) t = 1;
		else t = 0;
	}
	while(C.size()>1&&C.back()==0) C.pop_back();
	for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
int main(){
	string a,b;
	vector<int> A,B;
	cin>>a>>b;
	if(cmp(a,b)==false) {
		swap(a,b);
		cout<<"-";
	}
	for(int i=a.length()-1;i>=0;i--) A.push_back(a[i]-'0');
	for(int i=b.length()-1;i>=0;i--) B.push_back(b[i]-'0');
	minu(A,B);
	return 0;
}

乘法高精度

#include<bits/stdc++.h>
using namespace std;
void multi(vector<int>&A,int b){
	vector<int> C;
	int t = 0;
	for(int i=0;i<A.size()||t;i++){
		if(i<A.size()) t+=A[i]*b;
		C.push_back(t%10);
		t/=10;
	}
	while(C.size()>1&&C.back()==0) C.pop_back();
	for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
int main(){
	string a;
	int b;
	vector<int> A;
	cin>>a>>b;
	for(int i=a.length()-1;i>=0;i--) A.push_back(a[i]-'0');
	multi(A,b);
	return 0;
}

除法高精度

#include<bits/stdc++.h>
using namespace std;
void div(vector<int>&A,int b,int &r){
	vector<int> C;
	r = 0;
	for(int i=A.size()-1;i>=0;i--){
		r = r * 10 + A[i];
		C.push_back(r/b);
		r%=b;
	}
	reverse(C.begin(),C.end());
	while(C.size()>1&&C.back()==0) C.pop_back();
	for(int i=C.size()-1;i>=0;i--) cout<<C[i];
	cout<<endl;
	cout<<r;
}
int main(){
	string a;
	int b,r;
	vector<int> A;
	cin>>a>>b;
	for(int i=a.length()-1;i>=0;i--) A.push_back(a[i]-'0');
	div(A,b,r);
	return 0;
}

3.二分查找

lower_bound && upper_bound

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int Arr[N],m,n,temp;
int lower_bound(int data){
    int left = 0;
    int right = n-1;
    int mid;
    while(left<right){
        mid = (left+right) / 2;
        if(Arr[mid]>=data) right = mid;
        else left = mid + 1;
    }
    if(Arr[left]!=data) return -1;
    else return left;
}
int upper_bound(int data){
    int left = 0;
    int right = n-1;
    int mid;
    while(left<right){
        mid = (left+right+1)/2;
        if(Arr[mid]<=data) left = mid;
        else right = mid - 1;
    }
    if(left+1>n-1) return -1;
    else return left + 1;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>Arr[i];
    while(m--){
        cin>>temp;
        if(lower_bound(temp)==-1) cout<<"-1 -1"<<endl;
        else cout<<lower_bound(temp)<<" "<<upper_bound(temp)<<endl;
    }
    return 0;
}

4.树

已知前序和中序还原树

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n,in[N],pre[N];
struct node{
	int data;
	node *lchild;
	node *rchild;
};
node *build_tree(int prel,int prer,int inl,int inr){
	if(prel>prer) return NULL;
	node *root = new node;
	root->data = pre[prel];
	int k,num;
	for(k=inl;k<=inr;k++) if(in[k]==pre[prel]) break;
	num = k - inl;
	root->lchild = build_tree(prel+1,prel+num,inl,k-1);
	root->rchild = build_tree(prel+num+1,prer,k+1,inr);
	return root;
}
int main(){
	cin>>n;
	for(int i=0;i<n;i++) cin>>pre[i];
	for(int i=0;i<n;i++) cin>>in[i];
	node *root = build_tree(0,n-1,0,n-1);
	return 0;
}

已知后序和中序还原树

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n,in[N],post[N];
struct node{
	int data;
	node *lchild;
	node *rchild;
}; 
node *build_tree(int inl,int inr,int posl,int posr){
	if(posl>posr) return NULL;
	node *root = new node;
	root->data = post[posr];
	int k,num;
	for(k=inl;k<=inr;k++){
		if(in[k]==post[posr]) break;
	}
	num = k - inl;
	root->lchild = build_tree(inl,k-1,posl,posl+num-1);
	root->rchild = build_tree(k+1,inr,posl+num,posr-1);
}
void pre(node *root){
	if(root==NULL) return ;
	cout<<root->data<<" ";
	pre(root->lchild);
	pre(root->rchild);
}
int main(){
	cin>>n;
	for(int i=0;i<n;i++) cin>>in[i];
	for(int i=0;i<n;i++) cin>>post[i];
	node *root = build_tree(0,n-1,0,n-1);
	pre(root);
	return 0;
}

二叉搜索树(BST)

#include<bits/stdc++.h>
using namespace std;
struct node{
	int data;
	node *lchild;
	node *rchild;
};
void build_BST(node *&root,int v){
	if(root==NULL){
		root = new node;
		root->data = v;
		root->lchild = root->rchild = NULL;
		return ;
	}
	else if(root->data<v) build_BST(root->rchild,v);
	else build_BST(root->lchild,v);
}
int main(){
	node *root = NULL;
	int n,temp;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>temp;
		build_BST(root,temp);
	}
	return 0;
}

并查集(路径压缩)

#include<bits/stdc++.h>
using namespace std;
int father[10001];
void init(int n){
	for(int i=0;i<n;i++) father[i] = i;
}
int find_father(int x){
	if(x==father[x]) return x;
	return father[x] = find_father(father[x]);
}
void Union(int u,int v){
	int fu = find_father(u);
	int fv = find_father(v);
	if(fu!=fv) father[fu] = fv;
}
int main(){
	int n,m,u,v,w;
	cin>>n>>m;
	init(n);
	for(int i=0;i<n;i++){
		cin>>u>>v;
		Union(u,v);
	}
	while(m--){
		cin>>u>>v;
		if(find_father(u)==find_father(v)) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0; 
}

二叉堆(down_adjust)

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int heap[N],n;
void down_adjust(int low,int high){
	int i = low;
	int j = i * 2;
	while(j<=high){
		if(j+1<=high&&heap[j+1]<heap[j]) j = j + 1;
		if(heap[i]>heap[j]){
			swap(heap[i],heap[j]);
			i = j;
			j = i * 2;
		}
		else break;
	}
}
void create_heap(){
	for(int i=n/2;i>=1;i--) down_adjust(i,n);
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>heap[i];
	create_heap();
	for(int i=1;i<=n;i++) cout<<heap[i]<<" ";
	return 0;
}

二叉堆(up_adjust)

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int heap[N],t,n,idx;
void up_adjust(int high){
	int i = high;
	int j = i / 2;
	while(j>=1){
		if(heap[j]>heap[i]){
			swap(heap[i],heap[j]);
			i = j;
			j = i / 2;
		}
		else break;
	}
}
void insert(int x){
	heap[++idx] = x;
	up_adjust(idx);
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>t;
		insert(t);
	}
	for(int i=1;i<=n;i++) cout<<heap[i]<<" ";
	return 0;
}

5.图

Dijkstra求单源最短路(堆优化+链式前向星)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000001;
int vis[maxn],dis[maxn],first[maxn],pre[maxn];
int cnt;
struct node{
	int to;
	int weight;
	bool operator < (const node &temp) const{
		return weight > temp.weight;
	}
};
struct Graph{
	int to;
	int weight;
	int next;
}G[maxn];
void add(int u,int v,int w){
	G[++cnt].to = v;
	G[cnt].weight = w;
	G[cnt].next = first[u];
	first[u] = cnt;
}
priority_queue<node> q;
void Dijkstra(int s){
	fill(dis,dis+maxn,INT_MAX);
	dis[s] = 0; 
	pre[s] = s;
	q.push((node){s,0});
	while(!q.empty()){
		node temp = q.top();
		q.pop();
		if(vis[temp.to]) continue;
		vis[temp.to] = 1;
		for(int i=first[temp.to];i!=-1;i=G[i].next){
			int end = G[i].to;
			if(dis[end] > dis[temp.to] + G[i].weight){
			    dis[end] = dis[temp.to] + G[i].weight;
			    pre[end]  = temp.to;
			    if(!vis[end]) q.push((node){end,dis[end]});
		    } 
		} 
	}
}
void find_path(int start,int end){
	if(start==end){
		cout<<start;
		return ;
	}
	else find_path(start,pre[end]);
	cout<<"-->"<<end;
}
int main(){
	fill(first,first+maxn,-1);
	int m,n,u,v,w,start,end;
	cin>>n>>m;
	for(int i=0;i<m/2;i++){
		cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,w);
	}
	cin>>start>>end;
	Dijkstra(start);
	find_path(start,end); 
	cout<<endl;
	cout<<dis[end];
	return 0;
}

SPFA求单源最短路(图中含负环)(链式前向星+堆优化)

#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
int dis[N],vis[N],first[N],de[N],cnt,m,n,u,v,w;
struct Graphy{
	int v;
	int w;
	int next;
}G[N];
void add(int u,int v,int w){
	G[++cnt].v = v;
	G[cnt].w = w;
	G[cnt].next = first[u];
	first[u] = cnt;
}
struct node{
	int v;
	int w;
	bool operator < (const node&temp) const{
		return temp.w < w;
	}
};
bool SPFA(int s){
	de[s]++;
	dis[s] = 0;
	vis[s] = 1;
	priority_queue<node> q;
	q.push(node{s,0});
	while(!q.empty()){
		node top = q.top();
		q.pop();
		vis[top.v] = 0;
		for(int i=first[top.v];i;i=G[i].next){
			int e = G[i].v;
			if(dis[e]>dis[top.v]+G[i].w){
				dis[e] = dis[top.v] + G[i].w;
				if(!vis[e]) {
					q.push(node{e,dis[e]});
					de[e]++;
					vis[e] = 1;
					if(de[e]>=n) return true;
				}
			}
		} 
	}
	return false;
}
int main(){
	fill(dis,dis+N,INT_MAX); 
	cin>>n>>m;
	for(int i=0;i<m;i++){
		cin>>u>>v>>w;
		add(u,v,w);
	}
	for(int i=1;i<=n;i++){
		if(dis[i]!=INT_MAX) continue;
		if(SPFA(i)==true) {
			cout<<"Yes";
			return 0;
		}                                                                                                   
	}
	cout<<"No";
	return 0;
}

Floyd求多源最短路径

#include<bits/stdc++.h>
using namespace std;
const int maxn = 101;
int dis[maxn][maxn],path[maxn][maxn];
void Floyd(int n){
	for(int k=0;k<n;k++){
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				if(dis[i][k]!=INT_MAX&&dis[k][j]!=INT_MAX&&dis[i][j]>dis[i][k]+dis[k][j]) {
					dis[i][j] = dis[i][k]+dis[k][j];
					path[i][j] = path[i][k];
				}
			}
		}
	}
}
void find_path(int x,int y){
	int v = path[x][y];
	cout<<x;
	while(v!=y){
		cout<<"->"<<v;
		v = path[v][y];
	}
	cout<<"->"<<y;
}
int main(){
	int n,m,u,v,w,start,end;
	cin>>n>>m>>start>>end;
	fill(dis[0],dis[0]+maxn*maxn,INT_MAX);
	for(int i=0;i<n;i++) dis[i][i] = 0;
	for(int i=0;i<m;i++){
		cin>>u>>v>>w;
		dis[u][v] = w;
		path[u][v] = v;
	}
	Floyd(n);
	if(start==end) cout<<start<<"->"<<end<<":0";
	else find_path(start,end);
	return 0;
}

求最小生成树—Kruskal算法

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000001;
int father[maxn];
struct Edge{
	int u;
	int v;
	int dis;
}ed[maxn];
bool cmp(Edge a,Edge b){
	return a.dis < b.dis;
}
void init(int n){
	for(int i=1;i<=n;i++) father[i] = i;
}
int find_father(int x){
	if(x==father[x]) return x;
	int temp = find_father(father[x]);
	return temp;
}
int Kruskal(int n,int m){
	int ans = 0;
	int num_Edge = 0;
	for(int i=0;i<m;i++){
		int fu = find_father(ed[i].u);
		int fv = find_father(ed[i].v);
		if(fu!=fv){
			father[fu] = fv;
			ans+=ed[i].dis;
			num_Edge++;
			if(num_Edge==n-1) break;
		}
	}
	if(num_Edge!=n-1) return -1;
	else return ans;
}
int main(){
	int n,m;
	cin>>n>>m;
	init(n);
	for(int i=0;i<m;i++) cin>>ed[i].u>>ed[i].v>>ed[i].dis;
	sort(ed,ed+m,cmp);
	cout<<Kruskal(n,m);
	return 0;
}

求最小生成树—Prime算法

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000001;
int dis[maxn],vis[maxn],first[maxn],cnt;
struct Graph{
	int to;
	int weight;
	int next;
}G[maxn];
void add(int u,int v,int w){
	G[++cnt].to = v;
	G[cnt].weight = w;
	G[cnt].next = first[u];
	first[u] = cnt;
}
int prime(int n){
	fill(dis,dis+maxn,INT_MAX);
	dis[1] = 0;
	int minn,u,ans=0;
	for(int i=1;i<=n;i++){
		minn = INT_MAX;
		u = -1; 
		for(int j=1;j<=n;j++){
			if(vis[j]==0&&dis[j]<minn){
				minn = dis[j];
				u = j;
			}
		}
		if(u==-1) return -1;
		vis[u] = 1;
		ans+=dis[u];
		for(int k=first[u];k;k=G[k].next){
			int end = G[k].to;
			if(vis[end]==0&&dis[end]>G[k].weight) dis[end] = G[k].weight;
		}
	} 
	return ans;
}
int main(){
	int n,m,u,v,w;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		cin>>u>>v>>w;	
		add(u,v,w);
		add(v,u,w);
	}
	int ans = prime(n);
	if(ans==-1) cout<<"orz";
	else cout<<ans;
	return 0;
}

拓扑排序

#include<bits/stdc++.h>
using namespace std;
const int maxn = 10001;
vector<int> vi[maxn];
priority_queue<int,vector<int>,greater<int> > q;
int dis[maxn];
int main(){
	int n,m,u,v,num=0;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		cin>>u>>v;
		vi[u].push_back(v);
		dis[v]++;
	}
	for(int i=1;i<=n;i++){
		if(dis[i]==0) q.push(i);
	}
	while(!q.empty()){
		int top = q.top();
		cout<<top<<" ";
		q.pop();
		for(int i=0;i<vi[top].size();i++){
			int end = vi[top][i];
			dis[end]--;
			if(dis[end]==0) q.push(end);
		}
		vi[top].clear();
		num++;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值