算法与数据结构课设(有向图,无向图,有向网,无向网)
数据结构中有向图和无向图的c语言实现
#include<iostream.h>
#include<malloc.h>
#define M 50
typedef char vextype;//顶点数据类型char
typedef struct node //定义表结点类型
{
int adjvex;//邻接点域
struct node *link;//指针域
}
cout<<"以(0,0)为输入结束符"<<endl;
cout<<"输入一条边依附的两个顶点序号:";
cin>>i>>j;
while((i>0)&&(j>0))//输入的(i,j)为(0,0)作为结束符号
{
p=(edgenode*)malloc(sizeof(edgenode));//生成邻接序号为j的表结点
break;
default:cout<<"输入错误,程序结束!"<<endl;
return;
}
cout<<endl;
cout<<"是否继续?(输入n结束,输入y有效!)"<<endl;
cin>>flag;
}
cout<<"程序结束,再见!"<<endl;
}
}edgenode,*Edgenode;
typedef struct headnode//定义表头结点类型
{
vextype vexdata;//顶点数据域
算法与数据结构大纲
算法与数据结构大纲一、课程简介算法与数据结构是计算机科学中的核心基础课程,旨在介绍算法设计和数据结构的基本概念、原理和方法,培养学生的算法思维和问题解决能力。
二、教学目标1. 了解算法与数据结构的基本概念和原理;2. 掌握常见的数据结构及其操作;3. 学习常见的算法设计策略和分析方法;4. 能够运用所学知识解决实际问题。
三、教学内容1. 算法基础- 算法的概念和特征- 算法的表示方法- 算法的分析:时间复杂度和空间复杂度2. 数据结构基础- 数据结构的概念和分类- 抽象数据类型- 数据结构的操作和实现3. 线性结构- 数组- 链表- 栈和队列4. 树状结构- 树的概念和基本操作- 二叉树- 二叉搜索树- 平衡二叉树5. 图状结构- 图的概念和基本操作- 图的存储和表示- 图的遍历6. 排序算法- 插入排序- 选择排序- 冒泡排序- 快速排序- 归并排序7. 查找算法- 顺序查找- 二分查找- 哈希查找8. 算法设计策略- 分治法- 动态规划法- 回溯法- 贪心算法四、教学方法1. 理论讲解:通过课堂讲解,介绍算法与数据结构的基本概念、原理和方法;2. 编程实践:通过编程练习,让学生掌握数据结构的实现和算法的应用;3. 案例分析:通过实际问题的解决,让学生学会运用所学知识解决实际问题;4. 小组讨论:通过小组讨论,培养学生的团队合作和问题解决能力。
五、考核方式1. 平时作业:包括课后作业、编程练习和课堂表现等;2. 期中考试:考核学生对前半部分教学内容的掌握程度;3. 期末考试:考核学生对整个课程内容的掌握程度。
六、教学资料1. 教材:《算法与数据结构》(教材名称),(作者)著,(出版社)出版;2. 参考资料:《数据结构与算法分析》(参考书名称),(作者)著,(出版社)出版。
七、教学设备1. 计算机实验室;2. 投影仪;3. 编程软件。
《数据结构》教案(精华版)
《数据结构》教案(精华版)《数据结构》教案(精华版)前言数据结构是计算机学科中的重要基础课程,它涉及到数据的存储、组织和管理。
本教案旨在帮助学生掌握数据结构的基本概念、算法和应用,提高其解决实际问题的能力。
第一章:引言在本章中,我们将介绍数据结构的基本概念和重要性。
学生将了解到数据结构在计算机科学中的作用,以及为什么学习数据结构对于他们的职业发展至关重要。
1.1 数据结构的定义数据结构是一种组织和存储数据的方式,它涉及到数据元素之间的关系,以及对这些关系的操作。
1.2 数据结构的分类数据结构可以分为线性结构和非线性结构。
线性结构中的数据元素之间存在一个明确的顺序关系,而非线性结构中的数据元素之间没有固定的顺序关系。
1.3 数据结构的应用数据结构在计算机科学中有广泛的应用。
例如,在数据库管理系统中,数据结构被用来组织和管理大量的数据;在图形图像处理中,数据结构被用来存储和操作图像数据。
第二章:线性结构本章将介绍线性结构,包括线性表、栈和队列。
学生将学习这些线性结构的定义、实现和应用。
2.1 线性表线性表是一种最简单的数据结构,它由一组数据元素组成,这些元素按照线性的顺序存储。
2.2 栈栈是一种特殊的线性表,它具有“先进后出”的特点。
学生将学习栈的定义、实现和常见应用。
2.3 队列队列是另一种特殊的线性表,它具有“先进先出”的特点。
学生将学习队列的定义、实现和应用。
第三章:树结构本章将介绍树结构,包括二叉树、搜索树和平衡树。
学生将学习这些树结构的定义、实现和应用。
3.1 二叉树二叉树是一种常见的树结构,它的每个节点最多有两个子节点。
学生将学习二叉树的定义、实现和遍历算法。
3.2 搜索树搜索树是一种特殊的二叉树,它的每个节点都符合一定的大小关系。
学生将学习搜索树的定义、实现和查找算法。
3.3 平衡树平衡树是一种自平衡的二叉树,它可以保持树的高度平衡。
学生将学习平衡树的定义、实现和平衡算法。
第四章:图结构本章将介绍图结构,包括无向图和有向图。
数据结构课设——有向图的深度、广度优先遍历及拓扑排序
数据结构课设——有向图的深度、⼴度优先遍历及拓扑排序任务:给定⼀个有向图,实现图的深度优先, ⼴度优先遍历算法,拓扑有序序列,并输出相关结果。
功能要求:输⼊图的基本信息,并建⽴图存储结构(有相应提⽰),输出遍历序列,然后进⾏拓扑排序,并测试该图是否为有向⽆环图,并输出拓扑序列。
按照惯例,先上代码,注释超详细:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#pragma warning(disable:4996)#define Max 20//定义数组元素最⼤个数(顶点最⼤个数)typedef struct node//边表结点{int adjvex;//该边所指向结点对应的下标struct node* next;//该边所指向下⼀个结点的指针}eNode;typedef struct headnode//顶点表结点{int in;//顶点⼊度char vertex;//顶点数据eNode* firstedge;//指向第⼀条边的指针,边表头指针}hNode;typedef struct//邻接表(图){hNode adjlist[Max];//以数组的形式存储int n, e;//顶点数,边数}linkG;//以邻接表的存储结构创建图linkG* creat(linkG* g){int i, k;eNode* s;//边表结点int n1, e1;char ch;g = (linkG*)malloc(sizeof(linkG));//申请结点空间printf("请输⼊顶点数和边数:");scanf("%d%d", &n1, &e1);g->n = n1;g->e = e1;printf("顶点数:%d 边数:%d\n", g->n, g->e);printf("请输⼊顶点信息(字母):");getchar();//因为接下来要输⼊字符串,所以getchar⽤于承接上⼀条命令的结束符for (i = 0; i < n1; i++){scanf("%c", &ch);g->adjlist[i].vertex = ch;//获得该顶点数据g->adjlist[i].firstedge = NULL;//第⼀条边设为空}printf("\n打印顶点下标及顶点数据:\n");for (i = 0; i < g->n; i++)//循环打印顶点下标及顶点数据{printf("顶点下标:%d 顶点数据:%c\n", i, g->adjlist[i].vertex);}getchar();int i1, j1;//相连接的两个顶点序号for (k = 0; k < e1; k++)//建⽴边表{printf("请输⼊对<i,j>(空格分隔):");scanf("%d%d", &i1, &j1);s = (eNode*)malloc(sizeof(eNode));//申请边结点空间s->adjvex = j1;//边所指向结点的位置,下标为j1s->next = g->adjlist[i1].firstedge;//将当前s的指针指向当前顶点上指向的结点g->adjlist[i1].firstedge = s;//将当前顶点的指针指向s}return g;//返回指针g}int visited[Max];//标记是否访问void DFS(linkG* g, int i)//深度优先遍历{eNode* p;printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已访问过的顶点visited值改为1p = g->adjlist[i].firstedge;//p指向顶点i的第⼀条边while (p)//p不为NULL时(边存在){if (visited[p->adjvex] != 1)//如果没有被访问DFS(g, p->adjvex);//递归}p = p->next;//p指向下⼀个结点}}void DFSTravel(linkG* g)//遍历⾮连通图{int i;printf("深度优先遍历;\n");//printf("%d\n",g->n);for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问{DFS(g, i);//调⽤DFS函数}}}void BFS(linkG* g, int i)//⼴度优先遍历{int j;eNode* p;int q[Max], front = 0, rear = 0;//建⽴顺序队列⽤来存储,并初始化printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已经访问过的改成1rear = (rear + 1) % Max;//普通顺序队列的话,这⾥是rear++q[rear] = i;//当前顶点(下标)队尾进队while (front != rear)//队列⾮空{front = (front + 1) % Max;//循环队列,顶点出队j = q[front];p = g->adjlist[j].firstedge;//p指向出队顶点j的第⼀条边while (p != NULL){if (visited[p->adjvex] == 0)//如果未被访问{printf("%c ", g->adjlist[p->adjvex].vertex);visited[p->adjvex] = 1;//将该顶点标记数组值改为1rear = (rear + 1) % Max;//循环队列q[rear] = p->adjvex;//该顶点进队}p = p->next;//指向下⼀个结点}}}void BFSTravel(linkG* g)//遍历⾮连通图{int i;printf("⼴度优先遍历:\n");for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问过{BFS(g, i);//调⽤BFS函数}}}//因为拓扑排序要求⼊度为0,所以需要先求出每个顶点的⼊度void inDegree(linkG* g)//求图顶点⼊度{eNode* p;int i;for (i = 0; i < g->n; i++)//循环将顶点⼊度初始化为0{g->adjlist[i].in = 0;}for (i = 0; i < g->n; i++)//循环每个顶点{p = g->adjlist[i].firstedge;//获取第i个链表第1个边结点指针while (p != NULL)///当p不为空(边存在){g->adjlist[p->adjvex].in++;//该边终点结点⼊度+1p = p->next;//p指向下⼀个边结点}printf("顶点%c的⼊度为:%d\n", g->adjlist[i].vertex, g->adjlist[i].in);}void topo_sort(linkG *g)//拓扑排序{eNode* p;int i, k, gettop;int top = 0;//⽤于栈指针的下标索引int count = 0;//⽤于统计输出顶点的个数int* stack=(int *)malloc(g->n*sizeof(int));//⽤于存储⼊度为0的顶点for (i=0;i<g->n;i++)//第⼀次搜索⼊度为0的顶点{if (g->adjlist[i].in==0){stack[++top] = i;//将⼊度为0的顶点进栈}}while (top!=0)//当栈不为空时{gettop = stack[top--];//出栈,并保存栈顶元素(下标)printf("%c ",g->adjlist[gettop].vertex);count++;//统计顶点//接下来是将邻接点的⼊度减⼀,并判断该点⼊度是否为0p = g->adjlist[gettop].firstedge;//p指向该顶点的第⼀条边的指针while (p)//当p不为空时{k = p->adjvex;//相连接的顶点(下标)g->adjlist[k].in--;//该顶点⼊度减⼀if (g->adjlist[k].in==0){stack[++top] = k;//如果⼊度为0,则进栈}p = p->next;//指向下⼀条边}}if (count<g->n)//如果输出的顶点数少于总顶点数,则表⽰有环{printf("\n有回路!\n");}free(stack);//释放空间}void menu()//菜单{system("cls");//清屏函数printf("************************************************\n");printf("* 1.建⽴图 *\n");printf("* 2.深度优先遍历 *\n");printf("* 3.⼴度优先遍历 *\n");printf("* 4.求出顶点⼊度 *\n");printf("* 5.拓扑排序 *\n");printf("* 6.退出 *\n");printf("************************************************\n");}int main(){linkG* g = NULL;int c;while (1){menu();printf("请选择:");scanf("%d", &c);switch (c){case1:g = creat(g); system("pause");break;case2:DFSTravel(g); system("pause");break;case3:BFSTravel(g); system("pause");break;case4:inDegree(g); system("pause");break;case5:topo_sort(g); system("pause");break;case6:exit(0);break;}}return0;}实验⽤图:运⾏结果:关于深度优先遍历 a.从图中某个顶点v 出发,访问v 。
有向图与无向图的性质与算法
有向图与无向图的性质与算法1. 引言在图论中,有向图和无向图是两种最基本的图模型。
它们在表达和解决各类实际问题时具有重要的应用价值。
本文将介绍有向图和无向图的性质以及相关算法,以便读者对其有更深入的理解。
2. 有向图的性质有向图是由一系列顶点和有方向的边组成的图模型。
以下是有向图的几个重要性质:2.1 有向边的方向性与无向图不同,有向图中的边是有方向的,它们从一个顶点指向另一个顶点。
这种方向性在描述一些实际问题时非常有用,比如描述物流运输的路径。
2.2 顶点的入度和出度有向图中的每个顶点都有一个入度和一个出度。
顶点的入度是指指向该顶点的边的数量,而出度是指从该顶点出发的边的数量。
通过计算入度和出度,我们可以了解顶点在图中的连接情况。
2.3 有向环和拓扑排序有向图中存在一个重要的概念,即有向环。
有向环是指从一个顶点出发,经过若干个有向边后又回到该顶点的路径。
有向环在一些问题的分析和解决中具有特殊意义。
而拓扑排序是一种常用的对有向无环图进行排序的方法,它可以按照顶点之间的依赖关系进行排序。
3. 无向图的性质无向图是由一系列顶点和无方向的边组成的图模型。
以下是无向图的几个重要性质:3.1 无向边的无方向性与有向图不同,无向图中的边是无方向的,它们连接着两个顶点,代表了两个顶点之间的关系。
无向图可以用来表示一些没有方向性的问题,比如社交网络中的好友关系。
3.2 顶点的度数无向图中的顶点的度数是指与该顶点相连的边的数量。
顶点的度数越高,说明该顶点在图中的重要性越高,具有更多的连接关系。
3.3 联通性和连通分量无向图中有一个关键性质,即联通性。
若两个顶点之间存在一条连接它们的路径,则称这两个顶点是连通的。
连通分量则是将图中所有连通的顶点分为若干个集合,每个集合内的顶点都是连通的。
4. 算法与应用4.1 有向图的最短路径算法有向图中的最短路径算法是指寻找从一个顶点到另一个顶点的最短路径的方法。
其中,Dijkstra算法和Bellman-Ford算法是常用的有向图最短路径算法。
数据结构与算法-图结构
数据结构与算法-图结构数据结构-图图是⼀种数据结构,其中结点可以具有零个或者多个相邻元素。
两个结点的连接称为边,结点也可以称为顶点顶点边路径⽆向图有向图带权图邻接矩阵(⼆维数组)分为两部分:V和E集合,其中,V是顶点,E是边。
因此,⽤⼀个⼀维存放图中所有顶点数据;⽤⼀个⼆维数组存放顶点间关系(边或弧)的数据,这个⼆维数组称为邻接。
邻接表(链表)邻接表,存储⽅法跟树的孩⼦链表⽰法相类似,是⼀种顺序分配和链式分配相结合的。
如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。
所谓遍历,其实就是对结点的访问。
⼀个图的结点有很多,如何全部访问到,需要制定策略,⼀般是深度优先遍历与⼴度优先遍历深度优先遍历(Depth First Search)从初始访问结点出发,⾸先访问第⼀个邻接结点然后再以这个被访问的邻接结点作为初始结点,访问其第⼀个邻接结点即每次都在访问完当前结点后⾸先访问当前结点的第⼀个邻接结点深度优先遍历是⼀个递归的过程访问初始结点v,并标记v为已经访问查找结点v的第⼀个邻接结点w若w存在,则继续,不存在则回到第⼀步,从v的下⼀个结点继续若w未被访问,则对其进⾏深度优先遍历递归查找结点v的w邻接结点的下⼀个邻接结点,重新上述过程⼴度优先遍历(Broad First Search)类似于分层搜索的过程,⼴度优先遍历需求使⽤⼀个队列以保持访问过的结点的顺序,以便按这个顺序来访问这些结点的邻接结点访问初始结点v并标记结点v为已经访问结点v⼊队列队列为⾮空时,则继续执⾏,否则算法结束出队列,取出队列头结点u查找结点u的第⼀个邻接结点w若结点u的邻接结点w不存在,则回到上述步骤,否则继续进⾏若结点w未被访问,则访问结点w并标记为已经访问结点w⼊队列查找结点u的继邻接结点w,转到上述步骤package cn.imut;import java.util.ArrayList;import java.util.Arrays;import java.util.LinkedList;public class Graph {private ArrayList<String> vertexList; //存储顶点集合private int[][] edges; //存储图对应的邻接矩阵private int numOfEdges; //表⽰边的数⽬private boolean[] isVisited; //记录某个结点是否被访问public static void main(String[] args) {//测试⼀把图是否创建okint n = 8; //结点的个数//String Vertexs[] = {"A", "B", "C", "D", "E"};String Vertexs[] = {"1", "2", "3", "4", "5", "6", "7", "8"};//创建图对象Graph graph = new Graph(n);//循环的添加顶点for(String vertex: Vertexs) {graph.insertVertex(vertex);}//添加边//A-B A-C B-C B-D B-E// graph.insertEdge(0, 1, 1); // A-B// graph.insertEdge(0, 2, 1); //// graph.insertEdge(1, 2, 1); //// graph.insertEdge(1, 3, 1); //// graph.insertEdge(1, 4, 1); ////更新边的关系graph.insertEdge(0, 1, 1);graph.insertEdge(0, 2, 1);graph.insertEdge(1, 3, 1);graph.insertEdge(1, 4, 1);graph.insertEdge(3, 7, 1);graph.insertEdge(4, 7, 1);graph.insertEdge(2, 5, 1);graph.insertEdge(2, 6, 1);graph.insertEdge(5, 6, 1);//显⽰⼀把邻结矩阵graph.showGraph();//测试⼀把,我们的dfs遍历是否okSystem.out.println("深度遍历");graph.dfs(); // A->B->C->D->E [1->2->4->8->5->3->6->7]// System.out.println();System.out.println("⼴度优先!");graph.bfs(); // A->B->C->D-E [1->2->3->4->5->6->7->8]}//构造器public Graph(int n) {//初始化矩阵和vertexListedges = new int[n][n];vertexList = new ArrayList<String>(n);numOfEdges = 0;numOfEdges = 0;}/*** 得到第⼀个邻接结点的下标w* @param index 结点* @return 若存在则返回下标,否则返回 -1*/public int getFirstNeighbor(int index) {for(int j = 0; j < vertexList.size(); j++) {if(edges[index][j] > 0) {return j;}}return -1;}/*** 根据前⼀个邻接结点的下标来获取下⼀个邻接结点 * @param v1* @param v2* @return 返回下标或者-1*/public int getNextNeighbor(int v1, int v2) {for(int j = v2 + 1; j < vertexList.size(); j++) {if(edges[v1][j] > 0) {return j;}}return -1;}/**** @param isVisited* @param i 第⼀次是0*/private void dfs(boolean[] isVisited, int i) {//⾸先我们访问该结点,输出System.out.print(getValueByIndex(i) + "->");//将结点设置为已经访问isVisited[i] = true;//查找结点i的第⼀个邻接结点wint w = getFirstNeighbor(i);while(w != -1) {//说明有if(!isVisited[w]) {dfs(isVisited, w);}//如果w结点已经被访问过w = getNextNeighbor(i, w);}}//dfs重载,遍历所有的结点,进⾏dfspublic void dfs() {isVisited = new boolean[vertexList.size()];//遍历所有的结点,进⾏dfs[回溯]for(int i = 0; i < getNumOfVertex(); i++) {if(!isVisited[i]) {dfs(isVisited, i);}}}/**** @param isVisited* @param i*/private void bfs(boolean[] isVisited, int i) {int u ; // 表⽰队列的头结点对应下标int w ; // 邻接结点w//队列,记录结点访问的顺序LinkedList queue = new LinkedList();//访问结点,输出结点信息System.out.print(getValueByIndex(i) + "=>");System.out.print(getValueByIndex(i) + "=>");//标记为已访问isVisited[i] = true;//将结点加⼊队列queue.addLast(i);while( !queue.isEmpty()) {//取出队列的头结点下标u = (Integer)queue.removeFirst();//得到第⼀个邻接结点的下标 ww = getFirstNeighbor(u);while(w != -1) {//找到//是否访问过if(!isVisited[w]) {System.out.print(getValueByIndex(w) + "=>");//标记已经访问isVisited[w] = true;//⼊队queue.addLast(w);}//以u为前驱点,找w后⾯的下⼀个邻结点w = getNextNeighbor(u, w); //体现出我们的⼴度优先 }}}//遍历所有结点public void bfs() {isVisited = new boolean[vertexList.size()];for (int i1 = 0; i1 < getNumOfVertex(); i1++) {if(!isVisited[i1]) {bfs(isVisited, i1);}}}//返回结点个数public int getNumOfVertex() {return vertexList.size();}//显⽰图对应的矩阵public void showGraph() {for (int[] ints : edges) {System.out.println(Arrays.toString(ints));}}//得到边的数⽬public int getNumOfEdges() {return numOfEdges;}//返回结点i(下标)对应的数据public String getValueByIndex(int i) {return vertexList.get(i);}//返回v1,v2的权值public int getWeight(int v1, int v2) {return edges[v1][v2];}//插⼊结点public void insertVertex(String vertex) {vertexList.add(vertex);}/*** 添加边* @param v1 表⽰点的下标:第⼏个顶点* @param v2 第⼆个结点对应的下标* @param weight 表⽰*/public void insertEdge(int v1, int v2, int weight) {public void insertEdge(int v1, int v2, int weight) {edges[v1][v2] = weight;edges[v2][v1] = weight;numOfEdges++;}}深度优先算法遍历顺序:1 -> 2 -> 4 -> 8 -> 5 -> 3 -> 6 -> 7⼴度优先算法遍历顺序:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8。
数据结构与算法课程设计报告---图的算法实现
数据结构与算法课程设计报告课程设计题目:图的算法实现专业班级:信息与计算科学1002班目录摘要 (1)1、引言 (1)2、需求分析 (1)3、概要设计 (2)4、详细设计 (4)5、程序设计 (10)6、运行结果 (18)7、总结体会 (19)摘要(题目): 图的算法实现实验内容图的算法实现问题描述:(1)将图的信息建立文件;(2)从文件读入图的信息,建立邻接矩阵和邻接表;(3)实现Prim、Kruskal、Dijkstra和拓扑排序算法。
关键字:邻接矩阵、Dijkstra和拓扑排序算法1.引言本次数据结构课程设计共完成图的存储结构的建立、Prim、Kruskal、Dijkstra 和拓扑排序算法等问题。
通过本次课程设计,可以巩固和加深对数据结构的理解,通过上机和程序调试,加深对课本知识的理解和熟练实践操作。
(1)通过本课程的学习,能够熟练掌握数据结构中图的几种基本操作;(2)能针对给定题目,选择相应的数据结构,分析并设计算法,进而给出问题的正确求解过程并编写代码实现。
使用语言:CPrim算法思想:从连通网N={V,E}中的某一顶点v0出发,选择与它关联的具有最小权值的边(v0,v),将其顶点加入到生成树的顶点集合V中。
以后每一步从一个顶点在V中,而另一个顶点不在V中的各条边中选择权值最小的边(u,v),把它的顶点加入到集合V中。
如此继续下去,直到网中的所有顶点都加入到生成树顶点集合V中为止。
拓扑排序算法思想:1、从有向图中选取一个没有前驱的顶点,并输出之;2、从有向图中删去此顶点以及所有以它为尾的弧;重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止。
没有前驱-- 入度为零,删除顶点及以它为尾的弧-- 弧头顶点的入度减1。
2.需求分析1、通过键盘输入建立一个新的有向带权图,建立相应的文件;2、对建立的有向带权图进行处理,要求具有如下功能:(1)用邻接矩阵和邻接表的存储结构输出该有向带权图,并生成相应的输出结果;(2)用Prim、Kruskal算法实现对图的最小生成树的求解,并输出相应的输出结果;(3)用Dijkstra算法实现对图中从某个源点到其余各顶点的最短路径的求解,并输出相应的输出结果;(4)实现该图的拓扑排序算法。
数据结构与算法学习知识网络图解
数据结构与算法学习知识网络图解在计算机科学与软件工程领域中,数据结构与算法是构建高效的软件系统和解决复杂问题的基础。
掌握数据结构与算法的知识是每个计算机专业人员的必备技能。
但是,由于其抽象性和复杂性,学习数据结构与算法常常被认为是困难的。
为了帮助读者更好地理解和掌握这一领域的知识,本文将通过图解的方式,简洁明了地呈现数据结构与算法的核心概念和关系。
一、数据结构的基础概念1. 线性结构线性结构是数据元素之间存在一对一的关系,线性表是其中最常见的一种形式。
线性表可以分为顺序存储结构和链式存储结构两种类型。
其中,顺序存储结构使用连续的内存空间存储数据元素,而链式存储结构使用指针将数据元素链接起来。
2. 树形结构树形结构是数据元素之间存在一对多的关系,树是其中最常见的一种形式。
树由根节点、分支节点和叶节点组成,分支节点连接多个子节点,叶节点没有子节点。
树可以进一步分为二叉树、平衡二叉树和二叉查找树等类型。
3. 图状结构图状结构是数据元素之间存在多对多的关系,图是其中最常见的一种形式。
图由顶点和边组成,边表示顶点之间的连接关系。
图可以分为有向图和无向图两种类型,有向图中的边具有方向性,而无向图中的边没有方向性。
二、常见数据结构的应用场景1. 数组数组是最简单的数据结构之一,可以用于存储同类型的元素,并通过下标进行访问。
数组在实现矩阵、向量和字符串等数据结构时被广泛应用。
2. 链表链表是一种线性结构,可以动态地分配内存空间。
链表在插入和删除元素时具有较好的性能,因此在实现栈、队列和哈希表等数据结构时常常使用链表。
3. 栈栈是一种先进后出(LIFO)的数据结构,可以用于实现函数调用、表达式求值和括号匹配等场景。
4. 队列队列是一种先进先出(FIFO)的数据结构,可以用于实现进程调度、消息传递和缓存管理等应用。
5. 树树可以用于构建文件系统、数据库索引和组织结构等复杂的数据结构。
6. 图图可以用于社交网络分析、路径规划和网络拓扑结构分析等领域。
数据结构ppt课件
04
树与二叉树
树的定义与基本操作
01
树的定义
树是一种非线性数据结构,由 节点和边组成,具有层次关系
。
02
树的基本术语
根节点、子节点、父节点、兄 弟节点、叶子节点等。
03
树的基本操作
创建树、插入节点、删除节点 、查找节点等。
二叉树的定义与性质
二叉树的定义
二叉树是一种特殊的树,每个节点最多有两个子节点,分别称为左子节点和右子节点。
判断队列是否为空(IsEmpty)
检查队列中是否还有元素。
队列的应用举例
打印任务队列
在打印机中,多个打印任务按照它们到达的 顺序排队等待打印。
缓冲区
在网络传输或文件IO操作中,使用队列作为 缓冲区来暂存数据。
CPU任务调度
操作系统使用队列来管理等待CPU处理的任 务。
广度优先搜索(BFS)
在图或树等数据结构中,使用队列来实现广 度优先搜索算法。
时间复杂度
平均时间复杂度和最坏时 间复杂度均为O(n)。
适用场景
适用于数据量较小或数据 无序的情况。
查找算法设计之二分查找法
算法思想
在有序数组中,取中间元素与目标元素比较,若相等则查找成功;若目标元素小于中间元 素,则在左半部分继续查找;若目标元素大于中间元素,则在右半部分继续查找。
时间复杂度
平均时间复杂度和最坏时间复杂度均为O(log n)。
(或权值),否则为0。
邻接矩阵的性质
对于无向图,邻接矩阵是对称的 ;对于有向图,邻接矩阵不一定
对称。
邻接矩阵的优缺点
优点是直观、简单、方便检查任 意一对顶点间是否存在边;缺点 是空间复杂度高,对于稀疏图浪
《数据结构与算法》AOE网及关键路径
基本概念:
AOE网:带权的有向图,其中,顶点表示事件,弧表示活 动,权表示活动持续的时间。
关键路径:AOE-网中有些活动可以并行的进行,所以完 成工程的最短时间是从开始点到完成点的最长路径的 长度(这里所说的长度是指路径上各个活动持续时间 之和,不是路径上弧的数目)。路径长度最长的路径 叫做关键路径。
a5=1 7
v9 a8=7
v8 a11=4
a3=5
4
v4 a6=2
5
a9=4 11
v6
7
从ve(0)=0开始向后推.
Ve(j)=Max{ve(i)+dut(〈i,j〉)}
(j=1,2….n-1)
1 求活动最迟发生时间 6
a1=6 v2 a4=1
16v7
a7=9
a10=2 18
v9
0 v1 a2=4
a6=12
4 a5=7 6
el a1 0 0 a2 5 5 a3 0 7 a4 0 7 a5 9 16 a6 23 23 a7 15 15 a8 15 15 a9 5 5 a10 27 27 a11 27 27 a12 35 35 a13 41 41
v5 a8=7
v3 a5=1 7
v8 a11=4
a3=5
6
v4
8 a6=2
a9=4 14
v6
10
从vl(9)=18开始向回推(倒计时)。 Ve(i)=Min{vl(j)- dut(〈i,j〉)}
(j=n-2,n-3,----,0)
例: 对下面的AOE网络,试回答下列问题: ve vl
(1)列出所有的关键路径; (2)完成整个工程至少需要多少时间?
最早发生时间:假设开始点是V1,从V1到Vi的最长的路径 的长度叫做事件Vi的最早发生时间。
(完整版)数据结构详细教案——图
数据结构教案第七章图第7章图【学习目标】1.领会图的类型定义。
2.熟悉图的各种存储结构及其构造算法,了解各种存储结构的特点及其选用原则。
3.熟练掌握图的两种遍历算法。
4.理解各种图的应用问题的算法.【重点和难点】图的应用极为广泛,而且图的各种应用问题的算法都比较经典,因此本章重点在于理解各种图的算法及其应用场合。
【知识点】图的类型定义、图的存储表示、图的深度优先搜索遍历和图的广度优先搜索遍历、无向网的最小生成树、最短路径、拓扑排序、关键路径【学习指南】离散数学中的图论是专门研究图性质的一个数学分支,但图论注重研究图的纯数学性质,而数据结构中对图的讨论则侧重于在计算机中如何表示图以及如何实现图的操作和应用等.图是较线性表和树更为复杂的数据结构,因此和线性表、树不同,虽然在遍历图的同时可以对顶点或弧进行各种操作,但更多图的应用问题如求最小生成树和最短路径等在图论的研究中都早已有了特定算法,在本章中主要是介绍它们在计算机中的具体实现。
这些算法乍一看都比较难,应多对照具体图例的存储结构进行学习。
而图遍历的两种搜索路径和树遍历的两种搜索路径极为相似,应将两者的算法对照学习以便提高学习的效益。
【课前思考】1。
你有没有发现现在的十字路口的交通灯已从过去的一对改为三对,即每个方向的直行、左拐和右拐能否通行都有相应的交通灯指明。
你能否对某个丁字路口的6条通路画出和第一章绪论中介绍的”五叉路口交通管理示意图”相类似的图?2。
如果每次让三条路同时通行,那么从图看出哪些路可以同时通行?同时可通行的路为:(AB,BC,CA),(AB,BC,BA),(AB,AC,CA),(CB,CA,BC)目录第7章图 (1)7.1图的定义和基本术语 (1)7.2图的存储和创建 (2)7.2.1 图的存储表示 (2)7。
2.2 图的创建 (5)7。
3图的遍历 (5)7。
3.1 深度优先搜索 (5)7.3.2 广度优先搜索 (6)7。
4遍历算法的应用 (8)7.4。
算法与数据结构课程设计(有向图,无向图,有向网,无向网)
算法与数据结构课程设计报告系(院):计算机科学学院专业班级:教技1001班*名:***学号:*********指导教师:***设计时间:2012.6.16 - 2012.6.24设计地点:4号楼2号机房目录一、设计方案及实现过程******************第3页二、实现代码***********************************第4页三、测试******************************************第19页四、难点与收获********************************第21页一、设计方案及实现过程这次课程设计要求实现无向图、有向图、无向网以及有向网的一些基本操作以及应用,大体的方案是先进入界面后,选择无向图、有向图、无向网、无向网中的一个,然后创建相应的图或者网,创建好后,在此基础上选择进行相关的操作,具体的函数放在main函数前面,通过多次函数调用已达到具体操作的实现。
流程图如下:进入选择界面1 无向图创建无向图1 创建无向图的邻接矩阵函数调用2 创建无向图的邻接表函数调用3无向图的深度优先遍历函数调用4 无向图的广度优先遍历函数调用5 返回选择主界面2 有向图3 无向网4 有向网5 退出有向图、无向网、有向网的操作和无向图类似,在这里不一一列举。
二、实现代码#include<stdio.h># include <stdlib.h># define maxlen 10# define large 999# define true 1# define false 0# define ok 1# define error 0# define overflow -2# define null 0typedef int status;#include <ctype.h>#include <string.h>#include <queue>#include <stack>#include <process.h>using namespace std;#define MAX_VERTEX_NUM 20#define MAX 1000typedef struct{int a[maxlen],b[maxlen],h[maxlen];char vexs[maxlen];int vexnum,arcnum;int kind;int arcs[maxlen][maxlen];}graph;typedef struct node{int adjvex;int info;struct node *next;}edgenode;typedef struct{int id;char data;edgenode *link;}vexnode;typedef struct{vexnode adjs[maxlen];int vexnum,arcnum;int kind;}adjlist;typedef struct qnode{int data;struct qnode *next;}linkqlist;typedef struct{linkqlist *front;linkqlist *rear;} linkqueue;typedef struct{int stack[maxlen];int top;}stackstru;int cnull=-1;graph g;adjlist adjl;stackstru *t;stackstru *s;linkqueue *q;graph printf_adjmatrix(graph g){int i,j;printf("邻接矩阵:\n");printf("vertex\t");for (i=0;i<g.vexnum;i++) printf("%4c",g.vexs[i]);printf("\n");for(i=0;i<g.vexnum;i++){printf("% 4c \t",g.vexs[i]);for(j=0;j<g.vexnum;j++) printf("%4d",g.arcs[i][j]);printf("\n");}return g;}void create_2(graph g){ //构造有向图int i,j,k,c=0;for (i=0;i<g.vexnum;i++)for(j=0;j<g.vexnum;j++)g.arcs[i][j]=c;for(k=0;k<g.arcnum;k++)g.arcs[g.a[k]-1][g.b[k]-1]=1;printf_adjmatrix(g);}void create_1(graph g){ //构造无向图int i,j,k,c=0;for (i=0;i<g.vexnum;i++)for(j=0;j<g.vexnum;j++)g.arcs[i][j]=c;for(k=0;k<g.arcnum;k++){g.arcs[g.a[k]-1][g.b[k]-1]=1;g.arcs[g.b[k]-1][g.a[k]-1]=1;}printf_adjmatrix(g);}graph create_4(graph g){ //构造有向网int i,j,k,c=999;for (i=0;i<g.vexnum;i++)for(j=0;j<g.vexnum;j++)g.arcs[i][j]=c;for(k=0;k<g.arcnum;k++)g.arcs[g.a[k]-1][g.b[k]-1]=g.h[k];printf_adjmatrix(g);return g;}graph create_3(graph g){ //构造无向网int i,j,k,c=999;for (i=0;i<g.vexnum;i++)for(j=0;j<g.vexnum;j++)g.arcs[i][j]=c;for (k=0;k<g.arcnum;k++){g.arcs[g.a[k]-1][g.b[k]-1]=g.h[k];g.arcs[g.b[k]-1][g.a[k]-1]=g.h[k];}printf_adjmatrix(g);return g;}void creategraph(graph g){switch(g.kind){case 1:create_1(g);break;case 2:create_2(g);break;case 3:create_3(g);break;case 4:create_4(g);break;default:printf("Error\n");}}adjlist createlist (graph g ,adjlist adjl){ //创建邻接表int i;edgenode *p;if(g.kind==1||g.kind==3){//创建有向邻接表for(i=0;i<adjl.arcnum;i++){p=(edgenode*)malloc(sizeof(edgenode));p->adjvex=g.b[i];p->info=g.h[i];p->next=adjl.adjs[g.a[i]-1].link;adjl.adjs[g.a[i]-1].link=p;}}if(g.kind==2||g.kind==4){//创建无向邻接表for(i=0;i<adjl.arcnum;i++){p=(edgenode*)malloc(sizeof(edgenode));p->info=g.h[i];p->adjvex=g.b[i];p->next=adjl.adjs[g.a[i]-1].link;adjl.adjs[g.a[i]-1].link=p;p=(edgenode*)malloc(sizeof(edgenode));p->info=g.h[i];p->adjvex=g.a[i];p->next=adjl.adjs[g.b[i]-1].link;adjl.adjs[g.b[i]-1].link=p;}}printf("邻接表为:\n");for(i=0;i<g.vexnum;i++){printf("[%d,%c]=>",i+1,adjl.adjs[i].data);p=adjl.adjs[i].link;while(p!=null){printf("[%c,%d]-->",adjl.adjs[(p->adjvex)-1].data,p->info);p=p->next;}printf("^\n");}return adjl;}void initqueue(linkqueue *p){ //构造空队列p->front=(linkqlist *)malloc(sizeof(linkqlist));p->rear=p->front;(p->front)->next=null;}status empty(linkqueue *q){ //判断是否为空int v;if(q->front==q->rear) v=true;else v=false;return v;}int addqueue(linkqueue *q,int e){q->rear->next=(linkqlist *)malloc(sizeof(linkqlist));q->rear=q->rear->next;if(!q->rear) return -1;q->rear->data=e;q->rear->next=null;return ok;}status delqueue(linkqueue *q){ //linkqlist *p;int e;if (q->front==q->rear)printf("the linklist is overflow");else p=(q->front)->next;(q->front)->next=p->next;e=p->data;if(q->rear==p)q->rear=q->front;free(p);return(e);}bool visit[maxlen]; //深度优先搜索void DFS(adjlist adjl,int i){edgenode *p;visit[i]=1;printf("%c ",adjl.adjs[i].data);for(p=adjl.adjs[i].link;p;p=p->next){if(!visit[p->adjvex]) DFS(adjl,p->adjvex);}}void DFSTraverse(adjlist adjl){int i;printf("\t\t深度优先搜索:");for( i=0;i<maxlen;i++)visit[i]=false;for( i=0;i<=adjl.vexnum;i++)if(!visit[i]) DFS(adjl,i);}queue <int> Q;void BFSTraverse(adjlist adjl) { //广度优先搜索edgenode *w;int i,j;printf("\n\t\t广度优先搜索:");for( i=0;i<maxlen;i++)visit[i]=0;for(i=0;i<=adjl.vexnum;i++){if(!visit[i]){visit[i]=1;printf("%c ",adjl.adjs[i].data);Q.push(i);while(!Q.empty()){j=Q.front();Q.pop();for( w=adjl.adjs[i].link;w;w=w->next)if(!visit[w->adjvex]){visit[w->adjvex]=1;printf("%c ",adjl.adjs[w->adjvex-1].data);Q.push(w->adjvex);}}}}}status initstack(stackstru *s){ //构造空栈s->top=0;return ok;}status push(stackstru *s,int x) { //进栈if (s->top==maxlen)printf("the stack is overflow!\n");else{s->top=s->top+1;s->stack[s->top]=x;}return 1;}status pop(stackstru *s) //出栈{int y;if(s->top==0)printf("the stack is empty!\n");else{y=s->stack[s->top];s->top=s->top-1;}return y;}status stackempty(stackstru *s) //判断栈是否为空{ if (s->top==maxlen) return (true);else return (false);}int TopologicalSort(adjlist adjl) //拓扑排序{stack <int> S;edgenode *p;int i,j,count=0;printf("\n拓扑排序:");for(i=0;i<=adjl.vexnum;i++)if(adjl.adjs[i].id==0)S.push(i);count=0;while(!S.empty()){j=S.top(); S.pop();count++;printf("(%d %c) ",j,adjl.adjs[j].data);for(p=adjl.adjs[i].link;p;p=p->next){int k=p->adjvex;int d=--(adjl.adjs[k].id);if(!d)S.push(k);}}if(count<adjl.vexnum){ printf("\n网中有环!\n");return error;}else return ok;}void prim(graph g){int i,j,k,min;int lowcost[maxlen];int closet[maxlen];printf("最小生成树的边为:\n");for(i=1;i<g.vexnum;i++){lowcost[i]=g.arcs[0][i];closet[i]=1;}closet[1]=0;j=1;for(i=1;i<g.vexnum;i++){min=lowcost[j];k=i;for(j=1;j<g.vexnum;j++)if(lowcost[j]<min&&closet[j]!=0){min=lowcost[j];k=j;}printf("(%c,%c),",g.vexs[k-1],g.vexs[closet[k-1]]);closet[k]=0;for(j=1;j<g.vexnum;j++)if(g.arcs[k][j]<lowcost[j]&&closet[j]!=0){lowcost[j]=g.arcs[k][j];closet[j]=k;}}}int ve[maxlen];int vl[maxlen];status toporder(adjlist adjl,stackstru *t){ //关键路径int i,j,count,k;edgenode *p;initstack(s);initstack(t);for(i=0;i<adjl.vexnum;i++)if(adjl.adjs[i].id==0) push(s,i);count=0;for(i=0;i<adjl.vexnum;i++) ve[i]=0;while(!stackempty(s)){j=pop(s);push(t,j);++count;for(p=adjl.adjs[j].link;p;p=p->next){k=p->adjvex;if(--adjl.adjs[k-1].id==0) push(s,k-1);if(ve[j]+(p->info)>ve[k-1]) ve[k-1]=ve[j]+(p->info);}}if(count<adjl.vexnum) return error;else return ok;}int criticalpath(adjlist adjl){int i,j,k,dut,ee,el;edgenode *p;if(!toporder(adjl,t)) return error;for(i=0;i<adjl.vexnum;i++) vl[i]=ve[i-1];printf("关键路径为:\n");while(!stackempty(t))for(j=pop(t), p=adjl.adjs[j].link;p;p=p->next){k=p->adjvex; dut=(p->info);if(vl[k]-dut<vl[j]) vl[j]=vl[k]-dut;}for(j=0;j<adjl.vexnum;++j)for(p=adjl.adjs[j].link;p;p=p->next){k=p->adjvex;dut=p->info;ee=ve[j];el=vl[k-1]-dut;if(ee==el) printf("(%c,%c)->",adjl.adjs[j].data,adjl.adjs[k-1].data);}return ok;}void shortpath_dijkstra(graph g) //有向网的最短路径{int cost[maxlen][maxlen];int dist[maxlen];int path[maxlen];int s[maxlen];int i,j,v0,min,u;printf("\n请输入起点的编号:");scanf("%d",&v0);v0--;for(i=0;i<g.vexnum;i++){for(j=0;j<g.vexnum;j++)cost[i][j]=g.arcs[i][j];}for(i=0;i<g.vexnum;i++){dist[i]=cost[v0][i];if(dist[i]<large&&dist[i]>0) path[i]=v0;s[i]=0;}s[v0]=1;for(i=0;i<g.vexnum;i++){min=large;u=v0;for(j=0;j<g.vexnum;j++)if(s[j]==0&&dist[j]<min){min=dist[j];u=j;}s[u]=1;for(j=0;j<g.vexnum;j++)if(s[j]==0&&dist[u]+cost[u][j]<dist[j]){dist[j]=dist[u]+cost[u][j];path[j]=u;}}printf("\n顶点%d到各顶点的最短路径长度为:\n",v0);for(i=0;i<g.vexnum;i++)if(s[i]==1){u=i;while(u!=v0){ printf("%4c<-",g.vexs[u]);u=path[u];}printf("%4c",g.vexs[u]);printf(":%d\n",path[i]);}else printf("%4c<-%4c:无路径\n",g.vexs[i],g.vexs[v0]);}void ShowMainMenu(){printf("\n");printf("**************图的基本操作及应用***************\n");printf("* 1 无向图的基本操作及应用*\n");printf("* 2 有向图的基本操作及应用*\n");printf("* 3 无向网的基本操作及应用*\n");printf("* 4 有向网的基本操作及应用*\n");printf("* 5 退出\n");printf("***********************************************\n");}void UDG(){int n;do{printf("\n");printf("**************无向图的基本操作及应用***************\n");printf("* 1 创建无向图的邻接矩阵*\n");printf("* 2 创建无向图的邻接表*\n");printf("* 3 无向图的深度优先遍历*\n");printf("* 4 无向图的广度优先遍历*\n");printf("* 5 退出\n");printf("***************************************************\n");printf("请选择:");scanf("%d",&n);switch(n){case 1:printf("----------wait-------");creategraph(g);break; //邻接矩阵case 2:printf("----------wait-------");createlist (g,adjl);break; //邻接表case 3:printf("----------wait-------");DFSTraverse(adjl);break; //深度优先搜索case 4:printf("----------wait-------");BFSTraverse(adjl);break; //广度优先搜索case 5:break;default:printf("ERROR!");}}while(n!=5);}void DG(){int n;do{printf("\n");printf("**************有向图的基本操作及应用***************\n");printf("* 1 创建有向图的邻接矩阵*\n");printf("* 2 创建有向图的邻接表*\n");printf("* 3 拓扑排序*\n");printf("* 4 退出*\n");printf("***************************************************\n");printf("请选择:");scanf("%d",&n);switch(n){case 1:printf("--------wait-------");creategraph(g);break; //邻接矩阵case 2:printf("--------wait-------");createlist (g,adjl);break; //邻接表case 3:printf("--------wait-------");createlist(g,adjl);TopologicalSort(adjl);break; //拓扑排序case 4:break; //退出default:printf("ERROR!");}}while(n!=4);}void UDN(){int n;do{printf("\n");printf("**************无向网的基本操作及应用***************\n");printf("* 1 创建无向网的邻接矩阵*\n");printf("* 2 创建无向网的邻接表*\n");printf("* 3 Prim算法求最小生成树*\n");printf("* 4 kraskal算法求最小生成树*\n");printf("* 5 退出\n");printf("***************************************************\n");printf("请选择:");scanf("%d",&n);switch(n){case 1:printf("---------wait-------");creategraph(g);break; // 创建无向网的邻接矩阵case 2:printf("--- ----wait-------");createlist (g,adjl);break; // 创建无向网的邻接表case 3:printf("---------wait-------");prim(g);break; //Prim算法求最小生成树case 4:printf("---------wait-------");break;case 5:break;default:printf("ERROR!");}}while(n!=5);}void DN(){int n;do{printf("\n");printf("**************有向网的基本操作及应用***************\n");printf("* 1 创建有向网的邻接矩阵*\n");printf("* 2 创建有向网的邻接表*\n");printf("* 3 关键路径*\n");printf("* 4 单源顶点最短路径问题*\n");printf("* 5 退出\n");printf("***************************************************\n");printf("请选择:");scanf("%d",&n);switch(n){case 1:printf("---------wait-------");creategraph(g);break; //创建有向网的邻接矩阵case 2:printf("---------wait-------");createlist (g,adjl);break; //创建有向网的邻接表case 3:printf("---------wait-------");criticalpath(adjl);break; //关键路径case 4:printf("---------wait-------");criticalpath(adjl);break; //单源顶点最短路径问题case 5:break; //退出default:printf("ERROR!");}while(n!=5);}void main(){int i,j,k,h,n;do{ShowMainMenu();printf("请选择:");scanf("%d",&n);if(n>5) error;else{g.kind=n;h=n;printf("请输入顶点数,边数:");scanf("%d,%d",&i,&j);g.vexnum=i;adjl.vexnum=i;g.arcnum=j;adjl.arcnum=j;for (i=0;i<g.vexnum;i++){printf("第%d个顶点的信息:",i+1);scanf("%s",&g.vexs[i]);adjl.adjs[i].data=g.vexs[i];adjl.adjs[i].link=null;adjl.adjs[i].id=0;}for (k=1;k<=g.arcnum;k++){//label:if (g.kind==2||g.kind==4)printf("第%d条边的起点编号,终点编号:",k);else printf("第%d条边的两个顶点的编号:",k);scanf("%d,%d",&i,&j);g.a[k-1]=i;g.b[k-1]=j;while (i<1||i>g.vexnum||j<1||j>g.vexnum){printf(" 编号超出范围,重新输入");//goto label;}if (g.kind==3||g.kind==4){printf("\t该边的权值:");scanf("%d",&h);g.h[k-1]=h;}else g.h[k-1]=null;adjl.adjs[i].id++;}switch(n){case 1:UDG();break;case 2:DG();break;case 3:UDN();break;case 4:DN();break;case 5:break;default:printf("ERROR!");break;}}while(n!=5);}三、测试a)程序开始运行,进入选择界面b)选择无向图,并创建无向图C)基于已创建的的无向图选择各项具体的操作四、难点与收获这次的实习报告相对我而言算是比较难的,因为在学这门课程的时候就没怎么专心听讲,所以在拿到计划书的时候,对很多地方感觉很陌生,甚至有一种没办法动手的感觉,加之开始学JAVA以后就很少用C语言编写程序,导致对很多很简单的东西都很陌生,所以熟悉整个C语言的编程环境都花了一段时间。
成人本科函授学位考试课程《数据结构》知识点
继续教育学院本科学位考试课程《数据结构》知识点一、必须掌握的基本概念(可能的题型为名词解释)算法、数据、数据元素、数据类型、数组、串、模式匹配、顺序表、链表、栈、队列、树、二叉树、满二叉树、完全二叉树、线索二叉树、图、网、有向图、无向图、检索、哈希函数、哈希表、顺序检索、二分法检索、排序、堆二、一般掌握的知识点(可能的题型为填空、单选、多选、判断等客观题)1、算法的5个重要特性。
2、评价算法优劣的5条标准。
3、算法的时间复杂度分析。
4、算法与程序的联系和区别。
5、数据的逻辑结构的基本概念和分类。
什么是线性结构?什么是非线性结构?6、数组的顺序存储结构,数组元素的地址计算。
7、空串与空格串的区别。
8、简单模式匹配算法。
9、线性表的顺序存储和链式存储的特点。
10、栈和队列的特性。
11、循环队列为空的条件和为满的条件。
12、循环链表和双向链表的特点。
13、二叉树的特点和性质。
14、二叉树的存储结构。
15、二叉树的3种遍历(前序、中序、后序)。
16、满二叉树与完全二叉树的异同。
17、完全二叉树的相关计算。
18、计算二叉树的节点数和叶子数。
19、图的存储结构。
20、n个顶点的无向完全图有n(n-1)/2条边,n个顶点的有向完全图有n(n-1)条弧。
有向图中所有结点的入度之和、出度之和均等于边数。
21、有生成树的图是连通图。
对于n个顶点的连通图,其生成树均有n个结点和n-1条边。
22、对有序表进行顺序检索,求其检索成功和不成功的平均检索长度。
23、对有序表进行二分法检索,求其检索成功和不成功的平均检索长度。
24、用线性探查法消除地址冲突构造哈希表。
25、直接插入排序、希尔排序、冒泡排序、快速排序、堆排序、基数排序的时间复杂度、空间复杂度以及稳定性。
三、重点掌握的知识点(可能的题型为简答、论述等主观题)1、线性表的顺序存储和链式存储的具体实现。
2、栈和队列的顺序存储和链式存储的具体实现。
3、已知一棵二叉树的中序遍历和先序(或后序、层序)遍历画出该二叉树。
数据结构与算法学习知识网络图
数据结构与算法学习知识网络图数据结构与算法是计算机科学中的重要基础知识,对于程序设计和问题解决起着至关重要的作用。
为了更好地学习和理解数据结构与算法,我们可以使用知识网络图的方式来组织和呈现相关概念和知识,帮助我们更好地掌握和运用这些知识。
一、数据结构1. 数组(Array)数组是最基本的数据结构之一,是按照顺序存储数据的集合。
它的特点是可以通过下标快速访问任意位置的元素。
2.链表(Linked List)链表是另一种常见的数据结构,通过节点之间的链接关系存储数据。
它的特点是插入和删除元素更加高效,但访问元素的效率较低。
3. 栈(Stack)栈是一种特殊的线性数据结构,它遵循“先进后出”的原则。
常见的操作有入栈和出栈。
4. 队列(Queue)队列也是一种线性数据结构,遵循“先进先出”的原则。
常见的操作有入队和出队。
5. 树(Tree)树是一种非线性数据结构,由节点和链接关系组成。
常见的树结构有二叉树、平衡二叉树、红黑树等。
6. 图(Graph)图是由节点和边组成的非线性数据结构,用于表示多个对象之间的关系。
常见的图结构有有向图和无向图。
二、算法1. 排序算法(Sorting Algorithm)排序算法是常见的算法之一,用于对一组数据进行排序。
常见的排序算法有冒泡排序、插入排序、选择排序、快速排序等。
2. 查找算法(Search Algorithm)查找算法是用于在一组数据中查找指定元素的算法。
常见的查找算法有线性查找、二分查找、哈希查找等。
3. 图算法(Graph Algorithm)图算法是应用于图结构的特定算法,用于解决图相关的问题。
常见的图算法有深度优先搜索(DFS)、广度优先搜索(BFS)、最短路径算法等。
4. 动态规划(Dynamic Programming)动态规划是一种解决多阶段决策问题的数学优化方法。
它通过将问题分解为多个子问题,并存储子问题的解来提高效率。
5. 贪心算法(Greedy Algorithm)贪心算法是一种在每一步选择中都采取当前状态下最优的选择,从而得到全局最优解的算法。
数据结构和算法课程设计题目
北方民族大学课程设计课程名称:数据结构与算法院(部)名称:信息与计算科学学院组长姓名学号同组人员姓名指导教师姓名:纪峰设计时间:2010.6.7----2009.6.27一、《数据结构与算法》课程设计参考题目(一)参考题目一(每位同学选作一个,同组人员不得重复)1、编写函数实现顺序表的建立、查找、插入、删除运算。
2、编写函数分别实现单链表的建立、查找、插入、删除、逆置算法。
3、编写函数实现双向链表的建立、插入、删除算法。
4、编写函数实现顺序栈的进栈、退栈、取栈顶的算法。
5、编写函数实现链栈的进栈、退栈、取栈顶的算法。
6、编写函数实现双向顺序栈的判空、进栈、出栈算法。
7、编写函数实现循环队列的判队空、取队头元素、入队、出队算法。
8、编写函数实现链环队列的判队空、取队头节点、入队、出队算法。
9、编写函数实现串的,求串长、连接、求字串、插入、删除等运算。
10、分别实现顺序串和链串的模式匹配运算。
11、实现二叉树的建立,前序递归遍历和非递归遍历算法。
12、实现二叉树的建立,中序递归遍历和非递归遍历算法。
13、实现二叉树的建立,后序递归遍历和非递归遍历算法。
14、实现二叉树的中序线索化,查找*p结点中序下的前驱和后继结点。
15、分别以临接表和邻接矩阵作为存储就够实现图的深度优先搜索和广度优先搜索算法。
16、利用线性探测处理冲突的方法实现散列表的查找和插入算法。
(二)参考题目二(每三人一组,任选三个题目完成)1.运动会分数统计(限1人完成)任务:参加运动会有n个学校,学校编号为1……n。
比赛分成m个男子项目,和w个女子项目。
项目编号为男子1……m,女子m+1……m+w。
不同的项目取前五名或前三名积分;取前五名的积分分别为:7、5、3、2、1,前三名的积分分别为:5、3、2;哪些取前五名或前三名由学生自己设定。
(m<=20,n<=20)功能要求:1)可以输入各个项目的前三名或前五名的成绩;2)能统计各学校总分,3)可以按学校编号或名称、学校总分、男女团体总分排序输出;4)可以按学校编号查询学校某个项目的情况;可以按项目编号查询取得前三或前五名的学校。
图论:有向图和无向图,有环和无环
图论:有向图和⽆向图,有环和⽆环
有向⽆环图:为什么不能有环,有环会导致死循环。
检查⼀个有向图是否存在环要⽐⽆向图复杂。
(有向图为什么⽐⽆向图检查环复杂呢?)
现实中管⽹会存在环吗?管⽹是有⽅向的,理论上也是⽆环的。
arcgis有向⽆环图最短路径。
有向⽆环图和⼆叉树的关系:如何确定⽗节点和⼦节点[没有⽗节点的就是⽗节点,没有⼦节点的就是叶⼦节点] 有向⽆环图并不⼀定能转化成树【那能不能把有向⽆环图劈开成多棵树】
⼀个⽆环的有向图称做有向⽆环图(Directed Acyclic Graph)。
简称DAG 图。
DAG 图是⼀类较有向树更⼀般的特殊有向图,如图给出了有向树、DAG 图和有向图的例⼦。
虽然DAG图是更⼀般的有向图,但是依然可以使⽤树的判断公式来判断复杂度。
判断是否有环:
1. 起点编码和终点编码是否相等
从OBJECTID为1的开始遍历:下⼀个点是否与OBJECTID为1的相等。
如果相等,则回到起点,为环。
>>性质:有向⽆环图的⽣成树个数等于⼊度⾮零的节点的⼊度积。
有向⽆环图⽣成树:
(百度百科上不是说有向⽆环图不⼀定能转换成树吗?严格意义上,树的叶⼦节点只有⼀个⽗节点)
DAG(有向⽆环图)能否转化为树?:
如果说⼀个叶⼦节点有两个⽗节点,会怎么样
有向⽆环图不⼀定能只⽣成⼀棵树,但是可以⽣成多棵树。
但是这样就破坏了什么信息呢?。
数据结构考研讲义 第五章 图
第四章图4.1图的概念1.图的定义图是由一个顶点集V和一个弧集R构成的数据结构。
2.图的重要术语;(1)无向图:在一个图中,如果任意两个顶点构成的偶对(v,w)∈E是无序的,即顶点之间的连线是没有方向的,则称该图为无向图。
(2)有向图:在一个图中,如果任意两个顶点构成的偶对(v,w)∈E是有序的,即顶点之间的连线是有方向的,则称该图为有向图。
(3)无向完全图:在一个无向图中,如果任意两顶点都有一条直接边相连接,则称该图为无向完全图。
在一个含有n个顶点的无向完全图中,有n(n-1)/2条边。
(4)有向完全图:在一个有向图中,如果任意两顶点之间都有方向互为相反的两条弧相连接,则称该图为有向完全图。
在一个含有n个顶点的有向完全图中,有n(n-1)条边。
(5)稠密图、稀疏图:若一个图接近完全图,称为稠密图;称边数很少(e<nlogn)的图为稀疏图。
(6)顶点的度、入度、出度:顶点的度(degree)是指依附于某顶点v的边数,通常记为TD(v)。
在有向图中,要区别顶点的入度与出度的概念。
顶点v的入度是指以顶点为终点的弧的数目,记为ID(v);顶点v出度是指以顶点v为始点的弧的数目,记为OD(v)。
TD(v)=ID(v)+OD(v)。
(7)边的权、网图:与边有关的数据信息称为权(weight)。
在实际应用中,权值可以有某种含义。
边上带权的图称为网图或网络(network)。
如果边是有方向的带权图,则就是一个有向网图。
(8)路径、路径长度:顶点vp到顶点vq之间的路径(path)是指顶点序列vp,vi1,vi2,…,vim,vq.。
其中,(vp,vi1),(vi1,vi2),…,(vim,.vq)分别为图中的边。
路径上边的数目称为路径长度。
(9)简单路径、简单回路:序列中顶点不重复出现的路径称为简单路径。
除第一个顶点与最后一个顶点之外,其他顶点不重复出现的回路称为简单回路,或者简单环。
(10)子图:对于图G=(V,E),G’=(V’,E’),若存在V’是V的子集,E’是E的子集,则称图G’是G的一个子图。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法与数据结构课程设计报告系(院):计算机科学学院专业班级:教技1001姓名:李##学号: ******### 指导教师:***设计时间:2012.6.16 - 2012.6.24设计地点:4号楼2号机房目录一、设计方案 (1)二、实现过程以及代码 (2)三、测试 (20)四、结论和分析 (23)五、难点和收获 (23)一、 设计方案1.程序设计基本过程:拿到课程设计任务书,按照要求,需要设计有向图、有向网、无向图 、无向网四种图,以及邻接矩阵、邻接表两种数据存储结构,三层以上的显示菜单。
图的操作中又包含了有关线性表、栈和队列的基本操作。
由于显示菜单已给出,剩下的任务就是把函数写入其中。
2.程序流程图:预定义 定义结构体 定义变量 各种函数3.程序设计的原理:图的操作都是以两种存储结构为基础的:邻接矩阵存储结构和邻接表存储结构,如有向图,有向网,无向图,无向网的创建,其他的操作都是在四种图创建后才开始进行的。
所以,首先必须理解两种存储结构的定义。
图的邻接矩阵存储结构即图的数组表示法。
用两个数组分别存储数据元素(如顶点)的信息和数据元素之间的关系(如边或弧)的信息。
用邻接矩阵存储结构的图具有以下几点特征:(一):顶点数:vexnum ,边(弧)数:arcnum ,图的种类:kind ;(二):邻接矩阵:arcs(1顶点关系类型:adj 2相关信息:*info);(三):顶点向量(顶点名):vexs[];其优点是以二维数组表示有n 个顶点的图时,需存放n 个顶点的信息和n*n 条弧的信息存储量。
借助邻接矩阵容易判定任意两个顶点之间是否有边或弧相连,并容易求出各个顶点的度。
缺点是时间复杂度是O (n*n ),例如,构造一个具有n 个顶点和e 条边的无向网的时间复杂度为O (n*n+e*n )。
图的邻接表存储结构是图的一种链式存储结构。
对图中的每个顶点建立一个单链表,每个结点由三个域组成,邻接点域adjvex (弧尾在邻接表链表中的位序),链域nextarc (下一条弧),数据域info(权值)。
还要建立一个邻接表链表,用以存放顶点的data 和后继指针firstarc,表头结点以顺序结构的形式存储,便于随机访问任一顶点的单链表。
邻接表存储结构的优点在于其时间复杂度小。
树的深度优先搜索遍历类似于树的先根遍历,是树的先根遍历的推广。
从图中的某个顶点出发,访问此顶点,然后依次从该顶点出发深度优先搜索遍历图,直至图中所有与该顶点有关的路径都被访问到;此时图中若还有顶点未被访问到,则另选图中的一个未被访问的顶点作为起始点,重述上述过程,直至所有顶点都被访问到。
广度优先搜索遍历类似于树的按层次遍历的过程。
以某个顶点为起始顶点,由近至远,依次访问和该顶点有路径相通的且路径长度为1,2,3,······的顶点。
当图中所有顶点都被访问到后,就完成了图的广度优先搜索遍历。
求无向网的最小生成树问题有两种算法:Prima算法和Kruskal算法。
Prima算法是从网中的某个顶点出发,选择与该顶点有路径的所有顶点中路径最小的一条路径,从该最小路径的另一顶点出发,重复上述过程,直至图中所有顶点都被访问完成。
Kruskal算法是从网中找出所有路径最小的一条路径,记下已访问该路径的两个顶点,再次从图中找出剩下路径中的最小路径,重复上述过程,直至所有顶点都被访问完成,按访问的顺序依次输出各顶点,即构造了一棵最小生成树。
由某个集合上的一个偏序得到该集合的一个全序的操作就叫做拓扑排序。
拓扑排序的过程:(1)在有向图中选择一个没有前驱的顶点并输出;(2)在图中删除该顶点和所有以它为尾的弧。
重复上述两步,直至全部顶点均已输出,就得到了一个拓扑有序序列。
求关键路径的算法如下:(1)输入e条弧,建立AOE网的存储结构;(2)从源点v0出发,令ve[0]=0,按拓扑有序求其余各顶点的最早发生时间。
如果得到的拓扑有序序列中的顶点个数小于网中的顶点数,则说明网中存在环,不能求关键路径,算法终止;否则执行第三步。
(3)从汇点vn出发,令vl[n-1]=ve[n-1],按逆拓扑有序求其余各顶点的最迟发生时间vl[i];(4)根据各顶点的和值,求每条弧的最早开始时间e(s)和最迟开始时间e(s),若某条弧满足条件e(s)=l(s),则为关键活动。
从某个源点到其余各顶点的最短路径问题:若从v到vi有弧,则D[i]为弧上的权值,否则D[i]为无穷大。
显然,长度为D[j]=Min{D[i]|vi属于V}的路径就是从v出发的长度最短的一条路径。
二、实现过程以及代码当电脑运行程序的时候,界面会出现一个提示菜单:请输入你要进行操作的图类型的编码:1:有向图,2:有向网,3:无向图,4:无向网,请输入选择。
操作者根据自己的需要可输入相应的编码来进行操作。
如选择3,则将进入关于无向图的操作。
根据课设指导书要求,无向图有四个基本操作:构建邻接矩阵,构建邻接表,对已构建的邻接表进行深度遍历,对已构建的邻接表进行广度遍历,输出所有操作的结果。
第一步操作就是构建,程序会提示你进行下一步操作,然后再根据各操作提示从外部输入顶点和弧的相关信息。
其他三个图的操作基本与本图的操作时一致的。
代码:#include <stdio.h>#include<stdlib.h>#include<limits.h>#define ERROR 0#define OK 1#define INFINITY INT_MAX#define MAX_VERTEX_NUM 21#define STACK_INIT_SIZE 100#define STACKINCREAMENT 10typedef enum{DG,DN,UDG,UDN}GraphKind;typedef struct ArcCell {int adj;//infotype *info;}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct{char vexs[MAX_VERTEX_NUM];AdjMatrix arcs;int vexnum,arcnum;GraphKind kind;}MGraph; //邻接矩阵typedef struct ArcNode{int adjvex;int quan;struct ArcNode *nextarc;}ArcNode,*AList;typedef struct VNode {char data;AList firstarc;}VNode,AdjList[MAX_VERTEX_NUM];typedef struct{AdjList vertices;int vexnum,arcnum;GraphKind kind;}ALGraph; //邻接表typedef struct QNode{char data;struct QNode *next;}QNode,*QueuePre;typedef struct{QueuePre front;QueuePre rear;}LinkQueue; //队列typedef struct {int *base;int *top;int stacksize;}SqStack; //栈typedef struct {char adjvex;int lowcost;}closedges[MAX_VERTEX_NUM]; //求最小生成树中的辅助数组int option;int visited[MAX_VERTEX_NUM]; //顶点访问标记数组int indegree[MAX_VERTEX_NUM]; //顶点入度记录数组int ve[MAX_VERTEX_NUM]; //顶点权值记录数组int SetGraphKind(MGraph &G,int option){switch(option){case 1: G.kind=DG;break;case 2: G.kind=DN;break;case 3: G.kind=UDG;break;case 4: G.kind=UDN;break;default: return ERROR;}return OK;} //邻接矩阵类型设置int SetGraphKind(ALGraph &G,int option){switch(option){case 1: G.kind=DG;break;case 2: G.kind=DN;break;case 3: G.kind=UDG;break;case 4: G.kind=UDN;break;default: return ERROR;}return OK;} //邻接表类型设置int LocateVex(MGraph G,char v){int m;for(m=1;m<=G.vexnum;m++){if(G.vexs[m]==v) return m;}return ERROR;} //邻接矩阵顶点定位int LocateVex(ALGraph G,char v){int m;for(m=1;m<=G.vexnum;m++){if(G.vertices[m].data==v) return m;}printf("您输入的顶点不存在");return ERROR;} //邻接表顶点定位int InitQueue(LinkQueue &Q){Q.front=Q.rear=(QueuePre)malloc(sizeof(QNode));if(!Q.front) return ERROR;Q.front->next=NULL;return OK;} //队列创建int EnQueue(LinkQueue &Q,int e){QueuePre p;p=(QueuePre)malloc(sizeof(QNode));if(!p) return OK;p->data=e;p->next=NULL;Q.rear->next=p;Q.rear=p;return OK;} //元素入队列int DeQueue(LinkQueue &Q,int &e){QueuePre p;if(Q.front==Q.rear) return ERROR;p=Q.front->next;e=p->data;Q.front->next=p->next;if(Q.rear==p) Q.rear=Q.front;free(p);return OK;} //元素出队列int QueueEmpty(LinkQueue Q){if(Q.front==Q.rear)return OK;return ERROR;} //判断队列是否为空int InitStack(SqStack &S){S.base=(int*)malloc(STACK_INIT_SIZE*sizeof(int));if(!S.base) return ERROR;S.top=S.base;S.stacksize=STACK_INIT_SIZE;return OK;} //栈创建int Push(SqStack &S,int e){if(S.top-S.base>=S.stacksize){S.base=(int*)realloc(S.base,(S.stacksize+STACKINCREAMENT)*sizeof(int));if(!S.base) return ERROR;S.top=S.base+S.stacksize;S.stacksize+=STACKINCREAMENT;}*S.top++=e;return OK;} //元素入栈int Pop(SqStack &S,int &e){if(S.top==S.base) return ERROR;e=*--S.top;return OK;} //元素出栈int StackEmpty(SqStack S){if(S.top==S.base) return OK;return ERROR;} //判断栈是否为空int CreatGraph(MGraph &G){int i,j,k,w;char x,y;if(!SetGraphKind(G,option)) {printf("对图类型的设置失败");return ERROR;}printf("邻接矩阵:请输入定点的个数、弧的个数:");scanf("%d %d",&G.vexnum,&G.arcnum);if(G.vexnum>20){printf("您输入的顶点个数超过最大值");return ERROR;}printf("请输入%d个顶点\n",G.vexnum);for(i=1;i<=G.vexnum;++i) {fflush(stdin); scanf("%c",&G.vexs[i]);}if(G.kind==DG||G.kind==UDG){for(i=1;i<=G.vexnum;i++)for(j=1;j<=G.vexnum;j++)G.arcs[i][j].adj=0;if(G.kind==DG){printf("请输入有向图的两个相邻的顶点<x,y>(如果互相邻接则<x,y>也要输入):\n");for(k=1;k<=G.arcnum;k++){fflush(stdin);scanf("%c%c",&x,&y);i=LocateVex(G,x);j=LocateVex(G,y);G.arcs[i][j].adj=1;}}else{printf("请输入无向图的两个相邻的顶点(x,y):\n");for(k=1;k<=G.arcnum;k++){fflush(stdin);scanf("%c%c",&x,&y);i=LocateVex(G,x); j=LocateVex(G,y);G.arcs[i][j].adj=1; G.arcs[j][i].adj=G.arcs[i][j].adj;}}}else{for(i=1;i<=G.vexnum;i++)for(j=1;j<=G.vexnum;j++)G.arcs[i][j].adj=INT_MAX;if(G.kind==DN){printf("请输入有向网的两个相邻的顶点<x,y>以及相应的权值w(如果互相邻接则<y,x>也要输入):\n");for(k=1;k<=G.arcnum;k++){fflush(stdin);scanf("%c%c %d",&x,&y,&w);i=LocateVex(G,x); j=LocateVex(G,y);G.arcs[i][j].adj=w;}}else{printf("请输入无向网的两个相邻的顶点(x,y)以及相应的权值w:\n");for(k=1;k<=G.arcnum;k++){fflush(stdin);scanf("%c%c %d",&x,&y,&w);i=LocateVex(G,x); j=LocateVex(G,y);G.arcs[i][j].adj=w; G.arcs[j][i].adj=G.arcs[i][j].adj;}}}return OK;} //创建邻接矩阵int CreatAList(ALGraph &G){int i,j,m,n,key[MAX_VERTEX_NUM]; char x,y,w;AList p,q;SetGraphKind(G,option);printf("邻接表:请输入顶点的个数和弧的个数:");scanf("%d %d",&G.vexnum ,&G.arcnum);if(G.vexnum>20){printf("您输入的顶点个数超过最大值");return ERROR;}printf("请输入个顶点:\n");for(i=1;i<=G.vexnum;i++){fflush(stdin);scanf("%c",&G.vertices[i].data);G.vertices[i].firstarc=NULL;key[i]=0;}if(G.kind==DG){printf("请输入弧(如AB,其中AB与BA是不同的弧):\n");for(j=1;j<=G.arcnum;j++){fflush(stdin);scanf("%c%c",&x,&y);m=LocateVex(G,x);n=LocateVex(G,y);p=G.vertices[m].firstarc;q=(AList)malloc(sizeof(ArcNode));if(!q) return ERROR;q->nextarc=NULL;q->adjvex=n;while(key[m]&&p->nextarc){p=p->nextarc;key[m]++;}if(!key[m]){G.vertices[m].firstarc=q;key[m]++;}else p->nextarc=q;}}if(G.kind==UDG){printf("请输入弧(如AB,其中AB与BA是不同的弧):\n");for(j=1;j<=2*G.arcnum;j++){fflush(stdin);scanf("%c%c",&x,&y);m=LocateVex(G,x);n=LocateVex(G,y);p=G.vertices[m].firstarc;q=(AList)malloc(sizeof(ArcNode));if(!q) return ERROR;q->nextarc=NULL;q->adjvex=n;while(key[m]&&p->nextarc){p=p->nextarc;key[m]++;}if(!key[m]){G.vertices[m].firstarc=q;key[m]++;}else p->nextarc=q;}}if(G.kind==DN){printf("请输入依次输入弧以及这条弧的权值(如AB 8,其中AB与BA是不同的弧):\n");for(j=1;j<=G.arcnum;j++){fflush(stdin);scanf("%c%c %d",&x,&y,&w);m=LocateVex(G,x);n=LocateVex(G,y);p=G.vertices[m].firstarc;q=(AList)malloc(sizeof(ArcNode));if(!q) return ERROR;q->nextarc=NULL;q->quan=w;q->adjvex=n;while(key[m]&&p->nextarc){p=p->nextarc;key[m]++;}if(!key[m]){G.vertices[m].firstarc=q;key[m]++;}else p->nextarc=q ;}}if(G.kind==UDN){printf("请输入依次输入弧以及这条弧的权值(如AB 8,其中AB与BA是不同的弧):\n");for(j=1;j<=2*G.arcnum;j++){fflush(stdin);scanf("%c%c %d",&x,&y,&w);m=LocateVex(G,x);n=LocateVex(G,y);p=G.vertices[m].firstarc;q=(AList)malloc(sizeof(ArcNode));if(!q) return ERROR;q->nextarc=NULL;q->quan=w;q->adjvex=n;while(key[m]&&p->nextarc){p=p->nextarc;key[m]++;}if(!key[m]){G.vertices[m].firstarc=q;key[m]++;}else p->nextarc=q ;}}return OK;} //创建邻接表int FirstAdjVex(ALGraph G,int v){if(G.vertices[v].firstarc)return G.vertices[v].firstarc->adjvex;return 0;}int NextAdjVex(ALGraph G,int v,int w){AList s;s=G.vertices[v].firstarc;while(s->adjvex!=w)s=s->nextarc;if(s->nextarc)return s->nextarc->adjvex;return 0;}void DFS(ALGraph G,int v){int w;visited[v]=1; printf("%c ",G.vertices[v]);for(w=FirstAdjVex(G,v);w>=1;w=NextAdjVex(G,v,w)){ if(!visited[w]) DFS(G,w);}}void DFSTraverse(ALGraph G){int v;visited[0]=1;for(v=1;v<=G.vexnum;v++) visited[v]=0;for(v=1;v<=G.vexnum;v++)if(!visited[v]) DFS(G,v);} //图的深度遍历void BFSTraverse(ALGraph G){int v,w,u;LinkQueue Q;for(v=1;v<=G.vexnum;v++) visited[v]=0;visited[0]=1;InitQueue(Q);for(v=1;v<=G.vexnum;v++)if(!visited[v]){visited[v]=1;printf("%c ",G.vertices[v]);EnQueue(Q,v);while(!QueueEmpty(Q)){DeQueue(Q,u);for(w=FirstAdjVex(G,u);w>=1;w=NextAdjVex(G,u,w)){if(!visited[w]){visited[w]=1;printf("%c ",G.vertices[w]);EnQueue(Q,w);}else break;}}}} //图的广度遍历void FindInDegree(ALGraph G,int in[]){int i,j,k;AList p;for(k=1;k<=G.vexnum;k++) in[k]=0;for(i=1;i<=G.vexnum;i++){p=G.vertices[i].firstarc;while(p){j=p->adjvex;in[j]++;p=p->nextarc;}}} //计算各顶点入度int TopologicalSort(ALGraph G){int i,k,count;AList p;SqStack S;FindInDegree(G,indegree);InitStack(S);for(i=1;i<=G.vexnum;i++)if(!indegree[i]) Push(S,i);count=0;if(StackEmpty(S)) printf("此有向图不符合条件!");while(!StackEmpty(S)){Pop(S,i);printf("%c ",G.vertices[i].data);++count;for(p=G.vertices[i].firstarc;p;p=p->nextarc){k=p->adjvex;if(!(--indegree[k])) Push(S,k);}}if(count<=G.vexnum) return ERROR;else return OK;} //拓扑排序int Minimum(MGraph G,closedges m){int i,j,min=INFINITY;for(i=1;i<=G.vexnum;i++){if(m[i].lowcost){if(m[i].lowcost<min){min=m[i].lowcost;j=i;}}}return j;}void MinSpanTree_PRIM(MGraph G,char u){int i,j,k;closedges closedge;k=LocateVex(G,u);for(j=1;j<=G.vexnum;j++)if(j!=k) {closedge[j].adjvex=u;closedge[j].lowcost=G.arcs[k][j].adj;}closedge[k].lowcost=0;for(i=2;i<=G.vexnum;i++){k=Minimum(G,closedge);printf("%c%c ",closedge[k].adjvex,G.vexs[k]);closedge[k].lowcost=0;for(j=1;j<=G.vexnum;j++)if(G.arcs[k][j].adj<closedge[j].lowcost){closedge[j].adjvex=G.vexs[k];closedge[j].lowcost=G.arcs[k][j].adj;}}} //求最小生成树int TopologicalOrder(ALGraph G,SqStack &T){int i,j,k,count; SqStack S; AList p;FindInDegree(G,indegree);InitStack(S);for(i=1;i<=G.vexnum;i++)if(!indegree[i]) Push(S,i);InitStack(T);count=1;for(i=1;i<=G.vexnum;i++) ve[i]=0;while(!StackEmpty(S)){Pop(S,j);Push(T,j);++count;for(p=G.vertices[j].firstarc;p;p=p->nextarc){k=p->adjvex;if(--indegree[k]==0) Push(S,k);if(ve[j]+p->quan>ve[k]) ve[k]=ve[j]+p->quan;}}if(count<=G.vexnum) return ERROR;else return OK;}int CriticalPath(ALGraph G){int i,j,k,ee,el,dut,v1[MAX_VERTEX_NUM]; SqStack T; AList p; char tag;if(!TopologicalOrder(G,T)) return ERROR;for(i=1;i<=G.vexnum;i++){v1[i]=ve[G.vexnum];}while(!StackEmpty(T))for(Pop(T,j),p=G.vertices[j].firstarc;p;p=p->nextarc){k=p->adjvex;dut=p->quan;if(v1[k]-dut<v1[j]) v1[j]=v1[k]-dut;}for(j=1;j<=G.vexnum;j++)for(p=G.vertices[j].firstarc;p;p=p->nextarc){k=p->adjvex;dut=p->quan;ee=ve[j];el=v1[k]-dut;tag=(ee==el)?'*':' ';printf("%d %d %d %d %d %c\n",j,k,dut,ee,el,tag);}return OK;} //求关键路径void DG_(MGraph G1,ALGraph G2){int i,j,k,m,key;AList s;printf("**************************\n");printf("你选择了对有向图的基本操作及应用:\n1创建邻接矩阵\n2创建邻接表\n3拓扑结构\n4退出\n");printf("**************************\n");for(k=0;;){key=0;printf("请选择:");scanf("%d",&m);switch(m){case 1: CreatGraph(G1);printf("有向图的邻接矩阵:\n");for(i=1;i<=G1.vexnum;i++){for(j=1;j<=G1.vexnum;j++){printf(" %d",G1.arcs[i][j].adj);}printf("\n");}break;case 2: CreatAList(G2);printf("有向图的邻接表:\n");for(i=1;i<=G2.vexnum;i++){printf("%c:",G2.vertices[i]);s=G2.vertices[i].firstarc;while(s){j=s->adjvex;fflush(stdin);printf("<%c ",G2.vertices[i]);printf("%c> ",G2.vertices[j]);s=s->nextarc;}printf("\n");}break;case 3:printf("有向图的拓扑排序:\n");TopologicalSort(G2);break;case 4:key=1;break;}printf("\n");if(key) break;}printf("\n\n");} //DGvoid UDG_(MGraph G1,ALGraph G2){int i,j,k,m,key;AList s;printf("**************************\n");printf("你选择了对有向网的基本操作及应用:\n1创建邻接矩阵\n2创建邻接表\n3关键路径\n4退出\n");printf("**************************\n");for(k=0;;){key=0;printf("请选择:");scanf("%d",&m);switch(m){case 1: CreatGraph(G1); printf("有向网的邻接矩阵:\n");for(i=1;i<=G1.vexnum;i++){for(j=1;j<=G1.vexnum;j++){if(G1.arcs[i][j].adj==INT_MAX)printf(" #");else printf(" %d",G1.arcs[i][j].adj);}printf("\n");}break;case 2: CreatAList(G2); printf("有向网的邻接表:\n");for(i=1;i<=G2.vexnum;i++){printf("%c:",G2.vertices[i]);s=G2.vertices[i].firstarc;while(s){j=s->adjvex;fflush(stdin);printf("<%c ",G2.vertices[i]);printf("%c> ",G2.vertices[j]);printf(" %d ",s->quan);s=s->nextarc;}printf("\n");}break;case 3: printf("有向网关键路径:\n");CriticalPath(G2);break;case 4: key=1;break;}printf("\n");if(key) break;}printf("\n\n");} //DNvoid DN_(MGraph G1,ALGraph G2){int i,j,k,m,key;AList s;printf("**************************\n");printf("你选择了对无向图的基本操作及应用:\n1创建邻接矩阵\n2创建邻接表\n3深度遍历\n4广度遍历\n5退出\n");printf("**************************\n");for(k=0;;){key=0;printf("请选择:");scanf("%d",&m);switch(m){case 1:CreatGraph(G1); printf("无向图的邻接矩阵:\n");for(i=1;i<=G1.vexnum;i++){for(j=1;j<=G1.vexnum;j++){printf(" %d",G1.arcs[i][j].adj);}printf("\n");}break;case 2: CreatAList(G2); printf("无向图的邻接表:\n");for(i=1;i<=G2.vexnum;i++){printf("%c:",G2.vertices[i]);s=G2.vertices[i].firstarc;while(s){j=s->adjvex;fflush(stdin);printf("(%c ",G2.vertices[i]);printf("%c) ",G2.vertices[j]);s=s->nextarc;}printf("\n");}break;case 3: printf("无向图的深度优先遍历:\n");DFSTraverse(G2);printf("\n");break;case 4: printf("无向图的广度优先遍历:\n");BFSTraverse(G2);break;case 5: key=1;break;}printf("\n");if(key) break;}printf("\n\n");} //UDGvoid UDN_(MGraph G1,ALGraph G2){int i,j,m,k,key;AList s;char u;printf("**********************************\n");printf("你选择了对无向网的基本操作及应用:\n1创建邻接矩阵\n2创建邻接表\n3最小生成树\n4退出\n");printf("**********************************\n");for(k=0;;){key=0;printf("请选择:");scanf("%d",&m);switch(m){case 1: CreatGraph(G1); printf("无向网的邻接矩阵:\n");for(i=1;i<=G1.vexnum;i++){for(j=1;j<=G1.vexnum;j++){if(G1.arcs[i][j].adj==INT_MAX)printf(" #");else printf(" %d",G1.arcs[i][j].adj);}printf("\n");}break;case 2: CreatAList(G2); printf("无向网的邻接表:\n");for(i=1;i<=G2.vexnum;i++){printf("%c:",G2.vertices[i]);s=G2.vertices[i].firstarc;while(s){j=s->adjvex;fflush(stdin);printf("(%c ",G2.vertices[i]);printf("%c)",G2.vertices[j]);printf(" %d ",s->quan);s=s->nextarc;}printf("\n");}break;case 3: printf("请输入第一个顶点:");fflush(stdin);scanf("%c",&u);printf("无向网的最小生成树:\n");MinSpanTree_PRIM(G1,u);break;case 4: key=1;break;}printf("\n");if(key) break;}printf("\n\n");} //UDNvoid main(){MGraph G1;ALGraph G2;int i,n;for(i=0;;){n=0;printf("\n");printf("**************图的基本操作及应用***************\n1:有向图的基本操作及应用\n2:无向图的基本操作及应用\n3:有向网的基本操作及应用\n4:无向网的基本操作及应用\n5: 退出\n");printf("********************************\n");printf("请选择:");scanf("%d",&option);printf("\n\n");switch(option){case 1: DG_(G1,G2);break;case 2: DN_(G1,G2);break;case 3: UDG_(G1,G2);break;case 4: UDN_(G1,G2);break;case 5: n=1;break;default: printf("你输入的编码有误!"); break;}if(n) break;printf("\n\n");}}三、测试菜单有向图内部菜单有向图邻接矩阵有向图邻接表以及拓扑结构无向网的基本操作无向网邻接矩阵及最小生成树四、结论和分析整个程序最关键和最基本的是对图四种类型的邻接矩阵和邻接表的创建。