数据结构与算法实验9 实现无向连通图的最小生成树

文章目录

  • 1.上机名称
  • 2.上机要求
  • 3.上机环境
  • 4.程序清单(写明运行结果及结果分析)
    • 4.1 程序清单
      • 4.1.1 头文件 Graph.h 内容如下:
      • 4.1.2 实现文件 Graph.cpp 内容如下:
      • 4.1.3 源文件 main.cpp 内容如下:
    • 4.2 运行结果
  • 5.上机体会

1.上机名称

实现无向连通图的最小生成树

2.上机要求

(1)编写程序实现求带权连通图最小生成树的Prim算法。
(2)编写程序实现求带权连通图最小生成树的Kruskal算法。

3.上机环境

visual studio 2022 Windows11 家庭版 64位操作系统

4.程序清单(写明运行结果及结果分析)

4.1 程序清单

4.1.1 头文件 Graph.h 内容如下:

#pragma once#include<iostream>
#include<queue>
//按照实验要求,本次实验构建的是无向图,为后续实验方便,引进图的种类标志,尝试将有向版本、网的版本统一起来。
enum GraphKind{//枚举类型,无向图,无向网,有向图,有向网UN_GRAPH,UN_NET,_GRAPH,_NET
};typedef char Data;	//图的顶点里的数据元素
typedef int flag;	    //用于标注是否被遍历typedef struct NeighbourNode {//邻接表的一个成员int id;			//邻接表里的下标int weight;		//权重,默认为0
}NBnode, * pNBnode;typedef struct GNode {//定义图的顶点元素结构Data data;				//数据成员pNBnode* LNeighbours;	//左邻(入)接表pNBnode* RNeighbours;   //右邻(出)接表flag is_visited;		       //标注是否被遍历flag fatherid;			   //标注上一级节点id,用于Kruskal算法辅助int LN_cnt;			   //左邻数int RN_cnt;			   //右邻数
}Gnode, * pGnode;typedef struct ARC {//一个弧的抽象数据类型pGnode left;	//起点int leftid;		pGnode right;	//终点int rightid;int weight;
}Arc, * pArc;class Graph {
public://创建一个顶点数为vex_num的图,图的类型为KindGraph(int vex_num = 0, int Kind = 0);//通过邻接矩阵创建图	Graph(int** array_for_summon, int size, int Kind);~Graph();								//析构函数void insert(Data data);					//插入顶点void setdata(int id, Data data);		    //设置顶点数据void link(int id1,int id2,int weight = 1);	    //使两个顶点之间产生边关联,weight == 0 表示无关联。void CreateArray();						//通过传入的邻接矩阵生成图,并对矩阵的合法性进行检测void printNBS(int id);					//打印id顶点的邻接表void printARR();						//打印图的邻接矩阵void printArc();						//打印所有边void DFS(int firstid = 0);				//从下标为firstid的顶点深度优先遍历void BFS(int firstid = 0);				//从下标为firstid的顶点广度优先遍历void MSTPrim(int firstid = 0);			//使用Prim算法求最小生成树void MSTKruskal(int firstid = 0);		    //使用kruskal算法求最小生成树void MergeArcWeigt(int low ,int high);    //对带权边进行从小到大的排序,参数为0,arc_numconst int get_vex_num();				//返回顶点数const int get_arc_num();					//返回边数,无向图、网返回值是边的两倍,在函数调用过程中自洽
protected:void makeneighbour(int id1, int id2, int weight = 1);//造邻居void SetFlag();					//初始化两个flagvoid DFSearch(int firstid = 0);		//对一个顶点的DFSvoid BFSearch(int firstid = 0);        //对一个顶点的DFSvoid swap(int id1, int id2);			//在排序中对两个边进行互换int fa(int id);						//返回代表元素,用于kruskal算法int vex_num;			//顶点数量int arc_num;			//弧数量int** GArray;			//邻接矩阵int GKind;			//图的类型标记pGnode* vex;			//存放顶点的顺序表pArc* arc;			//存放弧的顺序表
};

4.1.2 实现文件 Graph.cpp 内容如下:

#include "Graph.h"
Graph::Graph(int vex_num , int Kind ){this->vex_num = vex_num;vex = new pGnode[vex_num];for (int i = 0; i < vex_num; i++) {vex[i] = new Gnode;}for (int i = 0; i < vex_num; i++) {vex[i]->LN_cnt = 0;vex[i]->RN_cnt = 0;vex[i]->LNeighbours = new pNBnode;vex[i]->RNeighbours = new pNBnode;vex[i]->is_visited = 0;}GArray = new int* [vex_num]; for (int i = 0; i < vex_num; i++)GArray[i] = new int[vex_num];for (int i = 0; i < vex_num; i++)for (int j = 0; j < vex_num; j++) GArray[i][j] = 0;GKind = Kind;arc_num = 0;arc = new pArc;
}Graph::Graph(int** array_for_summon, int size, int Kind){   vex_num = size;arc_num = 0;vex = new pGnode[vex_num];for (int i = 0; i < vex_num; i++) {vex[i] = new Gnode;}for (int i = 0; i < vex_num; i++) {vex[i]->LN_cnt = 0;vex[i]->RN_cnt = 0;vex[i]->LNeighbours = new pNBnode;vex[i]->RNeighbours = new pNBnode;vex[i]->is_visited = 0;}GKind = Kind;GArray = new int*[size];for (int i = 0; i < size; i++) GArray[i] = new int[size];for (int i = 0; i < size; i++) for (int j = 0; j < size; j++) GArray[i][j] = array_for_summon[i][j];CreateArray();
}Graph::~Graph(){for (int i = 0; i < vex_num; i++) delete[]GArray[i];delete[]GArray;for (int i = 0; i < vex_num; i++) {delete[]vex[i]->LNeighbours;delete[]vex[i]->RNeighbours;vex[i]->LN_cnt = 0;vex[i]->RN_cnt = 0;vex[i]->is_visited = 0;vex[i]->data = 0;}delete[]vex;vex_num = 0;std::cout << "内存释放完毕!" << std::endl;
}void Graph::insert(Data data){++vex_num;int** tmp = new int* [vex_num]; for (int i = 0; i < vex_num; i++) tmp[i] = new int[vex_num];for (int i = 0; i < vex_num; i++) for (int j = 0; j < vex_num; j++) {if (i == vex_num - 1 || j == vex_num - 1) tmp[i][j] = 0;else tmp[i][j] = GArray[i][j];}if (vex_num != 1) {	//不要释放空for (int i = 0; i < vex_num - 1; i++)delete[] GArray[i];delete []GArray;}vex[vex_num - 1]->data = data;std::cout << "new vertex ID: " << vex_num - 1 << "(start from zero)" << std::endl;GArray = tmp;
}void Graph::setdata(int id, Data data){vex[id]->data = data;
}void Graph::link(int id1, int id2, int weight ){switch (GKind){case UN_GRAPH: {//无向图if (id1 == id2) makeneighbour(id1, id2);else{makeneighbour(id1, id2);makeneighbour(id2, id1);}break;}case UN_NET: {//无向网if(id1==id2) makeneighbour(id1, id2, weight);else {makeneighbour(id1, id2, weight);makeneighbour(id2, id1, weight);}break;}case _GRAPH: {//有向图makeneighbour(id1, id2);break;}case _NET: {//有向网makeneighbour(id1, id2, weight);break;}default:std::cout << "Link failed!" << std::endl; break;}
}void Graph::CreateArray(){switch (GKind){case UN_GRAPH:case UN_NET: {for (int i = 0; i < vex_num; i++) {for (int j = 0; j <= i; j++) {if (GArray[i][j] != GArray[j][i]) {std::cout << "传入的矩阵作为无向图/网不合法!输入Y/N选择兼容或退出:" << std::endl;char c = getchar(); getchar();switch (c) {default:exit(-1);case 'y':case 'Y': {link(i, j, GArray[i][j] > GArray[j][i] ? GArray[i][j] : GArray[j][i]);continue;}}}if (GArray[i][j] != 0 ) link(i, j, GArray[i][j]);}}break;}case _GRAPH:case _NET: {for (int i = 0; i < vex_num; i++) {for (int j = 0; j < vex_num; j++) {if (GArray[i][j] != 0)link(i, j, GArray[i][j]);}}break;}default: std::cout << "Summon From Array Failed!" << std::endl;}
}void Graph::makeneighbour(int id1, int id2, int weight ) {//id1 出度+1。pNBnode* fresh = new pNBnode[vex[id1]->RN_cnt + 1];for (int i = 0; i < vex[id1]->RN_cnt + 1; i++) fresh[i] = new NBnode;for (int i = 0; i < vex[id1]->RN_cnt; i++) {fresh[i]->id = vex[id1]->RNeighbours[i]->id;fresh[i]->weight = vex[id1]->RNeighbours[i]->weight;}fresh[vex[id1]->RN_cnt]->id = id2;fresh[vex[id1]->RN_cnt]->weight = weight;for (int i = 0; i < vex[id1]->RN_cnt; i++) delete[] vex[id1]->RNeighbours[i];delete[] vex[id1]->RNeighbours;vex[id1]->RNeighbours = fresh;//id2 入度+1。pNBnode* fresh2 = new pNBnode[vex[id2]->LN_cnt + 1];for (int i = 0; i < vex[id2]->LN_cnt + 1; i++) fresh2[i] = new NBnode;for (int i = 0; i < vex[id2]->LN_cnt; i++) {fresh2[i]->id = vex[id2]->LNeighbours[i]->id;fresh2[i]->weight = vex[id2]->LNeighbours[i]->weight;}fresh2[vex[id2]->LN_cnt]->id = id1;fresh2[vex[id2]->LN_cnt]->weight = weight;for (int i = 0; i < vex[id2]->LN_cnt; i++) delete[] vex[id2]->LNeighbours[i];delete[] vex[id2]->LNeighbours;vex[id2]->LNeighbours = fresh2;//弧段添加pArc* fresh3 = new pArc[arc_num + 1];for (int i = 0; i < arc_num + 1; i++) {fresh3[i] = new Arc;fresh3[i]->right = new Gnode;fresh3[i]->left = new Gnode;}for (int i = 0; i < arc_num; i++) fresh3[i] = arc[i];fresh3[arc_num]->left = vex[id1];fresh3[arc_num]->right = vex[id2];fresh3[arc_num]->weight = weight;fresh3[arc_num]->leftid = id1;fresh3[arc_num]->rightid = id2;delete[] arc;arc = fresh3;//别忘了对邻接矩阵和用于记录的数据进行修改GArray[id1][id2] = weight;vex[id1]->RN_cnt++;vex[id2]->LN_cnt++;arc_num++;
}void Graph::printNBS(int id){pGnode obj = vex[id];switch (GKind){case UN_GRAPH: {std::cout << "顶点ID:" << id << "的邻居ID:" << std::endl;if (obj->RN_cnt != 0)for (int i = 0; i < obj->RN_cnt; i++)std::cout << obj->RNeighbours[i]->id << " ";std::cout << std::endl;break;}case UN_NET: {if (obj->LN_cnt != 0)std::cout << "顶点ID:" << id << "的邻居ID[权重]:" << std::endl;for (int i = 0; i < obj->LN_cnt; i++)std::cout << obj->LNeighbours[i]->id << "[" << obj->LNeighbours[i]->weight << "]" << " ";std::cout << std::endl;break;}case _GRAPH: {std::cout << "顶点ID:" << id << std::endl;if (obj->LN_cnt != 0) {std::cout << "左邻ID:" << std::endl;for (int i = 0; i < obj->LN_cnt; i++)std::cout << obj->LNeighbours[i]->id << " ";std::cout << std::endl;}if (obj->RN_cnt != 0) {std::cout<< "\n右邻ID:" << std::endl;for (int i = 0; i < obj->RN_cnt; i++)std::cout << obj->RNeighbours[i]->id << " ";std::cout << std::endl;}break;}case _NET: {std::cout << "顶点ID:" << id << std::endl;if (obj->LN_cnt != 0) {std::cout << "左邻ID[权重]:" << std::endl;for (int i = 0; i < obj->LN_cnt; i++)std::cout << obj->LNeighbours[i]->id <<"[" << obj->LNeighbours[i]->weight << "]" << " ";std::cout << std::endl;}if (obj->RN_cnt != 0) {std::cout << "右邻ID[权重]:" << std::endl;for (int i = 0; i < obj->RN_cnt; i++)std::cout << obj->RNeighbours[i]->id <<"[" << obj->RNeighbours[i]->weight << "]" << " ";std::cout << std::endl;}break;}default:std::cout << "Find Neighbours Error!" << std::endl;}
}void Graph::printARR(){std::cout << "图的邻接矩阵:\n";for (int i = 0; i < vex_num; i++){for (int j = 0; j < vex_num; j++) {std::cout << GArray[i][j] << " ";}std::cout << std::endl;}
}
void Graph::printArc(){switch (GKind) {case UN_GRAPH:case UN_NET: {for (int i = 0; i < arc_num; i+=2) {std::cout << "(" << arc[i]->left->data << " " << arc[i]->weight << " " << arc[i]->right->data << ")" << std::endl;}break;}case _GRAPH:case _NET: {for (int i = 0; i < arc_num; i ++) {std::cout << "<" << arc[i]->left->data << " " << arc[i]->weight << " " << arc[i]->right->data << ">" << std::endl;}break;}default:std::cout << "遍历边序列有误" << std::endl;}}void Graph::DFS(int firstid){SetFlag();DFSearch(firstid);for (int i = 0; i < vex_num; i++) {if (vex[i]->is_visited == 0)DFSearch(i);}std::cout << std::endl;}void Graph::BFS(int firstid){	SetFlag();BFSearch(firstid); for (int i = 0; i < vex_num; i++) {if (vex[i]->is_visited == 0)BFSearch(i);}std::cout << std::endl;
}void Graph::MSTPrim(int firstid){SetFlag();std::queue<int> v;v.push(firstid);vex[firstid]->is_visited = 1;while (v.size() != vex_num) {int wflag = 65535;int idflag = 65535;int iflag = firstid;for (int i = 0; i < v.size(); i++) {for (int j = 0; j < vex[i]->RN_cnt; j++) {if (vex[vex[i]->RNeighbours[j]->id]->is_visited == 0&& wflag > vex[i]->RNeighbours[j]->weight) {wflag = vex[i]->RNeighbours[j]->weight;idflag = vex[i]->RNeighbours[j]->id;iflag = i;}}}std::cout << vex[iflag]->data << " " << wflag << " " << vex[idflag]->data << std::endl;v.push(idflag);vex[idflag]->is_visited = 1;}}void Graph::MSTKruskal(int firstid){SetFlag();MergeArcWeigt(0,arc_num);			//首先我们进行排序为贪心算法做准备int num = 0;for (int i = 0; i <arc_num; i++){if (num == vex_num - 1)break;	//达到要求就退出else {if (fa(arc[i]->leftid) != fa(arc[i]->rightid)) {	//如果一个边左右不属于一个代表元素,也就是说他们不在一个连通图中,将他们连到一起。arc[i]->right->fatherid = arc[i]->leftid;num++;std::cout << arc[i]->left->data << " " << arc[i]->weight << " " << arc[i]->right->data << std::endl;}else if (fa(arc[i]->leftid) != fa(arc[i]->rightid))continue;}}if (num != vex_num - 1) {	//可能出现不连通的情况,这时有这个式子进行判断进行提示std::cout << "所给图并非连通图!" << std::endl;exit(-2);}
}void Graph::MergeArcWeigt(int low,int high){//此部分代码参考快速排序int flag = low;	//标杆元素下标if (low == high) return;for (int i = flag + 1; i < high; i++) {if (arc[flag]->weight <= arc[i]->weight)continue;if (arc[flag]->weight > arc[i]->weight) {swap(flag + 1, i);swap(flag, flag + 1);flag++;}}if (flag > low)	MergeArcWeigt(low, flag - 1);if (flag < high)MergeArcWeigt(flag + 1, high);
}const int Graph::get_vex_num(){return vex_num;
}const int Graph::get_arc_num(){return arc_num;
}void Graph::SetFlag(){for (int i = 0; i < vex_num; i++) {vex[i]->is_visited = 0;vex[i]->fatherid = i;}
}void Graph::DFSearch(int firstid){if (vex[firstid]->is_visited == 0) {	//如果元素没被访问vex[firstid]->is_visited = 1;		//进行访问std::cout << vex[firstid]->data << " ";for (int i = 0; i < vex[firstid]->RN_cnt; i++) {//对这个元素所有右邻if (vex[vex[firstid]->RNeighbours[i]->id]->is_visited == 0) {	//如果没被访问DFSearch(vex[firstid]->RNeighbours[i]->id);					//进行访问}}}}void Graph::BFSearch(int firstid){std::queue<int> q;		//一个队列q.push(firstid);		//放入一个元素vex[firstid]->is_visited = 1;	//标记为访问过while (!q.empty()) {	//当队列非空的时候for (int i = 0; i < vex[q.front()]->RN_cnt; i++) {		//对队头元素所有的右邻int nextid = vex[q.front()]->RNeighbours[i]->id;	//拿到右邻的idif (vex[nextid]->is_visited == 0) {					//如果没有被访问q.push(nextid);									//入队,标记为访问过vex[nextid]->is_visited = 1;}									else continue;}std::cout << vex[q.front()]->data << " ";q.pop();	//删除队头元素}}void Graph::swap(int id1, int id2){//用于快速排序中改变指针指向pArc tmp = arc[id1];arc[id1] = arc[id2];arc[id2] = tmp;
}int Graph::fa(int id){if (vex[id]->fatherid == id) return id;else {return fa(vex[id]->fatherid);}
}

4.1.3 源文件 main.cpp 内容如下:

#include"Graph.h"
int main() {int** arr_for_summon = new int* [8]; for (int i = 0; i < 8; i++)arr_for_summon[i] = new int[8];int arr[8][8] = {0, 1, 0, 2, 0, 3, 0, 4,1, 0, 4, 0, 5, 6, 0, 0,0, 4, 0, 3, 0, 0, 0, 0,2, 0, 3, 0, 2, 0, 0, 5,0, 5, 0, 2, 0, 1, 0, 0,3, 6, 0, 0, 1, 0, 1, 0,0, 0, 0, 0, 0, 1, 0, 2,4, 0, 0, 5, 0, 0, 2, 0 };for (int i = 0; i < 8; i++)for (int j = 0; j < 8; j++)arr_for_summon[i][j] = arr[i][j];Graph gr1(arr_for_summon, 8, UN_NET);for (int i = 0; i < 8; i++) {gr1.setdata(i, 'A' + i);}for (int i = 0; i < 8; i++) {gr1.printNBS(i);}//gr1.printARR();std::cout << "深度优先遍历" << std::endl;gr1.DFS();std::cout << "广度优先遍历" << std::endl;gr1.BFS();std::cout << "Prim算法最小生成树:" << std::endl;gr1.MSTPrim();std::cout << "Kruskal算法最小生成树:" << std::endl;gr1.MSTKruskal();
}

4.2 运行结果

在这里插入图片描述
在这里插入图片描述

5.上机体会

本次实验在上次实验基础上,利用矩阵输入,在无向连同图中完成了Prim算法和Kruskal算法,进行最小生成树的生成。在实验过程中发现了上次实验中存在的问题缺陷,例如在某些循环里将‘i’写成了‘1’,导致访问越界问题,可见在一个项目完成的过程中需要进行全面的测评。在本次实验中主要掌握了两种算法思想:一个是“做标记”,即在不确定是否满足条件的情况下,用一个flag先标记数据,在满足条件下更改flag以减少在循环里处理的次数,对于在一个数据群里需要按照某个规律找到有限个满足条件的数据时十分实用;另一个是“代表元素”,也就是简单的并查集,在大量数据群体中,若要拎出两个元素对它们是否在一个群体中进行判断,可以用到这样的思想:每个群体都派出一个代表元素,只要每个在群体里的数据知道自己的代表元素是谁就行,那样任意两个元素是否在一个群体里,只要看他们的代表元素是否相同就行,相比于无脑的循环查找判断能够大大降低时间复杂度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1547848.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用Git管理项目工程

目录 安装git 注册gitee gitee注册示例 git账户配置 使用git仓库 在本地生成一个git仓库 创建文件并增加commit 命令详解 git status git add git commit git remote git push git pull git fetch git log git branch 安装git windows下安装git可以直接上git…

distinct导致sql超时

前言 昨天敲着敲着代码&#xff0c;小杨哥跑过来给我说&#xff0c;快看他们大会议室演示报错了&#xff0c;还是一堆错了。完了啊在演示的时候报错&#xff01;&#xff01;&#xff01;接下来我们分析一下是什么原因吧。 问题分析 查看日志&#xff1a; 从日志打印看明显的…

Gin框架简易搭建(3)--Grom与数据库

写在前面 项目地址 个人认为GORM 指南这个网站是相比较之下最为清晰的框架介绍 但是它在环境搭建阶段对于初学者而言不是很友好&#xff0c;尤其是使用mysql指令稍有不同&#xff0c;以及更新的方法和依赖问题都是很让人头疼的&#xff0c;而且这些报错并非逻辑上的&#xf…

用大模型优化大模型预训练数据,节省20倍计算量,实现显著性能提升!

生成式人工智能研究实验室&#xff08;GAIR&#xff0c;主页&#xff1a;https://plms.ai/&#xff09;是国内首个聚焦于生成式人工智能的高校研究组。汇聚了来自于 CMU、复旦、交大&#xff08;ACM 班、IEEE 试点班等&#xff09;等顶尖高校的年轻本硕博人才。实验室专注于三大…

大数据-150 Apache Druid 安装部署 单机启动 系统架构

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

从‘盲管’到‘智网’,漫途精准构建排水管网监测方案

在城市错综复杂的基础设施网络中&#xff0c;排水管网作为城市的“血脉”&#xff0c;其高效、稳定运行直接关系到城市生活的安宁与财产的安全。面对日益频繁的雨季挑战与气候变化的不确定性&#xff0c;传统“盲管”管理模式已难以满足现代城市治理的需求。 漫途排水管网监测…

LED显示屏如何通过FMEA进行风险分析:打造无忧显示新境界

LED显示屏作为高科技产品&#xff0c;其性能受到多种因素的影响&#xff0c;包括但不限于设计缺陷、材料质量、制造工艺、使用环境等。任何环节的疏漏都可能导致显示屏出现亮度不均、色彩失真、故障频发等问题&#xff0c;进而影响用户体验和品牌形象。因此&#xff0c;通过FME…

Linux标准IO(四)-格式化I/O输入

C 库函数提供了 3 个格式化输入函数&#xff0c;包括&#xff1a;scanf()、fscanf()、sscanf()&#xff0c;其函数定义如下所示&#xff1a; #include <stdio.h> int scanf(const char *format, ...); int fscanf(FILE *stream, const char *format, ...); int sscanf(c…

Spring Web MVC课后作业

目录 1.加法计算器 2.⽤户登录 3.留⾔板 1.加法计算器 &#xff08;1&#xff09;需求分析 加法计算器功能, 对两个整数进⾏相加, 需要客⼾端提供参与计算的两个数, 服务端返回这两个整数计算 的结果。 &#xff08;2&#xff09;接⼝定义 请求路径&#xff1a; calc/sum 请…

爬取元气手机壁纸简单案例(仅用于教学,禁止任何非法获利)

爬虫常用的库 爬虫&#xff08;Web Scraping&#xff09;是一种从网页上提取数据的技术。在 Python 中&#xff0c;有许多库可以帮助实现这一目标。以下是一些常用的爬虫库&#xff0c;以及对 BeautifulSoup 的详细介绍。 常用爬虫库 1.Requests ​ a.功能&#xff1a;用于发…

spark计算引擎-架构和应用

一Spark 定义&#xff1a;Spark 是一个开源的分布式计算系统&#xff0c;它提供了一个快速且通用的集群计算平台。Spark 被设计用来处理大规模数据集&#xff0c;并且支持多种数据处理任务&#xff0c;包括批处理、交互式查询、机器学习、图形处理和流处理。 核心架构&#x…

ChatGPT Sidebar 浏览器插件配置指南

随着聊天机器人技术的不断进步&#xff0c;越来越多的人开始依赖这些强大的工具来提高工作效率、获取信息和解决问题。OpenAI 的 ChatGPT 是其中最受欢迎的聊天机器人之一。为了方便用户在浏览网页时随时与 ChatGPT 互动&#xff0c;开发者们设计了一款名为 ChatGPT Sidebar 的…

Latex——一行的划线 如何分开

代码&#xff1a; \cmidrule(r){3-4} \cmidrule(r){5-6} \cmidrule(r){7-8}效果&#xff1a; 参考文章&#xff1a; LaTeX技巧653&#xff1a;如何隔开LaTeX表格邻近\cline表格线&#xff1f;

四,MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用)

四&#xff0c;MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用) 文章目录 四&#xff0c;MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用)1. 主键策略1.1 主键生成策略介绍 2. 准备工作&#xff1a;2.1 AUTO 策略2.2 INPUT 策略2.3 ASSIGN_ID 策略2.3.1 雪花算…

电动车、电单车入梯数据集电动车进电梯检测识别(代码+教程+数据集)

数据集介绍 共有 5347 张图像和一一对应的标注文件 标注文件格式提供了两种&#xff0c;包括VOC格式的xml文件和YOLO格式的txt文件。 标注的对象共有以下几种&#xff1a; [‘Electric-bicycle’] 标注框的数量信息如下&#xff1a;&#xff08;标注时一般是用英文标的&am…

AC-DC电源自动测试系统介绍

AC-DC电源模块测试系统是一种高度自动化的测试设备&#xff0c;能够模拟实际工作环境中的交流电输入&#xff0c;并测量电源模块的输出电压、电流、功率等关键参数&#xff0c;以及评估其电磁兼容性、效率、热特性等性能指标。 AC-DC电源模块测试系统的主要硬件组成包括&#…

TDEngine在煤矿综采管控平台中的应用

一、行业背景 智能综采管控平台&#xff0c;是将煤矿综采工作面传感器数据采集&#xff0c;通过可视化界面展示。实现综采工作面的透明化展示&#xff0c;并基于历史的传感器数据进行机器学习的训练&#xff0c;了解工作面周期来压&#xff0c;设备故障检测等数据应用。因此针…

纷享销客生态伙伴大会西安站圆满落幕,共话CRM新纪元

9月19日&#xff0c;以“智享未来&#xff0c;领创CRM新纪元”为主题的纷享销客生态伙伴大会在西安成功举办。本次会议汇聚了SaaS领域、软件行业以及TOB市场的杰出代表、行业领袖以及技术前沿专家&#xff0c;共同探讨SaaS CRM行业的当前发展趋势&#xff0c;并就AI在CRM领域的…

如何使用ssm实现基于web的山东红色旅游信息管理系统的设计与实现

TOC ssm716基于web的山东红色旅游信息管理系统的设计与实现jsp 绪论 1.1研究背景 从古到今&#xff0c;信息的录入&#xff0c;存储&#xff0c;检索都受制于社会生产力的发展&#xff0c;不仅仅浪费大量的人力资源还需要浪费大量的社会物资&#xff0c;并且不能长时间的保…

c++----继承(初阶)

大家好呀&#xff0c;今天我们也是多久没有更新博客了&#xff0c;今天来讲讲我们c加加中的一个比较重要的知识点继承。首先关于继承呢&#xff0c;大家从字面意思看&#xff0c;是不是像我们平常日常生活中很容易出现的&#xff0c;比如说电视剧里面什么富豪啊&#xff0c;去了…