有向图(3.基于十字链表的c++实现)
很抱歉,换电脑后,原文件找不到了。现在的文件已经被我改得面目全非了。所以只好从新浪博客拷贝过来,格式惨不忍睹,让我蛋疼。但我实在是懒得去调整,将就一下吧。
这次发图的另一种实现,基于十字链表的c++实现。
就像上一章说的,十字链表是综合了邻接表和逆邻接表的构成,所以,代码需要修改的地方并不是很多。重要的是,修改算法的实现以提高效率。
代码中有两种搜索顶点的实现方式。一种是最原始的,另一种是排序后使用2分搜索。数据量巨大的时候,使用后一种能节省大量的时间。
整个过程中有几个比较需要注意的地方:
1.析构函数中,顶点释放时,开始错误地先删邻接表,后删逆邻接表。程序运行完毕,调用到析构函数的时候崩掉,才反应过来其实邻接表跟逆邻接表都是指向同样地节点。删除一个,另一个只需要置NULL就行了。一定要记住置NULL,不然悬浮指针可能也会引起问题。
2.2分搜索算法的实现。以前对于递归的实现很不在意,没有考虑太多的内部实现。后来看书才知道,尾部递归是个很差的习惯。所谓“尾部递归”,即在递归函数的最后又调用了自己。每一次递归产生的一些局部变量,开辟的空间会在本轮递归后释放。而如果尾部有递归调用,则会延迟释放的时间,造成大量空间的浪费。仔细思考,在尾部递归调用语句后面,函数不需要再处理什么,而尾部递归所需要的只是一些参数。这样,用递归和循环的思想,可以修改递归的实现方式,消除掉尾部递归,甚至可以消除掉递归,完全使用循环实现。
比如,代码中原始的2分搜索实现代码为:
template<typename vertexNameType, typename weight> int OLGraph<vertexNameType, weight>::binarySearchIndex(IN const vertexNameType vertexName, int beginPosition, int size){if ( size == 1) {if( m_vertexArray[beginPosition].vertexName == vertexName )return beginPosition;elsereturn -1; }if( vertexName == m_vertexArray[beginPosition + size/2 - 1].vertexName )return (beginPosition + size/2 - 1);else if( vertexName < m_vertexArray[beginPosition + size/2 - 1].vertexName )return binarySearchIndex(vertexName, beginPosition, size/2);elsereturn binarySearchIndex(vertexName, beginPosition + size/2, size - size/2 ); }
暂且不说这个效率比循环慢了很多,就复杂程度而言,也让人蛋疼。每一次分段的位置,必须要很仔细的检查,不然一不小心就会造成烦人的后果。
如果采用循环,消除掉递归,实现代码如下:
template<typename vertexNameType, typename weight>int OLGraph<vertexNameType, weight>::binarySearchIndex(IN const vertexNameType vertexName, int beginPosition, int size){int left = beginPosition;int right = size - 1;while(left <= right) {int middle = (left + right)/2;if (vertexName == m_vertexArray[middle].vertexName)return middle;if (vertexName > m_vertexArray[middle].vertexName) left = middle + 1;else right = middle - 1; }return -1;}
用循环实现,效率大概提升一倍。
3.指针。十字链表让人很烦躁的一个地方是弧头指针和弧尾指针很容易混淆。有时候一不注意,可能就会写反。尤其是插入边和删除边的时候,涉及到大量指针的做操,很容易出错。推荐先画个图,看着图写指针会清晰容易得多。
关于图的遍历,就留到后面,在讨论深度和广度遍历的时候再写出来。下一章写最短路径和dijkstra算法。
十字链表(OLGraph)代码如下:
#ifndef __GRAPH_H__#define __GRAPH_H__#include <vector>#include <iomanip>#define IN#define OUT#define INOUTusing namespace std;namespace graphspace{ template <typename weight>struct Edge //弧 {int tailvex; //弧尾顶点位置 int headvex; //弧头顶点位置 Edge<weight> *hlink; //弧头相同的弧链表 Edge<weight> *tlink; //弧尾相同的弧链表 weight edgeWeight; //弧权重 Edge(int a, int b, weight c, Edge<weight> *p = NULL, Edge<weight> *q = NULL) :tailvex(a), headvex(b), edgeWeight(c), hlink(p), tlink(q) {} }; template <typename vertexNameType, typename weight>struct Vertex //顶点 { vertexNameType vertexName; //顶点名 Edge<weight> *firstin; //指向第一条入弧(即指向逆邻接表) Edge<weight> *firstout; //指向第一条出弧(即指向邻接表) Vertex(vertexNameType x, Edge<weight> *p = NULL, Edge<weight> *q = NULL) :vertexName(x), firstin(p), firstout(q) {} }; template <typename vertexNameType, typename weight>class OLGraph {public:explicit OLGraph(); ~OLGraph();public://插入结点 bool insertAVertex(IN const vertexNameType vertexName);//插入边 bool insertAEdge(IN const vertexNameType vertexName1, IN const vertexNameType vertexName2, IN const weight edgeWeight);//边是否存在 bool edgeExist(IN const vertexNameType vertexName1, IN const vertexNameType vertexName2);//输出顶点的邻接表,即弧尾相同的链表 void vertexAdjEdges(IN const vertexNameType vertexName);//输出单个节点入度信息,弧头相同的链表(逆邻接表) void vertexRAdjEdges(IN const vertexNameType vertexName);//删除边 bool removeAEdge(IN const vertexNameType vertexName1, IN const vertexNameType vertexName2, IN const weight edgeWeight);//获取边权 weight getEdgeWeight(IN const Edge<weight> *pEdge);//将顶点的所有邻接边的权值放入数组或者vector中 void getVertexEdgeWeight(IN const int v1, OUT vector<weight> &DistanceArray); //获取最小权 weight getMinWeight(IN const vertexNameType vertexName1, IN const vertexNameType vertexName2);//获取顶点索引 int getVertexIndex(IN const vertexNameType vertexName);//获取顶点索引(2分搜索) int binarySearchIndex(IN const vertexNameType vertexName, int beginPosition, int size);//获取顶点名 vertexNameType getData(IN int index);//获取顶点数 int getVertexNumber();//迪科斯彻算法,最短路径 int Dijkstra(IN const vertexNameType vertexName1);//输出迪科斯彻 void DijkstraPrint(IN int index, IN int sourceIndex, IN vector<int> vecPreVertex);//结点合并拆分如何处理? friend ostream& operator<<(OUT ostream &out, IN const OLGraph<vertexNameType,weight> &graphInstance);public: vector< Vertex<vertexNameType, weight> > m_vertexArray; }; #include "OLGraph_realize.h"}#endif
实现类头文件:
#ifndef __GRAPH_REALIZE__H_#define __GRAPH_REALIZE__H_#include <ctime>template<typename vertexNameType, typename weight>OLGraph<vertexNameType, weight>::OLGraph(){if( !m_vertexArray.empty() ) m_vertexArray.clear();} template<typename vertexNameType, typename weight>OLGraph<vertexNameType, weight>::~OLGraph(){ vector< Vertex<vertexNameType, weight> >::iterator iter;for( iter = m_vertexArray.begin(); iter != m_vertexArray.end(); iter++ ) {//Error:删除两次节点//邻接表跟逆邻接表指向的是同样节点,删除其中之一即可,但是另一个指针一定不要忘记置NULL Edge<weight> *p = iter->firstin;while( NULL != p ) //删除逆邻接表 { iter->firstin = p->hlink; delete p; p = iter->firstin; } iter->firstout = NULL; }if( !m_vertexArray.empty()) m_vertexArray.clear();} template<typename vertexNameType, typename weight>bool OLGraph<vertexNameType, weight>::insertAVertex(IN const vertexNameType vertexName){//任然不做节点重复处理,因为数据来自另一个系统,已经保证不重复 Vertex<vertexNameType, weight> VertexInstance(vertexName, NULL); m_vertexArray.push_back(VertexInstance);return true;} template<typename vertexNameType, typename weight>bool OLGraph<vertexNameType, weight>::insertAEdge(IN const vertexNameType vertexName1, IN const vertexNameType vertexName2, IN const weight edgeWeight){int v1 = -1;int v2 = -1;int size = m_vertexArray.size();//2分搜索定位V1,V2在容器中的位置 v1 = binarySearchIndex(vertexName1, 0, size); v2 = binarySearchIndex(vertexName2, 0, size); if (-1 == v1) { cerr << "There is no vertex 1" << endl;return false; }if (-1 == v2) { cerr << "There is no vertex 2" << endl;return false; } Edge<weight> *p = m_vertexArray.at(v1).firstout; while( p != NULL && p->headvex != v2 ) { p = p->tlink; }if( NULL == p ) //不存在边v1->v2,将新边插入到链表头 { p = new Edge<weight>(v1, v2, edgeWeight, m_vertexArray.at(v2).firstin, m_vertexArray.at(v1).firstout); m_vertexArray.at(v1).firstout = p; m_vertexArray.at(v2).firstin = p;return true; }if( v2 == p->headvex) //已存在v1->v2的边 { Edge<weight> *q = p; Edge<weight> *t = m_vertexArray.at(v2).firstin;while( t != NULL && t->tailvex != v1) //找到边v1->v2在逆邻接表中的位置 { t = t->hlink; } p = new Edge<weight>(v1, v2, edgeWeight, t->hlink, q->tlink); //将新边加在已存在的第一条v1->v2后面 q->tlink = p; t->hlink = p;return true; }return false;}template<typename vertexNameType, typename weight>int OLGraph<vertexNameType, weight>::binarySearchIndex(IN const vertexNameType vertexName, int beginPosition, int size){ int left = beginPosition;int right = size - 1;while(left <= right) {int middle = (left + right)/2;if (vertexName == m_vertexArray[middle].vertexName)return middle;if (vertexName > m_vertexArray[middle].vertexName) left = middle + 1;else right = middle - 1; }return -1;} template<typename vertexNameType, typename weight>bool OLGraph<vertexNameType, weight>::edgeExist(IN const vertexNameType vertexName1, IN const vertexNameType vertexName2){int v1 = getVertexIndex(vertexName1);if (-1 == v1) { cerr << "There is no vertex 1" << endl;return false; }int v2 = getVertexIndex(vertexName2);if (-1 == v2) { cerr << "There is no vertex 2" << endl;return false; } Edge<weight> *p = m_vertexArray.at(v1).firstout;while(p != NULL && p->headvex != v2) { p = p->tlink; }if(NULL == p) { cout<<"dont exist"<<endl;return false; }if(v2 == p->headvex) //存在,则输出所有的v1->v2边 { cout<<"exist"<<endl; cout << vertexName1 << ": ";while(p != NULL && p->headvex == v2) { cout << "(" << vertexName1 << "," << vertexName2 << "," << p->edgeWeight << ") "; p = p->tlink; } cout << endl;return true; }} template<typename vertexNameType, typename weight>void OLGraph<vertexNameType, weight>::vertexAdjEdges(IN const vertexNameType vertexName){int v1 = getVertexIndex(vertexName);if( -1 == v1) { cerr<<"There is no vertex: "<<vertexName<<endl;return ; } Edge<weight> *p = m_vertexArray.at(v1).firstout; cout << vertexName << ": ";while( p != NULL) //顺着邻接表输出边信息 { cout<<"(" << vertexName << "," << getData(p->headvex) <<"," << p->edgeWeight <<") "; p = p->tlink; } cout<<endl;}template<typename vertexNameType, typename weight>void OLGraph<vertexNameType, weight>::vertexRAdjEdges(IN const vertexNameType vertexName){int v1 = getVertexIndex(vertexName);if( -1 == v1) { cerr<<"There is no vertex: "<<vertexName<<endl;return ; } Edge<weight> *p = m_vertexArray.at(v1).firstin; cout << vertexName << ": ";while( p != NULL) //顺着逆邻接表输出信息 { cout<<"(" << getData(p->tailvex) << "," << vertexName <<"," << p->edgeWeight <<") "; p = p->hlink; } cout<<endl;}template<typename vertexNameType, typename weight>bool OLGraph<vertexNameType, weight>::removeAEdge(IN const vertexNameType vertexName1, IN const vertexNameType vertexName2, IN const weight edgeWeight){int v1 = getVertexIndex(vertexName1);if (-1 == v1) { cerr << "There is no vertex 1" << endl;return false; }int v2 = getVertexIndex(vertexName2);if (-1 == v2) { cerr << "There is no vertex 2" << endl;return false; } Edge<weight> *p = m_vertexArray.at(v1).firstout; Edge<weight> *q = NULL;while( p != NULL && p->headvex != v2 ) { q = p; p = p->tlink; }if (NULL == p) { cerr << "Edge is not found" << endl;return false; }while( edgeWeight != p->edgeWeight && p->headvex == v2 ) { q = p; p = p->tlink; }if (v2 != p->headvex) { cerr << "Edge is not found" << endl;return false; } Edge<weight> *t = m_vertexArray.at(v2).firstin; Edge<weight> *s = NULL;while ( t != p ) //边若存在,那么一定是p指向的边,所以t的搜索条件与p相比即可 { s = t; t = t->hlink; } //修改v1的邻接表 if( q == NULL ) //邻接表第一个即所要删除的边 m_vertexArray.at(v1).firstout = p->tlink;else q->tlink = p->tlink; //修改v2的逆邻接表 if( s == NULL ) //逆邻接表第一个即所要删除的边 m_vertexArray.at(v2).firstin = t->hlink;else s->hlink = t->hlink; delete p; return true;}template<typename vertexNameType, typename weight>weight OLGraph<vertexNameType, weight>::getEdgeWeight(IN const Edge<weight> *pEdge){return pEdge->edgeWeight;} template<typename vertexNameType, typename weight>void OLGraph<vertexNameType, weight>::getVertexEdgeWeight(IN const int v1, OUT vector<weight> &DistanceArray){ Edge<weight> *p = m_vertexArray.at(v1).firstout;int prevIndex = -1; weight tmp;while(NULL != p) {if (prevIndex == p->headvex) //相同边找权值最小的一个 {if (tmp > p->edgeWeight) { DistanceArray[prevIndex] = p->edgeWeight; } }else { DistanceArray[p->headvex] = p->edgeWeight; prevIndex = p->headvex; tmp = p->edgeWeight; } p = p->tlink; }} template<typename vertexNameType, typename weight>weight OLGraph<vertexNameType, weight>::getMinWeight(IN const vertexNameType vertexName1, IN const vertexNameType vertexName2){ Edge<weight> *pEdge = NULL;int v1 = getVertexIndex(vertexName1);if (-1 == v1) { cerr << "There is no vertex 1" << endl;return false; }int v2 = getVertexIndex(vertexName2);if (-1 == v2) { cerr << "There is no vertex 2" << endl;return false; } Edge<weight> *p = m_vertexArray.at(v1).firstout;while (p != NULL && p->headvex != v2) { p = p->tlink; }if (NULL == p) { pEdge = NULL;return weight(0); } weight tmp = getEdgeWeight(p); pEdge = p;while (NULL != p && v2 == p->headvex) {if (tmp > getEdgeWeight(p)) { tmp = getEdgeWeight(p); pEdge = p; } p = p->tlink; }return tmp;} template<typename vertexNameType, typename weight>int OLGraph<vertexNameType, weight>::getVertexIndex(IN const vertexNameType vertexName){for( int i = 0; i < m_vertexArray.size(); i++ ) {if( vertexName == getData(i) )return i; }return -1;} template<typename vertexNameType, typename weight>vertexNameType OLGraph<vertexNameType, weight>::getData(IN int index){return m_vertexArray.at(index).vertexName;} template<typename vertexNameType, typename weight>int OLGraph<vertexNameType, weight>::getVertexNumber(){return m_vertexArray.size();}template<typename vertexNameType, typename weight>int OLGraph<vertexNameType, weight>::Dijkstra(IN const vertexNameType vertexName1){int sourceIndex = getVertexIndex(vertexName1);if (-1 == sourceIndex) { cerr << "There is no vertex " << endl;return false; }int nVertexNo = getVertexNumber(); vector<bool> vecIncludeArray; vecIncludeArray.assign(nVertexNo, false); vecIncludeArray[sourceIndex] = true; vector<weight> vecDistanceArray; vecDistanceArray.assign(nVertexNo, weight(INT_MAX)); vecDistanceArray[sourceIndex] = weight(0); vector<int> vecPrevVertex; vecPrevVertex.assign(nVertexNo, sourceIndex); getVertexEdgeWeight(sourceIndex, vecDistanceArray);int vFrom, vTo;while(1) { weight minWeight = weight(INT_MAX); vFrom = sourceIndex; vTo = -1;for (int i = 0; i < nVertexNo; i++) {if (!vecIncludeArray[i] && minWeight > vecDistanceArray[i]) { minWeight = vecDistanceArray[i]; vFrom = i; } }if (weight(INT_MAX) == minWeight) {break; } vecIncludeArray[vFrom] = true; Edge<weight> *p = m_vertexArray[vFrom].firstout;while (NULL != p) { weight wFT = p->edgeWeight; vTo = p->headvex;if (!vecIncludeArray[vTo] && vecDistanceArray[vTo] > wFT + vecDistanceArray[vFrom]) { vecDistanceArray[vTo] = wFT + vecDistanceArray[vFrom]; vecPrevVertex[vTo] = vFrom; } p = p->tlink; } }for (int i = 0; i < nVertexNo; i++) {if (weight(INT_MAX) != vecDistanceArray[i]) { cout << getData(sourceIndex) << "->" << getData(i) << ": "; DijkstraPrint(i, sourceIndex, vecPrevVertex); cout << "" << vecDistanceArray[i]; cout << endl; } }return 0;}template<typename vertexNameType, typename weight> void OLGraph<vertexNameType, weight>::DijkstraPrint(IN int index, IN int sourceIndex, IN vector<int> vecPreVertex){if (sourceIndex != index) { DijkstraPrint(vecPreVertex[index], sourceIndex, vecPreVertex); } cout << getData(index) << " ";} template<typename vertexNameType, typename weight> ostream& operator<<(OUT ostream &out, IN OLGraph<vertexNameType,weight> &graphInstance){int vertexNo = graphInstance.getVertexNumber();out << "This graph has " << vertexNo << "vertexes" << endl;for(int i = 0; i < vertexNo; i++) { vertexNameType x1 = graphInstance.getData(i);out << x1 << ": "; Edge<weight> *p = graphInstance.m_vertexArray.at(i).firstout;while (NULL != p) {out << "(" << x1 << "," << graphInstance.getData(p->headvex) << "," << p->edgeWeight << ") "; p = p->tlink; }out << endl; }return out;}#endif
主程序:
#include <iostream>#include <ctime>#include <string>#include <algorithm>#include "OLGraph.h"using namespace std;using namespace graphspace;int main(){ OLGraph<string, int> g; clock_t start1,finish1,time1;double duration; g.insertAVertex("A"); g.insertAVertex("B"); g.insertAEdge("A", "B", 16); g.insertAEdge("A", "B", 26); g.insertAEdge("A", "B", 36); g.insertAEdge("A", "B", 46); g.insertAEdge("A", "B", 6); g.insertAVertex("C"); g.insertAVertex("D"); g.insertAVertex("E"); g.insertAVertex("F"); cout<<g<<endl<<endl; g.insertAEdge("A", "B", 6); g.insertAEdge("A", "C", 3); g.insertAEdge("B", "C", 2); g.insertAEdge("B", "D", 5); g.insertAEdge("C", "D", 3); g.insertAEdge("C", "E", 4); g.insertAEdge("D", "E", 2); g.insertAEdge("D", "F", 3); g.insertAEdge("E", "F", 5); g.insertAEdge("B", "A", 6); g.insertAEdge("C", "A", 3); g.insertAEdge("C", "B", 2); g.insertAEdge("D", "B", 5); g.insertAEdge("D", "C", 3); g.insertAEdge("E", "C", 4); g.insertAEdge("E", "D", 2); g.insertAEdge("F", "D", 3); g.insertAEdge("F", "E", 5); cout<<g<<endl<<endl; cout<<g<<endl<<endl; g.Dijkstra("A"); g.vertexRAdjEdges("B");string vertex1;string vertex2;int controlNum;int value; cout<<"查询边请按 1,查询顶点邻接表请按 2,查询顶尖逆邻接表请按3 ,删除边请按4,退出请按 0:"<<endl; cin>>controlNum;while( controlNum != 0 ) { start1 = clock();switch ( controlNum ){case 1: cout<<"entry 2 vertex name"<<endl; cin>>vertex1>>vertex2; g.edgeExist(vertex1, vertex2); cout<<endl;break;case 2: cout<<"entry 1 vertex name"<<endl; cin>>vertex1; g.vertexAdjEdges(vertex1); cout<<endl;break;case 3: cout<<"entry 1 vertex name"<<endl; cin>>vertex1; g.vertexRAdjEdges(vertex1); cout<<endl;break;case 4: cout<<"entry 2 vertex name"<<endl; cin>>vertex1>>vertex2; cin>>value; g.removeAEdge(vertex1, vertex2, value); cout<<g<<endl<<endl;break;default:break; } cout<<"查询边请按 1,查询顶点邻接表请按 2,查询顶尖逆邻接表请按3 ,删除边请按4,退出请按 0:"<<endl; cin>>controlNum; finish1 = clock(); duration = (double)(finish1 - start1) / CLOCKS_PER_SEC; cout<<duration<<" seconds"<<endl; } system("pause");return 0;}
转载于:https://www.cnblogs.com/SadGeminids/archive/2011/12/23/2299207.html
有向图(3.基于十字链表的c++实现)相关推荐
- 【swjtu】数据结构实验5_基于十字链表的稀疏矩阵转置
实验内容及要求: 编写程序,从字符文件读入三个正整数m, n, t以及t个三元组(i, j, e)建立稀疏矩阵的十字链表存储结构.其中,m.n分别表示矩阵行数和列数:i, j为非零元素行号和列号.编 ...
- 7.2图的存储结构(十字链表、邻接多重表、边集数组)
思路: 有没有可能把邻接表和逆邻接表结合起来. 所以就产生了十字链表(Orthogonal List) 为此我们重新定义顶点表结点结构: data firstIn firstOut firstIn:第 ...
- 数据结构——十字链表(C语言实现)
十字链表是将邻接表和逆邻接表结合在一起的一种有向图的数据结构 十字链表的节点结构体表示的是一个节点到另一个节点的边,并且此由指出节点(from)和指入节点(to)共同使用,因此大大节省了内存. 先直观 ...
- 有向图的十字链表存储
/* c7-3.h 有向图的十字链表存储表示 */#define MAX_VERTEX_NUM 20typedef struct ArcBox{int tailvex,headvex; /* 该弧的尾 ...
- 日撸 Java 三百行(37 天: 十字链表)
注意:这里是JAVA自学与了解的同步笔记与记录,如有问题欢迎指正说明 目录 前言: 一.关于十字链表 1.特殊情况下邻接表的局限 2.十字链表的结构与特点 二.十字链表的代码实现 1.基本属性 2.出 ...
- noj数据结构稀疏矩阵的加法十字链表_数据结构学习(C )稀疏矩阵(十字链表1)
CSDN 先说说什么叫稀疏矩阵. 你说, 这个问题很简单吗, 那你一定不知道中国学术界的嘴皮子仗, 对一个字眼的"抠"将会导致两种相反的结论.这是清华 2000 年的一道考研题:& ...
- 图十字链表并求度c语言,利用十字链表存储树结构(便于同时求出某一点的入度与出度)------C语言实现...
#include #include #include /* 利用十字链表存储有向图,可用于同时查找某个顶点的出度与入度: */ typedef struct edge{//顶点表 int headve ...
- 稀疏矩阵的三元组表与十字链表存储
三元组表:存储稀疏矩阵的非零元素,以及该元素所在的行.列信息,极大的节省了空间(如相比于一般的二维数组的存储),而且三元组表的某些算法的时间效率也要优于经典算法,如基于三元组表的一次快速转置算法等等 ...
- C++ 十字链表图转java版
C++ 图 #include <iostream> #include <string> #include <queue> #include <stack> ...
- java用十字链表实现无向图_实验四:图的实现与应用
20162317袁逸灏 实验四:图的实现与应用 实验内容 用 邻接矩阵 十字链表 实现无向图中的 添加结点 删除结点 添加边 删除边 size() isEmpty() 广度优先迭代器 深度优先迭代器 ...
最新文章
- 父类与子类之间的关系
- linux删除文件操作
- vue 写bean_vue+jsp+删除一个bean
- 对刚iPad!华为最强Pad发布,独揽四项全球第一,3299元起!
- 计算机算法对程序设计的作用,算法计算机论文,关于数学算法对计算机编程优化相关参考文献资料-免费论文范文...
- python项目开发实例-有趣的十个Python实战项目,让你瞬间爱上Python!
- Day 12:枚举值、枚举类
- eclipse console 输出数据量大时不完整问题
- 错误因为数据库正在使用,所以无法获得对数据库的独占访问权的解决方案(转)...
- 经典算法——五大常用算法
- 将文件从ubuntu拷贝到linux开发板
- 正二十面体的各个面位置点
- 2.4g和5g要不要合并_路由器2.4g和5g双频合一好还是分开好
- 六成大学生认为自己毕业10年内会年入百万!
- 1、Visual Studio 2017安装
- Lora SX1268使用
- OpenWrt下使用iperf测试多跳网络性能
- R 关于NA的处理办法
- R16 5G NR Two-Step RACH
- 你真的不想知道录音如何转文字吗
热门文章
- 从论文pdf中复制粘贴文字时,空格变成回车的解决方法
- office2013打开出现配置进度
- Python Roberts算子、Sobel算子——举例说明 ^_^
- 图像处理MATLAB③(Roberts算子边缘检测,膨胀,滤波,腐蚀,开运算,闭运算使用方法)
- Allennlp 安装和使用问题
- MATLAB狼群算法求解车间生产调度问题代码实例(含甘特图)
- 五分钟带你玩转rabbitmq(八)【真实案例】消息消费失败如何处理?
- 【老生谈算法】matlab实现多元GARCH模型预测源码——GARCH模型
- LED产品认证和检测
- 马蜂窝张矗:我对技术团队绩效考核管理的几点思考