数据结构实验(C++实现):图的操作

实验要求:

  1. 创建图类,存储结构使用邻接矩阵。
  2. 输入图的节点数n(小于10个)、边数m,节点分别用1-n代表。
  3. 采用“起始节点,终止节点,权值”输入图的m条边,创建图。
  4. 输出从节点1开始的BFS遍历,在遍历过程中,如有多个可以选择的节点,则优先选择编号较小的节点。
  5. 输出从节点1开始的DFS遍历,在遍历过程中,如有多个可以选择的节点,则优先选择编号较小的节点。
  6. 输出从第1节点到第n节点最短路径的长度,如果没有路经,输出0。

(输出格式如下图所示
输出格式如图所示


实验难点:

  1. 自己定制图类(因为懒,所以定制图类是能省则省,能不写就不写,嘿嘿);
  2. 寻找最短路径的Dijkstra算法(也可以用深度优先搜索算法来实现,但是因为学习了Dijkstra算法,所以用来练习,难点);
  3. 控制输出格式,尤其是逗号,下面的算法用了commaFlag来实现逗号输出控制(讨巧实现);
  4. 对于STL中的list和queue的使用(也可以用自己写的,但是我懒,所以用现成的,嘿嘿);
  5. 要时刻注意一些细节,比如邻接数组的边界,new的数组的初始化和释放等等。

//my solution
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <iterator>
#define label 1//reached label
#define noPredecessor 0//no predecessor
#define maxCapacity 11
using namespace std;

//weighted graph(desribed by ajacency matrix)
template<class T>
class Graph
{
public:
	Graph(int = 0, T = (T)0);
	~Graph() { clearMatrix(); };

	void creatGraph(int);
	void insertEdge(int, int, T);
	//both bfs and dfs are traverrsal from vertex 1
	void bfs() const;
	void dfs() const;
	void realDfs(int, bool*, bool) const;
	void shortestPath() const;
	void clearMatrix();
protected:
	int vertexNum;
	int edgeNum;
	T** ajacencyMatrix;
	T noEdge;
};

template<class T>
Graph<T>::Graph(int vn,T theNoEdge)
{
	vertexNum = vn;
	edgeNum = 0;
	noEdge = theNoEdge;
	//creat ajacency matrix
	ajacencyMatrix = new T* [vn + 1];
	for (int i = 0; i <= vn; i++) ajacencyMatrix[i] = new T[vn + 1];
	//initialize
	for (int j = 1; j <= vertexNum; j++)
		fill(ajacencyMatrix[j], ajacencyMatrix[j] + vertexNum + 1, noEdge);
}

template<class T>
void Graph<T>::insertEdge(int v1, int v2, T w)
{
	ajacencyMatrix[v1][v2] = w;
	ajacencyMatrix[v2][v1] = w;
	edgeNum++;
}

template<class T>
void Graph<T>::creatGraph(int en)
{
	char c;
	int v1, v2, w;
	//insert
	for (int k = 1; k <= en; k++)
	{
		cin >> v1 >> c >> v2 >> c >> w;
		insertEdge(v1, v2, w);
	}
}


template<class T>
void Graph<T>::bfs() const
{
	int start = 1;
	//commaFlag is used to control output of comma.
	bool commaFlag = true;
	queue<int> q;
	//isReached is used to judge whether a vertex has been reached
	//value 0(false) means NOT REACHED and value 1(true) means REACHED	 
	bool* isReached=new bool[maxCapacity]();

	isReached[start] = label;
	q.push(start);
	while (!q.empty())
	{		
		int v = q.front();
		q.pop();
		//output bfs traversal result
		if (commaFlag)
		{
			cout << v;
			commaFlag = false;
		}
		else cout<< ',' << v;

		for (int i = 1; i <= vertexNum; i++)
		{
			if (ajacencyMatrix[v][i] != noEdge && !isReached[i])
			{
				q.push(i);
				isReached[i] = label;
			}
		}
	}
	delete[]isReached;
}

template<class T>
void Graph<T>::dfs() const
{
	//commaFlag is used to control output of comma.
	bool commaFlag = true;
	bool* isReached = new bool[maxCapacity]();
	realDfs(1, isReached, commaFlag);
	delete[]isReached;
}

template<class T>
void Graph<T>::realDfs(int vertex, bool* isReached, bool commaFlag) const
{
	//output dfs traversal result
	if (commaFlag)
	{
		cout << vertex;
		commaFlag = false;
	}
	else cout << "," << vertex;

	isReached[vertex] = label;
	for (int i = 1; i <= vertexNum; i++)
		if (ajacencyMatrix[vertex][i] != noEdge && !isReached[i])
			realDfs(i,isReached,commaFlag);
}

//Dijkstra Funtion
template<class T>
void Graph<T>::shortestPath() const
{
	int source = 1, distination = vertexNum;
	int* previous=new int[maxCapacity];
	T* presentDistance=new T[maxCapacity];
	list<int> newReach;
	//initialize presentDistance
	for (int x = 0; x < maxCapacity; x++) presentDistance[x] = noEdge;

	for (int i = 1; i <= distination; i++)
	{
		presentDistance[i] = ajacencyMatrix[source][i];
		if (presentDistance[i] != noEdge)
		{
			previous[i] = source;
			newReach.push_front(i);
		}
		else previous[i] = noPredecessor;
	}
	previous[source] = -1;//source has no predecessor
	
	while (!newReach.empty())
	{
		list<int>::iterator itNewReach = newReach.begin();
		list<int>::iterator end = newReach.end();
		list<int>::iterator itMin = newReach.begin();
		int vMin = *itNewReach;
		
		for (; itNewReach != end; itNewReach++)
		{
			if (presentDistance[vMin] > presentDistance[*itNewReach])
			{
				vMin = *itNewReach;
				itMin = itNewReach;
			}
		}
		newReach.erase(itMin);

		for (int k = 1; k <= distination; k++)
		{
			if (ajacencyMatrix[vMin][k] != noEdge && 
				(previous[k] == noPredecessor || presentDistance[k] > presentDistance[vMin] + ajacencyMatrix[vMin][k]))
			{
				presentDistance[k] = presentDistance[vMin] + ajacencyMatrix[vMin][k];
				if (previous[k] == noPredecessor) newReach.push_front(k);
				previous[k] = vMin;
			}
		}
	}
	if (presentDistance[distination] != noEdge) cout << presentDistance[distination] << endl;
	else cout << "0" << endl;
	delete[]presentDistance;
	delete[]previous;
}

template<class T>
void Graph<T>::clearMatrix()
{
	for (int i = 0; i <= vertexNum; i++) delete[]ajacencyMatrix[i];
	delete[]ajacencyMatrix;
}


int main()
{
	int n, m;
	char c;
	cout << "Input" << endl;
	cin >> n >> c >> m;
	Graph<int> g(n);
	g.creatGraph(m);
	cout << "Output" << endl;
	g.bfs(); cout << endl;
	g.dfs(); cout << endl;
	g.shortestPath();
	cout << "End" << endl;
	system("pause");
	return 0;
}

实验体会:
最后一次数据结构实验了,但考试月又来了
江郎才尽最后一次数据结构实验了,但考试月又来了

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构》实验题目 实验一 学生成绩管理(链表)  实验目的:熟练掌握单链表操作的基本算法实现。  实现功能:以带表头结点的单链表为存储结构实现如下学生成绩管理的设计要求。  实验机时:6  设计要求: (1)定义学生成绩链表结点结构类型,以xscjList和*XscjLink命名,据域:学号NO、姓名Name、手机号MTel、邮箱地址Email、籍贯 BornAddr、A分成绩AScore、B分成绩BScore,指针域:*next; (2)实现创建学生成绩链表函void Build(XscjLink &T),输入学号、姓名、手机号、邮箱地址、籍贯、A分成绩、B分成绩,建议用文件操作输入据; (3)实现void Update(XscjLink T, char *Name, float *ScoreA),将姓名为Name的学生的A分成绩改为ScoreA; (4)实现输出学生成绩信息void OutPut(XscjLink T),输出所有学生的学号、姓名、手机号、邮箱地址、籍贯、A分成绩、B分成绩; (5) 实现void Insert(XscjLink T, char *Name, char *No),插入学号为NO,姓名为Name学生信息,将链表中学号≤NO的结点放到该结点的前面,将学号>NO的结点放到该结点后面; (6)实现void Sort(XscjLink T),将该学生按照B分成绩进行非递减排序; (7)实现void Merge(XscjLink &T1;, XscjLink &T2;),将两个按B分成绩非递减排序的学生成绩单合并为一个按B分成绩非递增排序的通讯录,B分成绩相同且学号相同的成绩记录在结果中只保留一个;要求算法的时间复杂度不超过两个链表的长度之和O(m+n); (8)实现int Count(XscjLink T);统计籍贯是“广州”的学生人; (9)实现void MoveK(XscjLink T, int k),将学生成绩链表中倒第k个结点之后的所有结点移到头结点后面(保持结点间的先后顺序),注意:严禁采用先计算链表长度n再减k(即n-k)的方法;要求算法的时间复杂度不超过个链表的长度O(n); (10)实现void ReverseN(XscjLink T),将学生成绩链表的正中间位置结点之后的全部结点倒置,注意:严禁采用先计算链表长度n再除以2(即n/2)的方法;要求算法的时间复杂度不超过个链表的长度O(n); (11)主控函main()调用以上函,分别输出(2)、(3)、(5)、(6)、(7)、(8)、(9)(10)处理后的链表内容、输出籍贯是“广州”的学生人。 可能用到的函: 从文件中读取学生成绩据:fscanf(文件指针,"%s %s %s %s %s %f %f", p->NO, p->Name, p->Mtel, p->Email, p-> BornAddr, p->AScore, p->BScore); 输出学生成绩据:printf("%s %s %s %s %s %f %f", p->NO, p->Name, p->Mtel, p->Email, , p-> BornAddr, p->AScore, p->BScore); 字符串赋值函:char * strcpy(char *, const char *); 字符串比较函:int strcmp(const char *, const char *) #include #include #include //定义学生成绩链表结点结构 typedef struct XscjNode { char NO[10]; //学号 char Name[16]; //姓名 char MTel[11]; //手机号 char EMail[16]; //邮箱地址 char BornAddr[20]; //籍贯(值域:"北京"、"上海"、"大连"等等,只写城市名称) float AScore; // A分成绩 float BScore; //B分成绩 struct XscjNode *next; //指针域 }XscjList, *XscjLink; 实验二 Huffman编码(二叉树)  实验目的:熟练掌握二叉树应用(Huffman编码)的基本算法实现。  实现功能:对输入的一串电文字符实现Huffman编码,再对Huffman编码生成的代码串进行译码,输出电文字符串。实现功能如下: • Huffman树的建立 • Huffman编码的生成 • 编码文件的译码  实验机时:10  设计思路: 数据结构: #define n 100 //叶子结点 #define m 2*n-1 // Huffman树中结点总 typedef struct { char data; 字符 int weight; //权值 int lchild , rchild , parent; //左右孩子及双亲指针 }HTNode; //树中结点类型 typedef HTNode HuffmanTree[m+1]; //0号单元不用 主要实现:  统计字符串中字符的种类以及各类字符的个的函  构造Huffman树的函  Huffman编码的函  建立正文的编码文件的函  代码文件的译码函  主函 实验三 各种排序方法的比较  实验目的:熟练掌握内部排序算法实现。  实现功能:编制一个演示内部排序算法比较的程序。要求通过编写程序实现起泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、堆排序等常用的内部排序算法,并通过样本据比较各个算法的时空特性  实验机时:4
一. 实验目的: 1.通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解。熟悉虚存管理的各种页面淘汰算法 2.通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。 二.实验要求 实验程序由以下三大部分组成: (1) 通过随机产生一个指令序列(实际上是指令的逻辑地址序列),共320条指令。指令的地址按下述原则生成: A:50%的指令是顺序执行的 B:25%的指令要实现向前跳转,均匀分布在前地址部分 C:25%的指令要实现向后跳转,均匀分布在后地址部分 具体的实施方法是: A:在[0,319]的指令地址之间随机选取一起点m B:顺序执行一条指令,即执行地址为m+1的指令 C:在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m’ D:顺序执行一条指令,其地址为m’+1 E:在后地址[m’+2,319]中随机选取一条指令并执行 F:重复步骤A-E,直到320次指令 (2) 将每条指令的逻辑地址变换为页地址 设:页面大小为1K; 用户内存容量4页到32页; 用户虚存容量为32K。 在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为: 第 0 条-第 9 条指令为第0页(对应逻辑地址为[0,9]) 第10条-第19条指令为第1页(对应逻辑地址为[10,19]) ……………………………… 第310条-第319条指令为第31页(对应逻辑地址为[310,319]) 按以上方式,用户指令可组成32页。 (3) 分别使用FIFO算法和LFU算法,计算给用户进程的这32页分配4,5,…,32个页面(内存块)时其缺页率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值