【邻接表】77 邻接表:顶点u的下一个邻接点
问题描述 :
目的:使用C++模板设计并逐步完善图的邻接表抽象数据类型(ADT)。
内容:(1)请参照图的邻接矩阵模板类原型,设计并逐步完善图的邻接表ADT。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。)
(2)设计并实现一个算法,在已存在的图中返回G中指定顶点u的下一个邻接顶点(相对于v)的位序(顶点集)。若顶点在G中没有邻接顶点,则返回-1。图的存储结构采用邻接表。将其加入到ADT中。
注意:DG(有向图), DN(有向网), UDG(无向图), UDN(无向网)
参考函数原型:
//返回G中指定顶点u的下一个邻接顶点(相对于v)的位序(顶点集)。若顶点在G中没有邻接顶点,则返回false
template<class TypeOfVer, class TypeOfEdge>
int adjlist_graph<TypeOfVer, TypeOfEdge>::GetNextAdjVex(int u, int v, int &w);
图的邻接表模板类原型参考如下:
/* 边表的结点定义 */
template<class TypeOfEdge>
struct edgeNode
{
int data;
TypeOfEdge weight;
edgeNode<TypeOfEdge> *next;
edgeNode(const int &d, edgeNode<TypeOfEdge> *ptr = NULL) //构造函数,用于构造其他结点(无权图)
//函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
{
next = ptr;
data = d;
}
edgeNode(const int &d, const TypeOfEdge &w, edgeNode<TypeOfEdge> *ptr = NULL) //构造函数,用于构造其他结点(带权图)
//函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
{
next = ptr;
data = d;
weight = w;
}
int getData(){ return data;} //取得结点的序号(顶点集)
TypeOfEdge getWeight(){ return weight;} //取得边集中对应边的权值
void SetLink( edgeNode<TypeOfEdge> *link ){ next = link; } //修改结点的next域
void SetData( int value ){ data = value; } //修改结点的序号(顶点集)
void SetWeight(TypeOfEdge value ){ weight = value; } //修改边集中对应边的权值
};
//图的邻接表类
template<class TypeOfVer, class TypeOfEdge>
struct verNode
{
TypeOfVer ver;
edgeNode<TypeOfEdge> *head;
verNode(edgeNode<TypeOfEdge> *h = NULL){head = h;}
TypeOfVer getVer(){ return ver;} //取得结点值(顶点集)
edgeNode<TypeOfEdge> *getHead(){ return head;} //取得对应的边表的头指针
void setVer(TypeOfVer value){ ver = value;} //设置结点值(顶点集)
void setHead(edgeNode<TypeOfEdge> *value){ head = value;} //设置对应的边表的头指针
};
template <class TypeOfVer, class TypeOfEdge>
class adjlist_graph{
private:
int Vers; //顶点数
int Edges; //边数
verNode<TypeOfVer,TypeOfEdge> *verList;
string GraphKind; //图的种类标志
bool Delete_Edge( int u, int v );
bool DFS(int u, int &num, int visited[]); //DFS遍历(递归部分)
public:
adjlist_graph( const string &kd, int vSize, const TypeOfVer d[]); //构造函数构造一个只有结点没有边的图。
adjlist_graph( const string &kd, int vSize, int eSize, const TypeOfVer d[], int **e); 构造函数构造一个无权图。5个参数的含义:图的类型、结点数、边数、结点集和边集
adjlist_graph( const string &kd, int vSize, int eSize, const TypeOfVer d[], int **e, const TypeOfEdge w[]); //构造函数构造一个有权图。
bool GraphisEmpty() { return Vers == 0; } //判断图空否
string GetGraphKind(){ return GraphKind; }
bool GetVer(int u, TypeOfVer &data); //取得G中指定顶点的值
int GetFirstAdjVex(int u, int &v); //返回G中指定顶点u的第一个邻接顶点的位序(顶点集)。若顶点在G中没有邻接顶点,则返回-1
int GetNextAdjVex(int u, int v, int &w); //返回G中指定顶点u的下一个邻接顶点(相对于v)的位序(顶点集)。若顶点在G中没有邻接顶点,则返回false
bool PutVer(int u, TypeOfVer data); //对G中指定顶点赋值
bool InsertVer(const TypeOfVer &data); //往G中添加一个顶点
int LocateVer(TypeOfVer data); //返回G中指定顶点的位置
bool ExistEdge(int u, int v);
bool PrintVer(); //输出顶点集
bool PrintAdjList(); //输出邻接矩阵
int GetVerNum(){ return Vers;} //取得当前顶点数
int GetEdgeNum(){ return Edges;} //取得当前边数
bool Insert_Edge(int u, int v); //无权图插入一条边
bool Insert_Edge(int u, int v, TypeOfEdge w); //有权图插入一条边
bool DeleteVer(const TypeOfVer &data); //往G中删除一个顶点
bool DeleteEdge( int u, int v ); //删除边 (外壳:有向(删除1条边), 无向(删除2条边))
void DFS_Traverse(int u); //DFS遍历(外壳部分)
void BFS_Traverse(int u); //BFS遍历
~adjlist_graph(); //析构函数
};
输入说明 :
建图的输入数据格式参见建图的算法说明。
第一行:图的类型
第二行:结点数
第三行:结点集
第四行:边数
第五行:边集
第六行:指定顶点的位序
第七行:参照顶点的位序
输出说明 :
第一行:顶点集
第二行:邻接表
空行
第三行:下一个邻接顶点的位序(如无邻接顶点,则输出-1)
输入范例 :
DG
6
A B C D E F
6
0 1
0 2
0 3
1 4
2 4
3 5
0
3
输出范例 :
A B C D E F
A->3->2->1
B->4
C->4
D->5
E
F2
解题代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <sstream>
#include <stack>
#include <map>
#include <ctime>
#include <array>
#include <set>
#include <list>
using namespace std;
//边的定义
template<class TypeOfEdge>
struct Edge_pair
{int point = 0;TypeOfEdge length = 0;//=================
};
//顶点的定义
template<class TypeOfVer, class TypeOfEdge>
struct verNode
{TypeOfVer ver_data;list<Edge_pair<TypeOfEdge> > group;//构造函数,默认会讲头指针设为空.verNode(){group.clear();ver_data = 0;}//取得结点值(顶点) 估计是为了安全吧???TypeOfVer getVer(){return ver_data;}//取得对应的边表list<Edge_pair<TypeOfEdge> > getHead(){return group;}//设置结点值(顶点集) 估计是为了安全吧???void setdata(TypeOfVer value){ver_data = value;return;}//=====================================================void creat_Point(int new_point, TypeOfEdge new_length){Edge_pair<TypeOfEdge> Next_p;Next_p.point = new_point;Next_p.length = new_length;group.insert(group.begin(), Next_p);return;}//删除指定位置顶点void del_Point(int n){return;}
};template <class TypeOfVer, class TypeOfEdge>//顶点元素类型,边权值类型
class adjlist_graph {
private:int Vers;//顶点数 int Edges;//边数 vector<verNode<TypeOfVer, TypeOfEdge> >ver;//顶点存储string GraphKind;//图的种类标志 bool have_dir = false, have_w = false;//图类型参数//======================================================================bool Delete_Edge(int u, int v)//删除一条边{return false;}bool DFS(int u, int& num, int visited[])//DFS遍历(递归部分){return false;}public://一个空的构造函数adjlist_graph(){Edges = 0;Vers = 0;}//假的析构函数 ~adjlist_graph(){;//你电脑内存就640K吗?}//判断图空否bool GraphisEmpty(){return Vers == 0;}//获取图的类型string GetGraphKind(){return GraphKind;}//取得当前顶点数 int GetVerNum(){return Vers;}//取得当前边数 int GetEdgeNum(){return Edges;}//自动建立临接表bool Auto_build(void){//DG(有向图), DN(有向网), UDG(无向图), UDN(无向网)/*第一行:图的类型 DN UDN第二行:结点数第三行:结点集第四行:无边标记第五行:边数第六行:边集第七行:权集*//*第一行:图的类型 DG UDG第二行:结点数第三行:结点集第四行:边数第五行:边集*/cin >> GraphKind;//图的类型 cin >> Vers;//结点数ver.resize(Vers);//开辟节点空间for (int i = 0; i < Vers; i++)//结点集{TypeOfVer now;cin >> now;ver[i].setdata(now);}cin >> Edges;//边数vector<int> x_p, y_p, w_p;for (int i = 0; i < Edges; i++){int c_x, c_y;cin >> c_x >> c_y;x_p.push_back(c_x);y_p.push_back(c_y);}//图的类型识别if (GraphKind == "DG")//DG(有向图)have_dir = true, have_w = false;if (GraphKind == "DN")//DN(有向网)have_dir = true, have_w = true;if (GraphKind == "UDG")//UDG(无向图)have_dir = false, have_w = false;if (GraphKind == "UDN")//UDN(无向网)have_dir = false, have_w = true;if (have_w)for (int i = 0; i < Edges; i++){int c_w;cin >> c_w;w_p.push_back(c_w);}for (int i = 0; i < Edges; i++){if (have_dir)if (have_w)ver[x_p[i]].creat_Point(y_p[i], w_p[i]);elsever[x_p[i]].creat_Point(y_p[i], 0);elseif (have_w)ver[x_p[i]].creat_Point(y_p[i], w_p[i]), ver[y_p[i]].creat_Point(x_p[i], w_p[i]);elsever[x_p[i]].creat_Point(y_p[i], 0), ver[y_p[i]].creat_Point(x_p[i], 0);}return 1;}//取得G顶点的组vector<TypeOfVer> GetVer(void){vector<TypeOfVer> head_group;for (int i = 0; i < Vers; i++){head_group.push_back(ver[i].getVer());}return head_group;}//输出邻接表 bool Print_photo(){int i;for (i = 0; i < Vers; i++){cout << ver[i].getVer();if (ver[i].group.size() != 0)cout << "->";else{cout << endl;continue;}vector<Edge_pair<TypeOfEdge> > out_lis;out_lis.clear();for (auto j = ver[i].group.begin(); j != ver[i].group.end(); j++){out_lis.push_back(*j);}int j;for (j = 0; j < out_lis.size() - 1; j++)if (have_w)cout << out_lis[j].point << "(" << out_lis[j].length << ")" << "->";elsecout << out_lis[j].point << "->";if (have_w)cout << out_lis[j].point << "(" << out_lis[j].length << ")" << endl;elsecout << out_lis[j].point << endl;}return 1;}//往G中添加一个顶点 bool InsertVer(const TypeOfVer& data){verNode<TypeOfVer, TypeOfEdge> new_e;new_e.setdata(data);ver.push_back(new_e);Vers++;return true;}//寻找顶点位置int Look_Ver(const TypeOfVer& data){int i;for (i = 0; i < Vers; i++)if (ver[i].ver_data == data)return i;return -1;}//删除一个顶点bool del_Point(int place){int need_del = 0;if (!(0 <= place && place < Vers))return false;int i;for (i = 0; i < Vers; i++){for (auto j = ver[i].group.begin(); j != ver[i].group.end(); j++){if (j->point == place){need_del++;ver[i].group.erase(j);break;}}for (auto j = ver[i].group.begin(); j != ver[i].group.end(); j++){if (j->point > place)j->point--;}}need_del += ver[place].group.size();ver.erase(ver.begin() + place);Vers--;if (have_dir)Edges -= need_del;elseEdges -= (need_del / 2);return true;}//无权图插入一条边bool Insert_Edge(int u, int v){if (!(0 <= u && u < Vers))return false;if (!(0 <= v && v < Vers))return false;for (auto i = ver[u].group.begin(); i != ver[u].group.end(); i++){if (i->point == v)return false;}for (auto i = ver[v].group.begin(); i != ver[v].group.end(); i++){if (i->point == u)return false;}if (u == v)return false;if (have_dir){Edges++;ver[u].creat_Point(v, 1);return true;}else{Edges++;ver[u].creat_Point(v, 1);ver[v].creat_Point(u, 1);return true;}return true;}//有权图插入一条边bool Insert_Edge(int u, int v, TypeOfEdge w){if (!(0 <= u && u < Vers))return false;if (!(0 <= v && v < Vers))return false;for (auto i = ver[u].group.begin(); i != ver[u].group.end(); i++){if (i->point == v)return false;}for (auto i = ver[v].group.begin(); i != ver[v].group.end(); i++){if (i->point == u)return false;}if (u == v)return false;if (have_dir){Edges++;ver[u].creat_Point(v, w);return true;}else{Edges++;ver[u].creat_Point(v, w);ver[v].creat_Point(u, w);return true;}return true;}//删除边 (外壳:有向(删除1条边), 无向(删除2条边))bool del_Edge(int u, int v){if (!(0 <= u && u < Vers))return false;if (!(0 <= v && v < Vers))return false;if (u == v)return false;bool ok = true;if(have_dir)for (auto i = ver[u].group.begin(); i != ver[u].group.end(); i++){if (i->point == v){ver[u].group.erase(i);Edges--;return true;}}else{for (auto i = ver[u].group.begin(); i != ver[u].group.end(); i++){if (i->point == v){ver[u].group.erase(i);break;}}for (auto i = ver[v].group.begin(); i != ver[v].group.end(); i++){if (i->point == u){ver[v].group.erase(i);Edges--;return true;}}}return false;}//返回G中指定顶点u的第一个邻接顶点的位序(顶点集)。若顶点在G中没有邻接顶点,则返回-1int GetFirst_AdjVex(int u){if(ver[u].group.empty())return -1;return ver[u].group.begin()->point;}//返回G中指定顶点u的下一个邻接顶点(相对于v)的位序(顶点集)。若顶点在G中没有邻接顶点,则返回falseint GetNext_AdjVex(int u, int v){if (ver[u].group.size() == 1)return -1;for (auto i = ver[u].group.begin(); i != ver[u].group.end(); i++){if (i->point == v){if ((++i) == ver[u].group.end())return -1;return i->point;}}return -1;}/*+++++++++++====分割线====++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*///对G中指定顶点赋值 bool PutVer(int u, TypeOfVer data){return false;}//返回G中指定顶点的位置 int LocateVer(TypeOfVer data){return -1;}//存在边bool ExistEdge(int u, int v){return 0;}//DFS遍历(外壳部分)void DFS_Traverse(int u){return;}//BFS遍历void BFS_Traverse(int u){return;}};int main()
{int i;adjlist_graph<char, int> a;a.Auto_build();int u, v, w;cin >> u >> v;//cout << a.GetGraphKind() << endl;vector <char> ans;ans = a.GetVer();for (i = 0; i < ans.size() - 1; i++)cout << ans[i] << " ";cout << ans[i] << endl;//cout << a.GetVerNum() << endl;//cout << a.GetEdgeNum() << endl;a.Print_photo();cout << endl;cout << a.GetNext_AdjVex(u,v) << endl;return 0;
}
【邻接表】77 邻接表:顶点u的下一个邻接点相关推荐
- 邻接表:求指定顶点的(出)度
问题描述 : 目的:使用C++模板设计并逐步完善图的邻接表抽象数据类型(ADT). 内容:(1)请参照图的邻接矩阵模板类原型,设计并逐步完善图的邻接表ADT.(由于该环境目前仅支持单文件的编译,故将所 ...
- 邻接表:构造只有顶点没有边的图
文章目录 问题描述 : 输入说明 : 输出说明 : 输入范例 : 输出范例 : 基本知识 实现伪码 思路分析 实现伪码 析构函数 构造函数 事故现场 提交了三次 分析与总结 如有不妥或者疑问,请留言或 ...
- 邻接表:两个顶点是否相邻
问题描述 : 目的:使用C++模板设计并逐步完善图的邻接表抽象数据类型(ADT). 内容:(1)请参照图的邻接矩阵模板类原型,设计并逐步完善图的邻接表ADT.(由于该环境目前仅支持单文件的编译,故将所 ...
- 用邻接表存储图c语言,邻接表、邻接多重表、十字链表及C语言实现
上一节介绍了如何使用顺序存储结构存储邻接多重表和 邻接的意思是顶点之间有边或者弧存在,通过当前顶点,可以直接找到下一个顶点. 邻接表 使用邻接表存储图时,对于图中的每一个顶点和它相关的邻接点,都存储到 ...
- 【编译原理笔记15】运行存储分配概述,静态存储分配,栈式存储分配,调用序列和返回序列,非局部数据的访问,符号表,符号表建立
本次笔记内容: 7-1 运行存储分配概述 7-2 静态存储分配 7-3 栈式存储分配 7-4 调用序列和返回序列 7-5 非局部数据的访问 7-6 符号表 7-7 符号表建立 本节课幻灯片,见于我的 ...
- crc16 c语言 非查表,CRC16CCITT(1021)的16字表长查表程序
CRC位域4单表查表及建表原则: 左移位域4取列表16个,大端存储模式.右移位域4取行表16个,小端存储模式. 在CRC16CCITT中CRC的多项式为:左移CRC16=X16+X12+X5+1,即权 ...
- crc16 ibm c语言,CRC16IBM(A001)的16字表长查表程序
本帖最后由 hotpower 于 2009-10-18 19:10 编辑 此文依据: http://blog.ednchina.com/hotpower/272834/message.aspx CRC ...
- java有向图邻接表入度_图的实现--邻接表(求出各顶点的出度和入度)
#include using namespace std; #include #define MAX 100 struct ArcNode{//边结点 int adjvex;//有向边的另一个邻接点的 ...
- Mysql的多表查询(表添加,多表查询练习:笛卡尔积、内连接、外连接、子查询、UNION组合查询)
https://blog.csdn.net/hanhanwanghaha宝藏女孩 欢迎您的关注! 欢迎关注微信公众号:宝藏女孩的成长日记 如有转载,请注明出处(如不注明,盗者必究) 目录 一.表的创建 ...
最新文章
- Cordova error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Deve
- Java类加载文章1(z)
- 模式识别的评价方法:ROC曲线, DET曲线, FPPW, FPPI
- python读取xlsx文件pandas_python-如何使用iPython中的pandas库读取.xlsx文件?
- Java培训教程:Java中的位移运算符!
- linux下安装编译网卡驱动
- matlab概率论实验 分别掷硬币1,基于Matlab的概率论仿真实验
- python怎么模拟浏览器交互_python+webdriver 模拟用户交互工具
- python爬取某人所有微博_Python爬取博客的所有文章并存为带目录的word文档(实例67)
- android 汽车 源码_汽车级Linux,无需Google即可运行Android等
- 留言板显示服务器错误,动易Cms:解读SiteFactory 留言板出现:服务器无响应,错误代码:500-动易Cms教程...
- SpringCloud分布式开发理解
- 深蓝学院-视觉SLAM理论与实践-第十二期-第2章作业
- 【知识分享】C语言的设计模式——责任链、观察者
- Layui官方js正则验证手机号,邮箱,网址,日期,身份证
- 全球经济寒冬将至?且看顶级资本大鳄的大数据分析预测
- 免费WebCamps-北美,亚洲和欧洲-*立即注册*
- 计算机基础应用寒假作业,计算机基础寒假作业.doc
- ❤️软件设计师之程序设计语言与语言处理程序基础“小总结”(莽起来)❤️
- 仿新浪微博照片选择器
热门文章
- 明明输给了 SpaceX,OneWeb 为什么还能拿到英国政府的钱?
- 便携式禁毒采样器的基础功能
- 吸毒后人脸变化系统在禁毒教育展厅中的应用
- 如何给刚刚出厂的服务器配置IP地址(华为RH2288 v3)
- 计算机必修课程英语单词,《计算机专业英语》课程标准(已审核).doc
- 虹科PCAN在工程机械中的应用
- 每日一题:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
- android wifi tethering,新增Wi-Fi/USB Tethering功能
- word文档表格后面的空白页怎么删除?
- 计算机打印机共享失败,打印机共享失败终极解决办法