首页 > 编程语言 >大二上 数据结构与算法 课堂模板算法 20241225

大二上 数据结构与算法 课堂模板算法 20241225

时间:2024-12-25 21:47:06浏览次数:7  
标签:dist parent int 算法 vector ma 20241225 大二

数据结构与算法

1-基本数据结构

2-分治策略

3-堆

4-排序

5-选择 & 树

6-搜索树 & 散列表 & 并查集

6.1-搜索树

6.2-散列表

6.3-并查集

int find(int x) 
{
    if(pre[x] == x) return x;     
    return pre[x] = find(pre[x]);
}

void join(int x,int y)
{
    int fx=find(x), fy=find(y);
    if(fx != fy)
        pre[fx]=fy;
}

7-图

7.1-BFS(邻接表)

vector<vector<int>> graph; // 图的邻接表表示
vector<int> color; // 访问标记数组

void BFS(int start)
{
	queue<int> q; // BFS队列
	q.push(start); // 将起始节点加入队列
	color[start] = 1; // 标记起始节点为已访问
	while (!q.empty()) 
	{
		int current = q.front(); // 取出队列的第一个元素
		q.pop(); // 将该元素从队列中移除
		color[current] = 2;
		// 遍历当前节点的所有邻接节点
		for (auto &neighbour:graph[current]) 
		{
			color[neighbour] = 1;
			q.push(neighbour);
		}
	}
}

7.2-DFS(邻接表)

vector<vector<int>> graph; // 图的邻接表表示
vector<int> color; // 访问标记数组

void DFS(int node)
{
	color[node] = 1;
    for (auto &neighbour : graph[node])
    {
        if (color[neighbour]==0)
        {
            DFS(neighbour);
        }
    }
    color[node] = 2;
}

8-深度优先算法&生成树

  • DAG:有向无环图
  • (S)CC:(强)连通图
  • MST:最小生成树

8.1-Topological Sort(DAG)

int V; //顶点个数
vector<vector<int>> graph;
vector<int> indegree;
queue<int> q; // 维护一个入度为0的顶点的集合

bool topological_sort()
{
    for(int i=0; i<V; ++i)
        if(indegree[i] == 0)
            q.push(i);         // 将所有入度为0的顶点入队

    int count = 0;             // 计数,记录当前已经输出的顶点数 
    while(!q.empty())
    {
        int current = q.front();      // 从队列中取出一个顶点
        q.pop();
        cout << current << " ";      // 输出该顶点
        count++;
        // 将所有current指向的顶点的入度减1,并将入度减为0的顶点入栈
        for(auto &node:graph[current])
        {
        	indegree[node]--;
        	if(indegree[node]==0)
        	q.push(node);
        }
    }
    if(count < V)
        return false;           // 没有输出全部顶点,有向图中有回路
    else
        return true;            // 拓扑排序成功
}

8.2-Minimum Spanning Trees

8.2.1-Kruskal算法

int V; 			    //顶点个数
int parent[MAX];    //定义parent数组用来判断边与边是否形成环路

struct Edge
{
	int u,v,w;
};
vector<Edge> edges;

bool cmp(Edge a,Edge b)
{
	return a.w < b.w;
}

int Find(int x)
{
   return parent[x]==x ? x : parent[x] = find(parent[x])''
}
 
void Kruskal()
{
	sort(edges.begin(),edges.end(),cmp); //把图中的所有边按代价从小到大排序
	for(int i=0;i<V;i++) 				 //把图中的n个顶点看成独立的n棵树组成的森林
		parent[i] = i;
	for(int i=0;i<edges.size();i++)
	{
		int u=edges[i].u,v=edges[i].v;
		if(Find(u)!=Find(v)) //如果Find(u)=Find(v),则形成环路
			//将此边的结尾顶点放入下标为起点的parent数组中,表示此顶点已经在生成树集合中
			parent[Find(u)] = Find(v);
	}
}

8.2.2-Prim算法

#define inf INT_MAX
int n; //顶点个数
int res; //结果

vector<vector<int>> ma(n+1,vector<int>(n+1,inf)); //邻接矩阵,存边权,初始化为正无穷
vector<int> dist(n+1,0);					      //dist[]储存到生成树的距离
vector<bool> book(n+1,false);					  //用book数组记录某个点是否加入到生成树中

void prim()
{
	dist[1] = 0;
    book[1] = true;
    for(int i = 2; i <= n; i++)
    	dist[i] = min(dist[i],ma[1][i]);//用点1去更新dist[]
    for(int i = 2; i <= n; i++)
    {
        int temp = INF;//初始化距离
        int t = -1;    //接下来去寻找离生成树点集最近的点加入到集合中,用t记录这个点的下标。
        for(int j = 2 ; j <= n; j++)
        {
            if(!book[j] && dist[j]<temp)
            {
                temp = dist[j];
                t = j;
            }
        }
        //如果t==-1,意味着在集合V找不到边连向集合S,生成树构建失败,将res赋值正无穷表示构建失败
        if(t==-1)
        {
        	res = INF; 
        	return;
        }
        book[t] = true;//如果找到了这个点,就把它加入集合S
        res += dist[t];//加上这个点到集合S的距离
        for(int j = 2 ; j <= n ; j++)
        	dist[j] = min(dist[j],g[t][j]);//用新加入的点更新dist[]
}

8.2.3-Borůvka算法

int N,M;//N:点个数,M:边条数
struct Edge
{
	int u,v,w;
}
vector<Edge> edges;
vector<bool> visited(M+1,0);
vector<int> parent(N+1,0),dist(M+1,0),e(M+1,0);

int find(int x)
{
    return parent[x] == x ? x : parent[x] = find(parent[x]);
}

bool cmp(Edge a,Edge b)
{
	return a.w < b.w;
}

int boruvka()
{
	int cnt = 0,sum = 0;
	for(int i = 1;i <= N; i++)
		parent[i] = i;
	while (1)
	{
		int cnt_tmp=0;
		memset(dist,inf,sizeof(dist));                      //初始化dist数组 
		for (int i = 1; i <= M; i++)                        //每个边都计算一下dist
		{
			int f1 = find(edges[i].u),f2 = find(edges[i].v);//用并查集找到根 
			if (f1 == f2 || visited[i])                     //如果一棵树或者拓展过这个边 
				continue;
			cnt_tmp++;                                      //记录一下看下有没有边可以拓展 
			if (edges[i].w < d[f1])
				dist[f1] = edges[i].w,e[f1] = i;            //更新,e数组表示dist数组对应的边 
			if (edges[i].w < d[f2])
				dist[f2] = edges[i].w,e[f2] = i;
		}
		if (cnt_tmp == 0 || cnt == n - 1)
			break;
		for (int i = 1; i <= N; i++)                         //扫描每棵树 
		{
			int f1 = find(edges[e[i]].u),f2 = find(edges[e[i]].v);
			if(dist[i] == inf || f1 == f2 || visited[e[i]])
				continue;
			visited[e[i]] = 1;                              //加入最小生成树集合 
			parent[f1] = f2;
			sum += edges[e[i]].w;
			cnt++;
		}
	}
}

9-贪心

10-最短路

10.1-Floyd算法

int N; //顶点个数
vector<vector<int>> ma;//邻接矩阵,存储i到j的边权

void Floyd()
{
	for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            for (int k = 0; k < N; k++)
            {
                if (ma[j][k] > ma[j][i] + ma[i][k]) //若j到k间存在更短的通路,则更新
                    ma[j][k] = ma[j][i] + ma[i][k];
            }
        }
    }
}

10.2-Dijkstra算法

#define inf INT_MAX
int N; //顶点个数
vector<vector<int>> ma(N+1,vector<int>(N+1,inf));//邻接矩阵,存储i到j的边权
vector<int> dist(N+1,0),finished(N+1,0);

void Dijkstra(int start,int end)
{
	int min,k;
	finished[s] = 1,dist[s] = 0;
	for (int i = 1; i <= N; i++)
    {
        ma[i][i] = 0;
        dis[i] = ma[s][i];
    }
	for (int i = 1; i <= N; i++)
    {
        if (i != s)
        {
            min = inf;
            for (int j = 1; j <= N; j++)
            {
                if (flag[j] == 0 && dis[j] < min)
                {
                    min = dist[j];
                    k = j;
                }
            }
            flag[k] = 1;
            if (k == t)
                break;
            for (int j = 1; j <= N; j++)
            {
                int tmp = (ma[k][j] == inf ? inf : (min + ma[k][j]));
                if (finished[j] == 0 && tmp < dist[j])
                    dist[j] = tmp;
            }
        }
    }
}

10.3-Bellman-Ford算法

//用于判断图中是否存在负权环
#define inf INT_MAX
int N,M;//N:顶点个数,M:边条数
struct Edge
{
    int u, v, w;
};
vector<Edge> edges(M+1);
vector<int> dist(N+1,inf);

bool Bellman-Ford()
{
	for (int i = 1; i <= N; i++) //将dist数组更新一次,存储i节点所在环的权
    {
        for (int j = 1; j <= M; j++)
        {
            int u = edges[j].u, v = edges[j].v, w = edges[j].w;
            if (dist[v] > dist[u] + w)
                dist[v] = dist[u] + w;
        }
    }
    for (int i = 1; i <= M; i++) //再次更新dist数组,若权值改变,则图中存在负权环
    {
        if (dis[edges[i].v] > dis[edges[i].u] + edges[i].w)
            return 1;
    }
    return 0;
}

11-动态规划

标签:dist,parent,int,算法,vector,ma,20241225,大二
From: https://www.cnblogs.com/landboat/p/18631441

相关文章

  • 常见字符串算法简记(持续更新中)
    包含KMP(border相关,KMP自动机),Manacher,Zalgorithm(exKMP),SuffixArray的简单记录。当然写的很烂,欢迎当玩笑看。0.前言1.记一忘三二本文所写的字符串算法都基于一个基本思想:充分利用已知信息的性质加速求出所求信息的过程。这是老生常谈的。因此在这些算法的复杂度分析中主要......
  • 打印三角形金字塔 、debug、java的方法、命令行传参、可变参数20241225
    打印三角形金字塔debug20241225packagecom.pangHuHuStudyJava.struct;publicclassPrint_Tran{publicstaticvoidmain(String[]args){for(intj=0;j<5;j++){for(intr=5;r>j;r--){System.out.print(&#......
  • 一个GLSL Shader的格式化算法(LALR解析器)
    一个GLSLShader的格式化算法(LALR解析器)在进行OpenGL程序开发时,我需要自行解析`string`类型的Shader代码,抽取出里面的某些变量名和subroutine名。由于找不到可用的GLSLShader解析器,就照着虎书(《现代编译原理-c语言描述》)自己写了个LALRGenerator,实际上包含了(词法分析器+语法......
  • 算法备案、安全评估全网最详细流程说明【附流程+附件】
    一、“深度合成算法”与“生成合成类算法”的区别实践中,《互联网信息服务算法备案系统》显示,“生成合成类算法”与“深度合成算法”被称为一类,即“生成合成类(深度合成)算法”。因此,即使在技术层面深度合成技术与生成合成技术的或存在争议,但就算法备案实操而言,企业履行算法备案关系......
  • springboot毕设 协同过滤算法商品推荐系统程序+论文
    系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,电子商务已成为人们日常生活的重要组成部分。在海量商品信息面前,用户往往难以快速找到符合自己兴趣和需求的商品。传统的搜索方式依赖于用户主动输入关键词,但这种方式往往受限于用户的表达能力和对商品描述的......
  • 回溯算法来解决数独问题
    实现了一个基于回溯法的数独求解器,并且使用了位掩码来优化数字的使用情况检查,这样的实现可以提高效率。不过,存在一些可以进一步优化或改进的地方,特别是在backtrack函数中如何进行回溯以及使用最小剩余值(MRV)策略选择空单元格时的细节。1.初始化状态1row_used=[0]*9......
  • 冒泡排序算法-C语言
    冒泡排序的基本思想是通过重复遍历待排序的数列,比较相邻的元素,并将顺序错误的元素交换过来,从而把最大(或最小)的元素“冒泡”到数列的一端,就如同气泡最终会上浮到顶端一样,故名“冒泡排序”。  下面看个直接示例: 冒泡排序算法的基本步骤:1.从第一个元素开始,比较相邻的两个......
  • Scikit-learn机器学习库核心知识全攻略:算法、预处理与模型评估
    一、基本概念与安装安装可以使用pipinstall-Uscikit-learn命令在命令行中进行安装。如果使用Anaconda环境,也可以通过AnacondaNavigator或condainstallscikit-learn进行安装。依赖关系它依赖于NumPy(用于高效的数值计算,如数组操作)和SciPy(提供了许多科学计算算......
  • 算法刷题_链表篇
    算法刷题Day8_链表相交文章目录算法刷题Day8_链表相交@[TOC](文章目录)前言一、求出两个链表的长度和差值二、让其中较长一个链表移动到和第二链表对齐的位置三、其他解法_双指针法:总结前言简单来说,就是求两个链表交点节点的指针。一、求出两个链表的长度和差值......
  • 预测类算法实施全攻略:从数据到部署的完整流程
    一、问题定义明确目标变量:确定要预测的对象,例如预测股票价格、客户流失率、天气状况等。清晰地定义目标变量的含义和范围。了解业务背景:深入研究问题所在的领域,如在预测电商销售额时,需要了解产品类型、销售渠道、促销活动等因素对销售额的影响。确定预测期限:明确是进行短期预......