各种算法备忘

目录

1.背包问题_01背包

2.DIjkstra算法

3.KMP算法

4.并查集算法(查找图中是否存在环)

5.C++中实现类似python中字典的功能

6.DFS:

7.BFS:

8.线段树:



1.背包问题_01背包

https://blog.csdn.net/insistgogo/article/details/8579597

2.DIjkstra算法

https://www.cnblogs.com/jason2003/p/7222182.html

单纯求起始点各点最短路径长度代码:

#include<iostream>
#include<memory.h>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int map[100][100];
bool vis[100];
int dis[100];
int n, m;
/*
测试数据
10 12
1 4 1
1 5 1
1 6 1
4 8 1
4 3 1
3 5 1
5 7 1
3 7 1
6 2 1
7 2 1
7 10 1
2 9 1
*/
void Dijkstra(int u)
{
	memset(dis, INF, sizeof dis);
	int start = u;
	vis[start] = 1;
	for (int i = 1; i <= n; ++i)
		dis[i] = map[start][i];
    //因为第一个结点已经标记 所以应该循环n-1次
	for (int i = 1; i < n; ++i)
	{
		int minn = INF;
		for(int j=1;j<=n;++j)
			if (vis[j] == 0 && minn > dis[j])
			{ 
                //这里不是dis[start]+map[start][j]
                //而应该是 minn>dis[j] 
                //因为我们寻找的应该是到源点最近的点                              
				minn = dis[j];               
				start = j;
			}
		vis[start] = 1;
		for (int i = 1; i <= n; ++i)
		{
			dis[i] = min(dis[i], dis[start]+map[start][i]);
            //这里不是map[start][i]
            //而是dis[start]+map[start][i]
            //防止出现start结点直接到i结点的距离比绕了几个节点到i距离小的情况 
		}                                                   
	}                                                     
}
int main()
{
	int x, y, z;
	cin >> n >> m;
	memset(map, INF, sizeof map);//将所有路线初始化为∞ 表示无法连通
	for (int i = 0; i < m; ++i)
	{
		cin >> x >> y >> z;
		map[x][y] = map[y][x] = z;//将连通道路以及耗费代价记录
	}
	for (int i = 1; i <= n; ++i)//每一个结点到自身的耗费代价为0
		map[i][i] = 0;
	Dijkstra(1);
	for (int i = 1; i <= n; ++i)
	{
		if (dis[i] != INF)
			cout << "1->"<<i << ' ' << dis[i] << endl;
	}
}

求起始节点到各个节点最短路径以及长度:

#include<iostream>
#include<memory.h>
#include<string>
#include<algorithm>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
int map[501][501];
bool vis[501];
int dis[501];
int num[501];
int n, m,s,d;
string path[501];
string init_path = "V1";
/*
测试数据
10 12
1 4 1
1 5 1
1 6 1
4 8 1
4 3 1
3 5 1
5 7 1
3 7 1
6 2 1
7 2 1
7 10 1
2 9 1
*/
void Dijkstra(int u)
{
	mem(dis, INF);
	int start = u;
	vis[start] = 1;
	for (int i = 1; i <= n; ++i)
		dis[i] = map[start][i];
	for (int i = 2; i <= n; ++i)
		path[i] = init_path + "V" + to_string(i);
	for (int i = 1; i <= n; ++i)
	{
		int minn = INF;
		for (int j = 1; j <= n; ++j)
			if (vis[j] == 0 && minn > dis[j])
			{
				minn = dis[j];
				start = j;
			}
		vis[start] = 1;
		for (int i = 2; i <= n; ++i)
		{
			if (map[start][i] != INF && vis[i] == 0)
			{//如果新加入的节点ii到i节点有路径 而且i不在已选取的节点中
				if (dis[i] != INF)
				{//v1到i节点有路径  ???
					if (dis[i] > dis[start] + map[start][i])
					{//而且 经过ii节点的路径更短
						dis[i] = dis[start] + map[start][i];
						path[i] = path[start] + "V" + to_string(i);
					}
				}
				else
				{//v1到i没有路径
					dis[i] = dis[start] + map[start][i];
					path[i] = path[start] + "V" + to_string(i);
				}
			}
		}
	}
}
int main()
{
	int x, y, z;
	cin >> n >> m/*>>s>>d*/;
	/*for (int i = 1; i <= n; ++i)
		cin >> num[i];*/
	mem(map, INF);
	for (int i = 0; i < m; ++i)
	{
		cin >> x >> y >> z;
		map[x][y] = map[y][x] = z;
	}
	for (int i = 1; i <= n; ++i)
		map[i][i] = 0;
	Dijkstra(1);
	for (int i = 2; i <= n; ++i)
		if (dis[i] != INF)
			cout << path[i] <<"  "<<dis[i]<< endl;
}

代码效果:

3.KMP算法

#include<iostream>
#include<cstring>
using namespace std;
void prefix_table(char pattern[], int prefix[], int len)
{
	prefix[0] = 0;
	int i = 0, j = 1;
	while (j < len)
	{
		if (pattern[i] == pattern[j])
			prefix[j++] = ++i;
		else
		{
			if (i > 0)
				i = prefix[i - 1];
			else
				prefix[j++] = 0;
		}
	}
}
void move_prefix_table(int prefix[], int len)
{
	for (int i = len - 1; i > 0; --i)
		prefix[i] = prefix[i - 1];
	prefix[0] = -1;
}
void KMP_search(char text[], char pattern[])
{
	int n = strlen(pattern);
	int m = strlen(text);
	int i = 0, j = 0;
	int *prefix = new int[n];
	prefix_table(pattern, prefix, n);
	move_prefix_table(prefix, n);
	//	 text[i] ,     strlen(text) = n
	//pattern[j] ,  strlen(pattern) = m
	while (i < m)
	{
		if (text[i] == pattern[j])
		{
			if (j == n - 1)
			{
				printf("Found at %d\n", i-j);
				j = prefix[j];
			}
			i++, j++;
		}
		else
		{
			j = prefix[j];
			if (j == -1)
				i++, j++;
		}
	}
}
int main()
{
	char text[50], pattern[50];
	cin >> text >> pattern;
	KMP_search(text, pattern);
}

测试结果:

4.并查集算法(查找图中是否存在环)

#include<iostream>
#include<cstring>
using namespace std;
#define VERTICES 6
void initialise(int parent[])
{
	for (int i = 0; i < VERTICES; ++i)
		parent[i] = i;
}
int find_root(int x, int parent[])
{
	int x_root = x;
	while (parent[x_root] !=x_root)
		x_root = parent[x_root];
	return x_root;
}
int union_vertices(int x,int y,int parent[])
{
	int x_root = find_root(x, parent);
	int y_root = find_root(y, parent);
	if (x_root == y_root)
	{
		printf("%d and %d has root %d\n", x,y,x_root);
		return 0;
	}
	else
	{
		parent[x_root] = y_root;
		return 1;
	}
}
int main()
{
	int parent[VERTICES] = { 0 };
	int edges[5][2]=
	{
		{1,3},{1,2},{2,5},{3,4},{4,5}
	};

	initialise(parent);
	for (int i = 0; i < 5; ++i)
	{
		if (union_vertices(edges[i][0], edges[i][1], parent) == 0)
		{
			printf("Cycle Found\n");
			break;
		}
	}
	printf("No Cycle Found\n");
	return 0;
}

更加高效的并查集查找:

string& find(string &t) {
	if (dp.find(t) == dp.end())
		return t;
	string st = dp[t];
	if (st == t) return t;
	else return dp[t] = find(st);
}
void merge(string &a, string &b)
{
	string aa = find(a);
	string bb = find(b);
	if (aa != bb)
		dp[aa] = bb;
}

 

我也不知道为什么这样就高效了。。。有一道题这样做不会超时,我换个方式压缩路径不调用递归反而算的比这个吊用递归还慢,我毫无头绪。

5.C++中实现类似python中字典的功能

#include<iostream>
#include<vector>
#include<map>
using namespace std;
map<char, map<char,int>>dp;
int main()
{
	char A, B;
	int dist;
	while (cin >> A >> B >> dist)
	{
		dp[A][B] = dist;
	}
	map<char, map<char, int>>::iterator it = dp.begin();
	while (it != dp.end())
	{
		map<char, int>::iterator ite=it->second.begin();
		while (ite != it->second.end())
		{
			cout << it->first << " -> " << ite->first << "  " << ite->second << endl;
			ite++;
		}
		it++;
	}
}

代码效果:

以这个图为例:

非递归式的深度搜索与广度搜索(二者极其相似):

6.DFS:

int DFS(int x,int y)
{
    stack<Type>sta;
    sta.push(Type(x,y));
    while(!sta.empty())
    {
        Type t=sta.top();
        sta.pop();
       for(int i=0;i<4;++i)
       {
            int xx=t.x+dir[i][0];
            int yy=t.y+dir[i][1];
            if(/*满足某种条件*/)
                {
                    sta.push(Type(xx,yy));
                    //添加你要进行的额外操作
                }
        }
    }
    return 0;
}

7.BFS:

int BFS(int x,int y)
{
    queue<Type>que;//修改此处
    que.push(Type(x,y));
    while(!que.empty())
    {
        Type t=que.front();//sta.top()改为que.front()
        que.pop();
       for(int i=0;i<4;++i)
       {
            int xx=t.x+dir[i][0];
            int yy=t.y+dir[i][1];
            if(/*满足某种条件*/)
                {
                    que.push(Type(xx,yy));
                    //添加你要进行的额外操作
                }
        }
    }
    return 0;
}

8.线段树:

#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
#include<queue>
#include<memory.h>
#define INF 0x3f3f3f3f
using namespace std;
void build_tree(int arr[], int tree[], int node, int start, int end)
{
	if (start == end)
		tree[node] = arr[start];
	else
	{
		int mid = (start + end) / 2;
		int left_node  = 2 * node + 1;
		int right_node = 2 * node + 2;
		build_tree(arr, tree, left_node, start, mid);
		build_tree(arr, tree, right_node, mid + 1, end);
		tree[node] = tree[left_node] + tree[right_node];
	}
}
void update(int arr[], int tree[], int node, int start, int end, int idx, int val)
{
	if (start == end)
	{
		arr[idx] = val;
		tree[node] = val;
	}
	else
	{
		int mid = (start + end) / 2;
		int left_node  = 2 * node + 1;
		int right_node = 2 * node + 2;
		if(idx<=mid)
		update(arr, tree, left_node, start, mid, idx, val);
		else
		update(arr, tree, right_node,mid+1, end, idx, val);
		tree[node] = tree[left_node] + tree[right_node];
	}
}
int query_tree(int arr[], int tree[], int node, int start, int end, int L, int R)
{
	if (L > end || R < start)
		return 0;
	if (L<=start&&end<=R)
		return tree[node];
	int mid = (start + end) / 2;
	int left_node  = 2 * node + 1;
	int right_node = 2 * node + 2;
	int sum_left  = query_tree(arr, tree, left_node, start, mid, L, R);
	int sum_right = query_tree(arr, tree, right_node, mid + 1, end, L, R);
	return sum_left + sum_right;
}
int main()
{
	int arr[] = { 1,3,5,7,9,11 };
	int size  = 6;
	int tree[100] = { 0 };
	build_tree(arr, tree, 0, 0, size - 1);
	update(arr, tree, 0, 0, size - 1,4,6);
	for (int i = 0; i < 15; ++i)
	printf("tree[%d] = %d\n",i, tree[i]);
	cout << query_tree(arr, tree, 0, 0, size - 1, 2, 5);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值