《数据结构》课程设计 —— 图的实现(C++)

目录

图的实现

项目获取

具体实现解析

pubuse.h C++头文件

ALGraphDef.h C++头文件 

ALGraphAlgo.h C++头文件

C++代码文件ALGraphUse.cpp 

结语


图的实现

文件名功能
ALGraphAlgo.h定义了图数据结构相关的函数,包括无向图的创建、获取顶点数据、邻接边及遍历操作。
ALGraphDef.h定义了图的邻接列表数据结构,包括顶点、边的结构体和图的数据结构,以及队列结构。
pubuse.h包含基本的标准库导入,定义了布尔常量、枚举和类型别名,用于项目中的通用操作。
ALGraphUse.cpp实现了一个交互式应用,允许用户创建、探索并遍历图,使用了上述头文件中定义的数据结构和函数。

整个程序的功能是:提供一个基于命令行的图形数据结构交互式工具,用户可以创建无向图,查询顶点信息和邻接边,并进行深度优先和广度优先遍历。

这些文件整体上构成了一个C++实现的图数据结构库,包含图的定义、算法实现以及一个示例应用,让用户能够创建、操作和遍历无向图。

项目获取

【免费】学生课设,C++数据结构实验,图的实现,vs2022完整项目,包含完整代码,开箱即用资源-CSDN文库icon-default.png?t=N7T8https://download.csdn.net/download/btaworld/89304194

所有代码已经上传到CSDN,通过资源绑定功能已经绑定本篇博客,有需要请自取,完整的VS2022项目,运行“数据结构-二叉树.sln”即可在vs2022中打开(一般来说,版本无限制)

在我上传时,设置了0积分,可以免费获取,但不保证后续积分要求会不会变化(但放心,不会变成付费或会员专享资源),不过,还请尽快保存! 

具体实现解析

pubuse.h C++头文件

pubuse.h 是一个C++头文件,包含了一系列标准库和自定义常量及类型的定义。这个文件的主要目的是提供常用的函数和类型以便在项目中使用:

  1. 引入多种标准库,如<string><iostream><math.h>等,支持字符串操作,输入输出,数学计算等功能。
  2. 定义了一些布尔常量TRUEFALSE,以及状态枚举OKERRORINFEASIBLE,原本可能用于表示函数调用的结果。
  3. 使用typedef定义了StatusBoolean类型,简化了代码中对整型常量作为返回值或参数的使用。
  4. 注意到注释中提到的OVERFLOW原本被定义,但因为math.h已经定义了相同的值,所以取消了定义。

这个文件可能在更大的数据结构或算法实现项目中用作通用的头文件,为其他源代码文件提供共用的类型和常量。

#include<string> 
#include<ctype.h> 
#include<malloc.h> /* malloc()等*/ 
#include<limits.h> /* INT_MAX 等*/ 
#include<stdio.h> /* EOF(=^Z 或F6),NULL */ 
#include<iostream>
#include<stdlib.h> /* atoi() */ 
#include<io.h> /* eof() */ 
#include<math.h>/* floor(),ceil(),abs() */ 
#include<process.h> /* exit() */ 
#include"conio.h" 
#include <sstream>

using namespace std;

/* 函数结果状态代码*/
#define TRUE 1 
#define FALSE 0 
#define OK 1 
#define ERROR 0 
#define INFEASIBLE -1 
//#define OVERFLOW -2 因为在math. h 中已定义OVERFLOW 的值为3,故去掉此行
typedef int Status; /* Status 是函数的类型,其值是函数结果状态代码,如OK 等*/
typedef int Boolean; /* Boolean 是布尔类型,其值是TRUE 或FALSE */

ALGraphDef.h C++头文件 

ALGraphDef.h 是一个C++头文件,它定义了一个图的数据结构和相关操作。以下是文件内容的概述:

  1. #include "pubuse.h":包含另一个名为"pubuse.h"的头文件。
  2. MVNum 100:定义了一个常量MVNum,值为100,可能用于限制图中顶点的最大数量。
  3. OtherInfo 结构体:存储图中的边的额外信息(例如权重),包含一个double类型的'l'成员。
  4. ArcNode 结构体:表示图中的有向边,包含:
    • adjvex:边连接的顶点索引。
    • nextarc:指向下一个相邻边的指针(链表结构)。
    • info:存储与边相关的OtherInfo对象。
  5. VerTexType 结构体:表示图中的顶点,包含一个字符串s作为顶点数据。
  6. VNode 结构体:表示图的顶点节点,包含:
    • data:顶点数据,类型为VerTexType
    • firstarc:指向顶点的第一个邻接边的指针。
  7. ALGraph 结构体:定义了一个邻接列表表示的图,包括:
    • verticesAdjList类型的数组,存储所有顶点。
    • vexnum:图中顶点的数量。
    • arcnum:图中边的数量。
  8. QNode 结构体:表示队列中的节点,包含一个整型变量v和一个指向下一个节点的指针next
  9. QueuePtr 类型定义:指向QNode结构体的指针。
  10. LinkQueue 结构体:表示链式队列,包含frontrear指针,分别指向队列的头部和尾部。

这个头文件提供了图、顶点、边和链式队列的基本数据结构定义,可用于实现图的各种算法,如遍历、搜索等。

#include "pubuse.h"
#define MVNum 100

typedef struct {
	double l; //边的长度
}OtherInfo;

typedef struct ArcNode // 边结点
{ 
	int adjvex; // 边指向顶点的位置
	struct ArcNode* nextarc = nullptr; // 边下一个结点位置
	OtherInfo info; // 边相关信息
}ArcNode; // 边类型

typedef struct 
{
	string s; // 顶点信息
}VerTexType; // 顶点类型

typedef struct VNode // 顶点结点
{
	VerTexType data; // 顶点信息
	struct ArcNode* firstarc; // 顶连接的边
}VNode, AdjList[MVNum]; // 顶点数组

typedef struct 
{
	AdjList vertices; // 顶点数组
	int vexnum, arcnum; // 顶点数和边数
}ALGraph;

// 队列
typedef struct QNode {
	int v; // 顶点位置
	struct QNode* next; // 下一个结点
}QNode, * QueuePtr; // 队列指针

typedef struct {
	QueuePtr front; // 队头指针
	QueuePtr rear; // 队尾指针
}LinkQueue; // 队列

ALGraphAlgo.h C++头文件

ALGraphAlgo.h 是一个C++头文件,它定义了与图数据结构相关的函数。这个文件主要实现了无向图(Undirected Graph,UDG)的创建、获取顶点数据、获取顶点邻接边、遍历(深度优先搜索DFS和广度优先搜索BFS)等功能。

  1. LinkVex 函数用于在图中添加两个顶点之间的边,并保持图的无向性。
  2. CreateUDG 函数从用户输入创建一个无向图,包括读取顶点数、边数以及边的权重信息。
  3. GetVexData 函数获取指定顶点的数据。
  4. GetVexArc 函数显示给定顶点的所有邻接边及其权重。
  5. GetAllVexArc 函数显示图中所有顶点的邻接边及其权重。
  6. DFS 和 useDFS 函数实现了深度优先遍历图。
  7. BFS 和 useBFS 函数实现了广度优先遍历图。
  8. 文件还包含了一些辅助的队列操作函数,如初始化队列、入队、出队和判断队列是否为空。

这些函数使用了简单的邻接表(Adjacency List)来存储图的结构,每个顶点都有一个指向其邻接顶点的链表。

#include "ALGraphDef.h"


// 无向图连接2点
void LinkVex(ALGraph& G, int v1, int v2, double l) {
	// v1顶点连接v2顶点
	if (G.vertices[v1].firstarc == nullptr) {
		G.vertices[v1].firstarc = new ArcNode;
		G.vertices[v1].firstarc->adjvex = v2;
		G.vertices[v1].firstarc->info.l = l;
	}
	else {
		ArcNode* p1 = G.vertices[v1].firstarc;
		if (p1->adjvex == v2) {
			cout << "两顶点已连接" << endl;
			return;
		}
		while (p1->nextarc) {
			if (p1->nextarc->adjvex == v2) {
				cout << "两顶点已连接" << endl;
				return;
			}
			p1 = p1->nextarc;
		}
		ArcNode* pp1 = new ArcNode;
		pp1->adjvex = v2;
		pp1->info.l = l;
		p1->nextarc = pp1;
	}
	
	// v2顶点连接v1顶点
	if (G.vertices[v2].firstarc == nullptr) {
		G.vertices[v2].firstarc = new ArcNode;
		G.vertices[v2].firstarc->adjvex = v1;
		G.vertices[v2].firstarc->info.l = l;
	}
	else {
		ArcNode* p2 = G.vertices[v2].firstarc;
		if (p2->adjvex == v1) {
			cout << "两顶点已连接" << endl;
			return;
		}
		while (p2->nextarc) {
			if (p2->nextarc->adjvex == v1) {
				cout << "两顶点已连接" << endl;
				return;
			}
			p2 = p2->nextarc;
		}
		ArcNode* pp2 = new ArcNode;
		pp2->adjvex = v1;
		pp2->info.l = l;
		p2->nextarc = pp2;
	}
}


// 采用邻接表表示法创建无向图
Status CreateUDG(ALGraph& G) {
	cout << "输入总顶点数和总边数,用空格隔开:";
	cin >> G.vexnum >> G.arcnum;
	cin.clear();
	cin.ignore();
	if (G.vexnum > MVNum || G.vexnum < 0) return ERROR;
	for (int i = 0; i < G.vexnum; i++) {
		cout << "输入序号为" << i + 1 << "的顶点值:";
		getline(cin, G.vertices[i].data.s); //输人顶点值
		G.vertices[i].firstarc = nullptr;
	}
	cout << "----------------------" << endl;
	cout << "边的信息包括:边连接2个顶点的序号,和边的长度。用空格隔开" << endl;
	cout << "比如:1 3 2.3  表示,该边连接序号为1和3的顶点,长度为2.3" << endl;
	for (int k = 0; k < G.arcnum; k++) {
		cout << "输入第" << k + 1 << "条边的信息:";
		int v1, v2;
		double l;
		cin >> v1 >> v2 >> l;
		v1 -= 1;
		v2 -= 1;
		if (l < 0 || v1 < 0 || v2 < 0 || v1 > G.vexnum - 1 || v2 > G.vexnum - 1 || cin.fail()) {
			cin.clear();
			cin.ignore();
			return ERROR;
		}
		LinkVex(G, v1, v2, l);
	}
	return OK;
}


// 获取顶点的值
Status GetVexData(ALGraph G) {
	cout << "输入顶点的序号,获取顶点的值:";
	int choice;
	cin >> choice;
	choice -= 1;
	if (choice > G.vexnum - 1 || choice < 0 || cin.fail()) return ERROR;
	cout << "序号为" << choice + 1 << "的顶点的值为:" << G.vertices[choice].data.s << endl;
	return OK;
}

// 获取顶点的邻接点
Status GetVexArc(ALGraph G) {
	cout << "输出:值(序号)----边的长度---->" << endl;
	cout << "获取顶点的邻接点,输入顶点的序号:";
	int choice;
	cin >> choice;
	choice -= 1;
	if (choice > G.vexnum - 1 || choice < 0 || cin.fail()) return ERROR;
	ArcNode* p = G.vertices[choice].firstarc;
	cout << G.vertices[choice].data.s << "(" << choice + 1 << ")";
	while (p)
	{
		cout << "----" << p->info.l << "---->";
		cout << G.vertices[p->adjvex].data.s << "(" << p->adjvex + 1 << ")";
		p = p->nextarc;
	}
	cout << endl;
	return OK;
}
// 整体输出邻接表
Status GetAllVexArc(ALGraph G) {
	cout << "输出:值(序号)----边的长度---->" << endl;
	for (int i = 0; i < G.vexnum; i++) {
		ArcNode* p = G.vertices[i].firstarc;
		cout << G.vertices[i].data.s << "(" << i + 1 << ")";
		while (p)
		{
			cout << "----" << p->info.l << "---->";
			cout << G.vertices[p->adjvex].data.s << "(" << p->adjvex + 1 << ")";
			p = p->nextarc;
		}
		cout << endl;
	}
	return OK;
}

bool visited[MVNum];
// 递归深度优先遍历算法
void DFS(ALGraph G, int v) {
	if (v < 0 || v >= G.vexnum) {
		cout << "无此顶点" << endl;
		return;
	}
	cout << G.vertices[v].data.s << "(" << v + 1 << ")    ";
	visited[v] = true;
	ArcNode* p = G.vertices[v].firstarc;
	while (p)
	{
		if (!visited[p->adjvex]) {
			DFS(G, p->adjvex);
		}
		p = p->nextarc;
	}
}
// 使用递归深度优先遍历算法
Status useDFS(ALGraph G) {
	for (int i = 0; i < MVNum; i++) visited[i] = false;
	cout << "输出:值(序号)……" << endl;
	cout << "对图进行深度优先递归遍历,输入开始顶点的序号:";
	int choice;
	cin >> choice;
	choice -= 1;
	if (choice > G.vexnum - 1 || choice < 0 || cin.fail()) return ERROR;
	DFS(G, choice);
	cout << endl;
	return OK;
}

……具体看看绑定的资源

C++代码文件ALGraphUse.cpp 

这个C++代码文件(ALGraphUse.cpp)实现了一个基于命令行的图形数据结构交互式应用。它包括以下功能:

  1. 创建无向图(UDG)
  2. 获取图中顶点的数据
  3. 获取图中顶点的邻接边
  4. 深度优先遍历图
  5. 广度优先遍历图
  6. 显示所有顶点及其邻接边

用户通过菜单选择操作,程序使用ALGraphAlgo.h头文件中定义的数据结构和算法。程序在每个操作后暂停,等待用户确认(使用system("pause")),并在完成或出错时清除屏幕重绘菜单。

#include "ALGraphAlgo.h"

void ShowMenu() {
    cout << "========= 图的实现及应用 =========" << endl;
    cout << "1. 采用邻接表表示法创建无向图G" << endl;
    cout << "2. 获取顶点的值" << endl;
    cout << "3. 获取顶点的邻接点" << endl;
    cout << "4. 自选顶点,对图进行深度优先递归遍历" << endl;
    cout << "5. 自选顶点,对图进行广度优先非递归遍历" << endl;
    cout << "6. 整体输出邻接表" << endl;
    cout << "0. 退出" << endl;
    cout << "请输入你的选择:";
}
void ExitEnter() {
    cout << "-------------------------------" << endl;
    system("pause");
    system("cls");
}

int main() {
    ALGraph G;
    int numF = 6; //菜单选项数量
    int choice;
    do {
        ShowMenu();
        cin >> choice;
        while (choice < 0 || choice>numF || cin.fail())
        {
            system("cls");
            cin.clear();
            cin.ignore();
            ShowMenu();
            cin >> choice;
        }

        switch (choice) {
        case 1: {
            // 采用邻接表表示法创建无向图G
            system("cls");
            if (CreateUDG(G)) cout << "\n无向图创建成功!" << endl;
            else cout << "\n无向图创建失败,请重新尝试" << endl;
            ExitEnter();
            break;
        }
        case 2: {
            // 获取顶点的值
            system("cls");
            if (GetVexData(G)) cout << "\n获取顶点的值成功!" << endl;
            else cout << "\n失败,请重新尝试" << endl;
            ExitEnter();
            break;
        }
        case 3: {
            // 获取顶点的邻接点
            system("cls");
            if (GetVexArc(G)) cout << "\n获取顶点的邻接点成功!" << endl;
            else cout << "\n失败,请重新尝试" << endl;
            ExitEnter();
            break;
        }
        case 4: {
            // 自选顶点,对图进行深度优先递归遍历
            system("cls");
            if (useDFS(G)) cout << "\n对图进行深度优先递归遍历成功!" << endl;
            else cout << "\n失败,请重新尝试" << endl;
            ExitEnter();
            break;
        }
        case 5: {
            // 自选顶点,对图进行广度优先非递归遍历
            system("cls");
            if (useBFS(G)) cout << "\n对图进行广度优先非递归遍历成功!" << endl;
            else cout << "\n失败,请重新尝试" << endl;
            ExitEnter();
            break;
        }
        case 6: {
            // 整体输出邻接表
            system("cls");
            GetAllVexArc(G);
            ExitEnter();
            break;
        }
        case 0: {
            cout << "-------------------------------" << endl;
            cout << "感谢使用,再见!" << endl;
            break;
        }
        default:
            system("cls");
            cout << "输入无效,请重新选择!" << endl;
            break;
        }
    } while (choice != 0);
    return 0;
}

结语

希望你能通过本篇博客,更好理解数据结构——图。

最后,使用愉快!

  • 53
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构是计算机科学中研究数据组织、存储和管理方式的一门学科。它关注如何高效地组织和使用数据,以及设计和实现相关的算法。数据结构是计算机程序的基础,它能够影响程序的性能和效率。 C语言是一种功能强大的编程语言,广泛应用于系统级编程和嵌入式系统开发。由于其底层语言特性和灵活的语法,C语言非常适合于处理和操作数据结构。 C语言提供了针对数据结构的一些基本概念和操作方式。例如,可以使用结构体来定义自定义的数据类型,结构体可以包含多个不同类型的变量。这种方式可以用来表示和组织复杂的数据结构,比如链表、树等。 此外,C语言还提供了一些对数据结构进行操作的函数和库。例如,可以使用指针来操作链表和树等数据结构,通过指针的灵活性,能够高效地进行数据的插入、删除和查找等操作。 在程序设计中,数据结构的选择和设计是非常重要的。不同的数据结构适用于不同的场景和问题。在使用C语言进行程序设计时,我们需要根据实际需求选择合适的数据结构,并合理设计和实现相应的算法,以提高程序的性能和效率。 总结而言,数据结构与程序设计是密切相关的。C语言提供了丰富的功能和灵活的语法,使得我们能够方便地处理和操作各种数据结构。通过合理的数据结构选择和算法设计,我们能够编写出高效、可靠的程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值