当前位置:文档之家› 图的基本操作与实现的课程设计报告

图的基本操作与实现的课程设计报告

中国矿业大学徐海学院计算机系《软件认知实践》报告姓名:学号:专业:设计题目:指导教师:2013年12月30日目录第1章题目概述 (2)第1.1节题目要求 (2)第1.2节主要难点 (3)第2章系统流程图 (4)第3章数据结构和算法 (5)第4章核心代码分析 (6)第5章复杂度分析 (25)参考文献 (25)第一章题目概述第1.1节题目要求(1)自选存储结构,输入含n个顶点(用字符表示顶点)和e条边的图G;(2)求每个顶点的度,输出结果;(3)指定任意顶点x为初始顶点,对图G作DFS遍历,输出DFS顶点序列(提示:使用一个栈实现DFS);(4)指定任意顶点x为初始顶点,对图G作BFS遍历,输出BFS顶点序列(提示:使用一个队列实现BFS);(5)输入顶点x,查找图G:若存在含x的顶点,则删除该结点及与之相关连的边,并作DFS遍历(执行操作3);否则输出信息“无x”;(6)判断图G是否是连通图,输出信息“YES”/“NO”;(7)如果选用的存储结构是邻接矩阵,则用邻接矩阵的信息生成图G的邻接表,即复制图G,然再执行操作(2);反之亦然。

第1.2节主要难点(1)自选存储结构创建一个图:通过用户从键盘敲入的两个数值分别确定图的顶点数和边数,选择邻接矩阵存储结构将图的结点信息存储在一个顺序表中,图的边信息存储在一个二维数组中。

(2)求每个顶点的度:1.邻接矩阵存储结构下求每个顶点的度:利用图的邻接矩阵,每个顶点所在行和所在列的边的权值如果存在则该顶点的度+1,依次算出每个顶点的度,并且记录在一个数组中输出。

2.邻接表存储结构下求每个顶点的度:定义一个邻接边指针循环指向顶点的邻接边单链表头结点,当结点不空时,该顶点的出度+1,邻接边弧头结点的入度+1,依次求出每个顶点的出度和入度之和就为该顶点的度。

(3)图的深度优先遍历:采取邻接矩阵结构,指定任意顶点x为初始顶点1.访问结点v并标记结点v已访问;2.查找结点v的第一个邻接结点w;3.若结点v的邻接结点w存在,则继续执行,否则算法结束;4.若结点w尚未被访问,则递归访问结点w;5.查找结点v的w邻接结点的下一个邻接结点w,转到步骤3。

(4)图的广度优先遍历:采取邻接矩阵结构,指定任意顶点x为初始顶点,利用顺序循环队列以保持访问过的结点的顺序1.首先访问初始结点v并标记结点v为已访问;2.结点v入队列;3.当队列非空时则继续执行,否则算法结束;4.出队列取得队头结点u;5.查找u的第一个邻接结点w;6.若u的邻接结点w不存在则转到步骤3,否则循环执行下列步骤:6.1若结点w尚未被访问,则访问结点w并标记结点w为已访问;6.2结点w入队列;6.3查找结点u的w邻接结点的下一个邻接结点w,转到步骤6 。

(5)判断有向图的强连通性:采取邻接表结构,在图中寻找一个包含所有顶点且首尾相连的环,若这样的环存在,则该图为强连通图,否则不为强连通图。

(6)用邻接矩阵的信息生成邻接表:定义一个邻接表的边信息结构体,将邻接矩阵的边信息转换成邻接表的边信息存储到邻接边的单链表中。

第二章系统流程图第三章数据结构和算法(1)有向图顶点的数据类型DataType 定义如下:typedef int DataType ;(2)邻接矩阵存储结构下图的结构体定义如下:typedef struct{SeqList Vertices;int edge[MaxVertices][MaxVertices];int numOfEdges;}AdjMGraph;(3)邻接矩阵存储结构下图的边信息结构体定义如下:typedef struct{int row;int col;int weight;}RowColWeight;(4)邻接表存储结构下图的结构体定义如下:typedef struct Node{int dest;struct Node *next;}Edge;typedef struct{DataType data;int sorce;Edge *adj;}AdjLHeight;typedef struct{AdjLHeight a[MaxVertices];int numOfVerts;int numOfEdges;}AdjLGraph;(5)邻接表存储结构下图的边信息结构体定义如下:typedef structint row;int col;}RowCol;(6)顺序循环队列的结构体定义如下:typedef struct{DataType queue[MaxQueueSize];int rear;int front;int count;}SeqCQueue;(7)顺序表的结构体定义如下:typedef struct{DataType list[MaxSize];int size;}SeqList;第四章核心代码分析源程序存放在八个文件夹中,文件SeqList.h是顺序表的结构体定义和操作函数,文件SeqCQueue.h是顺序循环队列的结构体定义和操作函数,文件AdjMGraph.h是邻接矩阵存储结构下图的结构体定义和操作函数,文件AdjMGraphCreate.h是邻接矩阵存储结构下图的创建函数,文件AdjLGraph.h是邻接表存储结构下图的结构体定义和操作函数,文件AdjLGraphCreate.h 是邻接表存储结构下图的创建函数,文件AdjMGraphTraverse.h是邻接矩阵存储结构下图的深度优先遍历和广度优先遍历操作函数,文件图的基本操作与实现.c是主函数。

(1)/* 文件SeqList.h */typedef struct{DataType list[MaxSize];int size;}SeqList;void ListInitiate(SeqList *L)L->size=0;}int ListLength(SeqList L){return L.size;}int ListInsert(SeqList *L,int i,DataType x){int j;if(L->size>=MaxSize){printf("数组已满无法插入!\n");return 0;}else if(i<0||i>L->size){printf("参数不合法!\n");return 0;}else{for(j=L->size;j>i;i--)L->list[j]=L->list[j-1];L->list[i]=x;L->size++;return 1;}}int ListDelete(SeqList *L,int i,DataType *x){int j;if(L->size<=0){printf("顺序表已空无数据元素可删!\n");return 0;}else if(i<0||i>L->size-1){printf("参数i不合法!\n");return 0;}else{*x=L->list[i];for(j=i+1;j<=L->size-1;j++)L->list[j-1]=L->list[j];L->size--;return 1;}}int ListGet(SeqList L,int i,DataType *x){if(i<0||i>L.size-1){printf("参数i不合法!\n");return 0;}else{*x=L.list[i];return 1;}}(2)/* 文件SeqCQueue.h*/typedef struct{DataType queue[MaxQueueSize];int rear;int front;int count;}SeqCQueue;void QueueInitiate(SeqCQueue *Q){Q->rear=0;Q->front =0;Q->count =0;}int QueueNotEmpty(SeqCQueue Q){if(Q.count !=0) return 1;else return 0;}int QueueAppend(SeqCQueue *Q,DataType x) {if(Q->count>0&&Q->rear==Q->front){printf("队列已满无法插入!");return 0;}else{Q->queue [Q->rear]=x;Q->rear =(Q->rear +1)%MaxQueueSize;Q->count ++;return 1;}}int QueueDelete(SeqCQueue *Q,DataType *d) {if(Q->count ==0){printf("队列已空无数据出队列!\n");return 0;}else{*d=Q->queue[Q->front];Q->front=(Q->front+1)%MaxQueueSize;Q->count --;return 1;}}int QueueGet(SeqCQueue Q,DataType*d){if(Q.count ==0){printf("队列已空无数据出队列!\n");return 0;}else{*d=Q.queue [Q.front ];return 1;}}(3)/* 文件AdjMGraph.h*/#include"SeqList.h"typedef struct{SeqList Vertices; //存放结点的顺序表int edge[MaxVertices][MaxVertices]; //存放边的邻接矩阵int numOfEdges; //边的条数}AdjMGraph; //边的结构体定义void Initiate(AdjMGraph *G,int n) //初始化{int i,j;for(i=0;i<n;i++)for(j=0;j<n;j++){if(i==j)G->edge[i][j]=0;elseG->edge[i][j]=MaxWeight;}G->numOfEdges=0; //边的条数置为0ListInitiate(&G->Vertices); //顺序表初始化}void InsertVertex(AdjMGraph *G,DataType vertex) //在图G中插入结点vertex {ListInsert(&G->Vertices,G->Vertices.size,vertex); //顺序表尾插入}void InsertEdge(AdjMGraph *G,int v1,int v2,int weight)//在图G中插入边<v1,v2>,边<v1,v2>的权为weight{if(v1<0||v1>G->Vertices.size||v2<0||v2>G->Vertices.size){printf("参数v1或v2越界出错!\n");exit(1);}G->edge[v1][v2]=weight;G->numOfEdges++;}void DeleteEdge(AdjMGraph *G,int v1,int v2) //在图中删除边<v1,v2> {if(v1<0||v1>G->Vertices.size||v2<0||v2>G->Vertices.size||v1==v2) {printf("参数v1或v2越界出错!\n");exit(1);}if(G->edge[v1][v2]==MaxWeight||v1==v2){printf("该边不存在!\n");exit(0);}G->edge[v1][v2]=MaxWeight;G->numOfEdges--;}void DeleteVerten(AdjMGraph *G,int v) //删除结点v{int n=ListLength(G->Vertices),i,j;DataType x;for(i=0;i<n;i++) //计算删除后的边数{for(j=0;j<n;j++)if((i==v||j==v)&&G->edge[i][j]>0&&G->edge[i][j]<MaxWeight) G->numOfEdges--; //计算被删除边}for(i=v;i<n;i++) //删除第v行{for(j=0;j<n;j++)G->edge[i][j]=G->edge[i+1][j];}for(i=0;i<n;i++) //删除第v列{for(j=v;j<n;j++)G->edge[i][j]=G->edge[i][j+1];}ListDelete(&G->Vertices,v,&x); //删除结点v}int GetFistVex(AdjMGraph *G,int v)//在图G中寻找序号为v的结点的第一个邻接结点//如果这样的邻接结点存在,返回该邻接结点的序号;否则,返回-1{int col;if(v<0||v>G->Vertices.size){printf("参数v1越界出错!\n");exit(1);}for(col=0;col<G->Vertices.size;col++)if(G->edge[v][col]>0&&G->edge[v][col]<MaxWeight)return col;return -1;}int GetNextVex(AdjMGraph*G,int v1,int v2)//在图中寻找v1结点的邻接结点v2的下一个邻接结点//如果这样的结点存在,返回该邻接结点的序号;否则,返回-1//v1和v2都是相应结点的序号{int col;if(v1<0||v1>G->Vertices.size||v2<0||v2>G->Vertices.size){printf("参数v1或v2越界出错!\n");exit(1);}for(col=v2+1;col<G->Vertices.size;col++)if(G->edge[v1][col]>0&&G->edge[v1][col]<MaxWeight)return col;return -1;}//输出图G的邻接矩阵void Print(AdjMGraph *G){int i,j;for(i=0;i<G->Vertices.size;i++){for(j=0;j<G->Vertices.size;j++)printf("%6d ",G->edge[i][j]);printf("\n");}}//邻接矩阵存储结构下求出每个顶点的度并输出void MVertices(AdjMGraph *G,DataType a[]){int i,j,m;DataType b[MaxVertices];//用数组b[]记录相应结点的度for(i=0;i<G->Vertices.size;i++)b[i]=0; //置0printf("邻接矩阵存储结构下图的顶点的度为:\n");for(m=0;m<G->Vertices.size;m++) //求出每个结点的度{for(i=0;i<G->Vertices.size;i++)for(j=0;j<G->Vertices.size;j++){if(i==m&&G->edge[i][j]>0&&G->edge[i][j]<MaxWeight)//求出邻接矩阵第i行权值存在的边的个数,当边<m,j>存在时,b[m]加1 b[m]++;if(j==m&&i!=m&&G->edge[i][j]>0&&G->edge[i][j]<MaxWeight)//求出邻接矩阵第j列权值存在的边的个数,当边<i,m>存在时,b[m]加1 b[m]++;}printf("顶点%d的度为:%d\n",a[m],b[m]);}}//查找图G中是否存在点vint ChaZhao(AdjMGraph *G,int v){if(0<=v&&v<G->Vertices.size){printf("存在顶点%d\n",v);return 1;}else{printf("不存在顶点%d\n",v);return 0;}}//删除查找到的结点v并删除该结点及与之相关的边void MDelete(AdjMGraph *G,int v){int i;for(i=0;i<G->Vertices.size;i++){if(G->edge[v][i]>0&&G->edge[v][i]<MaxWeight)//当邻接矩阵的第v行有边<v,i>存在时,删除边<v,i>DeleteEdge(G,v,i);if(G->edge[i][v]>0&&G->edge[i][v]<MaxWeight)//当邻接矩阵的第j行有边<i,v>存在时,删除边<i,v>DeleteEdge(G,i,v);}DeleteVerten(G,v);//删除结点v}(4)/* 文件AdjMGraphCreate.h*/typedef struct{int row; //行下标int col; //列下标int weight; //权值}RowColWeight; //边信息结构体定义void CreatGraph(AdjMGraph *G,DataType v[],int n,RowColWeight E[],int e) //在图G中插入n个结点信息v和e条边信息E{int i,k;Initiate(G,n); //结点顺序表初始化for(i=0;i<n;i++)InsertVertex(G,v[i]); //结点插入for(k=0;k<e;k++)InsertEdge(G,E[k].row,E[k].col,E[k].weight); //边插入}(5)/* 文件AdjLGraph.h *///邻接表的存储结构typedef struct Node{int dest; //邻接边的弧头结点序号struct Node *next;}Edge; //邻接边单链表的结点结构体t ypedef struct{DataType data; //结点数据元素int sorce; //邻接边的弧尾结点序号Edge *adj; //邻接边的头指针}AdjLHeight; //数组的数据元素类型结构体typedef struct{AdjLHeight a[MaxVertices]; //邻接表数组int numOfVerts; //结点个数int numOfEdges; //边个数}AdjLGraph; //邻接表结构体//初始化操作函数void LAdjInitiate(AdjLGraph *G){int i;G->numOfVerts=0;G->numOfEdges=0;for(i=0;i<MaxVertices;i++){G->a[i].sorce=i;G->a[i].adj=NULL;}}//撤销操作函数void LAdjDestroy(AdjLGraph *G)//撤销图G中的所有邻接边单链表{int i;Edge *p,*q;for(i=0;i<G->numOfVerts;i++){p=G->a[i].adj;while(p!=NULL){q=p->next;free(p);p=q;}}}//插入结点操作函数void LInsertVertex(AdjLGraph *G,int i,DataType vertex)//在图G中的第i(0<=i<MaxVertices)个位置插入结点数据元素vertex {if(i>=0&&i<MaxVertices){G->a[i].data=vertex; //存储结点数据元素vertexG->numOfVerts++; //个数加1}elseprintf("结点越界");}//插入边操作函数void LInsertEdge(AdjLGraph *G,int v1,int v2)//在图G中加入边<v1,v2>的信息{Edge *p; //定义一个邻接边指针if(v1<0||v1>=G->numOfVerts||v2<0||v2>=G->numOfVerts){printf("参数v1或v2越界出错");exit(0);}p=(Edge *)malloc(sizeof(Edge)); //申请邻接边单链表结点空间p->dest=v2; //置邻接边弧头序号p->next=G->a[v1].adj; //新结点插入单链表的表头G->a[v1].adj=p; //头指针指向新的单链表表头G->numOfEdges++; //边数个数加1}//删除边操作函数void LDeleteEdge(AdjLGraph *G,int v1,int v2)//删除图G中的边<v1,v2>信息{Edge *curr,*pre;if(v1<0||v1>=G->numOfVerts||v2<0||v2>=G->numOfVerts) {printf("参数v1或v2越界出错!");exit(0);}pre=NULL;curr=G->a[v1].adj;while(curr!=NULL&&curr->dest!=v2)//在v1结点的邻接边单链表中查找v2结点{pre=curr;curr=curr->next;}//删除表示邻接边<v1,v2>的结点if(curr!=NULL&&curr->dest==v2&&pre==NULL)//当邻接边<v1,v2>的结点是单链表的第一个结点时{G->a[v1].adj=curr->next;free(curr);G->numOfEdges--;}else if(curr!=NULL&&curr->dest==v2&&pre!=NULL)//当邻接边<v1,v2>的结点不是单链表的第一个结点时{pre->next=curr->next;free(curr);G->numOfEdges--;}else//当邻接边<v1,v2>结点不存在时printf("边<v1,v2>不存在时");}//取第一个邻接结点int LGetFirstVex(AdjLGraph *G,int v)//取图G中结点v的第一个邻接结点//取到时返回该邻接结点的对应序号,否则返回-1{Edge *p;if(v<0||v>G->numOfVerts){printf("参数v1或v2越界出错!");exit(0);}p=G->a[v].adj;if(p!=NULL)return p->dest; //返回该邻接结点的对应序号elsereturn -1; //返回-1}//取下一个邻接结点int LGetNextVex(AdjLGraph *G,int v1,int v2)//取图G中结点v1的邻接结点v2的下一个邻接结点//取到时返回该邻接结点的对应序号,否则返回-1{Edge *p;if(v1<0||v1>G->numOfVerts||v2<0||v2>G->numOfVerts) {printf("参数v1或v2越界出错!");exit(0);}p=G->a[v1].adj;while(p!=NULL) //寻找结点v1的邻接结点v2{if(p->dest!=v2){p=p->next;continue;}elsebreak;}p=p->next; //p指向邻接结点v2的下一个邻接结点if(p!=NULL)return p->dest; //返回该邻接结点的对应序号elsereturn -1; //返回-1}//邻接表存储下求每个顶点的度并输出结果void LVertices(AdjLGraph *G,DataType a[]){printf("邻接表存储结构下的图的顶点的度为:\n");int OutDegree[MaxVertices],InDegree[MaxVertices];//定义一个出度和入度的数组int i;for(i=0;i<G->numOfVerts;i++) //首先将出度和入度数组的每个成员都置0{OutDegree[i]=0;InDegree[i]=0;}Edge *p; //定义一个邻接边指针for(i=0;i<G->numOfVerts;i++){p=G->a[i].adj; //指针指向a[i]的邻接边单链表头结点while(p!=NULL)//当p所指向的邻接边结点不空时{OutDegree[i]++; //出度加1InDegree[p->dest]++; //邻接边弧头结点的入度加1p=p->next; //p指向下一个邻接边结点}}for(i=0;i<G->numOfVerts;i++) //输出每个结点的度{printf("顶点%d的度为:",a[i]);printf("%d",OutDegree[i]+InDegree[i]); //每个结点的度即出度与入度相加的和printf("\n");}}//判断有向图G是否为强连通图int LianTong(AdjLGraph *G,DataType a[]){int i,b[MaxVertices],k=0;for(i=0;i<G->numOfVerts;i++)b[i]=0;Edge *q,*p; //定义一个邻接边指针for(i=0;i<G->numOfVerts;i++){q=G->a[i].adj;while(q!=NULL){b[i]++;q=q->next;}}for(i=0;i<G->numOfVerts;i++){if(b[i]==1)k++;}p=G->a[G->numOfVerts-1].adj;if(k==G->numOfVerts&&p->dest==a[0])return 1;elsereturn 0;}(6)/* 文件AdjLGraphCreate.h */typedef struct{int row; //行下标int col; //列下标}RowCol; //边信息结构体定义void CreatLGraph(AdjLGraph *G,DataType v[],int n,RowCol d[],int e) {int i,k;LAdjInitiate(G);for(i=0;i<n;i++)LInsertVertex(G,i,v[i]);for(k=0;k<e;k++)LInsertEdge(G,d[k].row,d[k].col);}(7)/* 文件AdjMGraphTraverse.h */void Visit(DataType item){printf("%d ",item);}void DepthFSearch(AdjMGraph G,int v,int visited[],void Visit(DataType item)) //连通图G以v为初始结点的访问操作为Visit()的深度优先遍历//数组visited标记了相应结点是否已访问过,0表示未访问,1表示已访问{int w;Visit(G.Vertices.list[v]); //访问结点vvisited[v]=1; //置已访问标记w=GetFistVex(&G,v); //取第一个邻接结点while(w!=-1){if(!visited[w])//非0 还未访问DepthFSearch(G,w,visited,Visit);w=GetNextVex(&G,v,w);}}void DepthFirstSearch(AdjMGraph G,void Visit(DataType item))//非连通图G的访问操作为Visit()的深度优先遍历{int i;int *visited=(int *)malloc(sizeof(int)*G.Vertices.size);for(i=0;i<G.Vertices.size;i++)visited[i]=0;for(i=0;i<G.Vertices.size;i++)if(!visited[i])DepthFSearch(G,i,visited,Visit);free(visited);}#include"SeqCQueue.h" //包括顺序循环队列void BroadFSearch(AdjMGraph G,int v,int visited[],void Visit(DataType item)) //连通图G以v为初始结点的访问操作为Visit()的广度优先遍历//数组visited标记了相应结点是否已访问过,0表示未访问,1表示已访问{DataType u,w;SeqCQueue queue;Visit(G.Vertices.list[v]); //访问结点vvisited[v]=1; //置已访问标记QueueInitiate(&queue); //队列初始化QueueAppend(&queue,v); //初始结点v入队列while(QueueNotEmpty(queue)) //队列非空时{QueueDelete(&queue,&u); //出队列w=GetFistVex(&G,u); //取结点u的第一个邻接结点while(w!=-1) //邻接结点w存在时{if(!visited[w]) //若没有访问过{Visit(G.Vertices.list[w]); //访问结点wvisited[w]=1; //置已访问标记QueueAppend(&queue,w); //结点w入队列}w=GetNextVex(&G,u,w); //取下一个邻接结点}}}void BroadFirstSearch(AdjMGraph G,void Visit(DataType item)) //非连通图G访问操作为Visit()的广度优先遍历{int i;int *visited=(int *)malloc(sizeof(int)*G.Vertices.size);for(i=0;i<G.Vertices.size;i++)visited[i]=0;for(i=0;i<G.Vertices.size;i++)if(!visited[i])BroadFSearch(G,i,visited,Visit);free(visited);}(8)/* 文件图的基本操作与实现.c */#include<stdio.h>#include<stdlib.h>#include<malloc.h>typedef int DataType;//定义DataType为整形#define MaxSize 100#define MaxVertices 10#define MaxEdges 100#define MaxWeight 10000 //定义无穷大的具体值#define MaxQueueSize 100#include "AdjMGraph.h"#include"AdjMGraphCreate.h"#include"AdjMGraphTraverse.h"#include"AdjLGraph.h"#include"AdjLGraphCreate.h"void main(){AdjMGraph g1; //定义一个邻接矩阵存储结构的图g1RowColWeight rcw[MaxEdges];//定义边信息数组int n,e,i,j;printf("请输入有向图的顶点数:");scanf("%d",&n);printf("请输入有向图的边数:");scanf("%d",&e);DataType a[MaxVertices];//定义一个数组存储顶点字符为整形printf("该图的%d个顶点字符分别为:",n);//输出每个顶点字符for(i=0;i<n;i++){a[i]=i;printf("%2d",a[i]);}printf("\n");//存储边的信息for(i=0;i<e;i++){printf("请输入一条边依附的顶点字符v1,v2及权值(v1,v2,w):");scanf("%d,%d,%d",&rcw[i].row,&rcw[i].col,&rcw[i].weight);}CreatGraph(&g1,a,n,rcw,e);//创建一个邻接矩阵存储结构的图g1printf("该图的邻接矩阵为:\n");Print(&g1);//输出图g1的邻接矩阵//求出邻接矩阵存储结构下图g1的每个顶点的度MVertices(&g1,a);AdjLGraph g2;//定义一个邻接表存储结构的图g2RowCol rwc[MaxEdges];//定义边信息数组//用邻接矩阵的信息生成邻接表for(i=0;i<e;i++){rwc[i].col=rcw[i].col;rwc[i].row=rcw[i].row;}CreatLGraph(&g2,a,g1.Vertices.size,rwc,g1.numOfEdges);//求出邻接表存储结构下图g2每个顶点的度LVertices(&g2,a);//判断图g1的连通性printf("图g1是否为强连通图:");if(LianTong(&g2,a)){printf("YES\n");printf("深度优先遍历序列为:");//对图g1作DFS遍历,输出DFS顶点序列DepthFirstSearch(g1,Visit);printf("\n");printf("广度优先遍历序列为:");//对图g1作BFS遍历,输出BFS顶点序列BroadFirstSearch(g1,Visit);}else{printf("NO\n");printf("深度优先遍历序列为:");DepthFirstSearch(g1,Visit);printf("\n");printf("广度优先遍历序列为:");BroadFirstSearch(g1,Visit);}printf("\n");//输入顶点x,查找图g1:若存在含x的顶点,则删除该结点及与之相关连的边, //并作DFS遍历否则输出信息"无x";int x;printf("请输入要查找的顶点:");scanf("%d",&x);if(ChaZhao(&g1,x)){MDelete(&g1,x);printf("删除顶点%d后的图的邻接矩阵为:\n",x);Print(&g1);printf("删除顶点%d后的深度优先遍历序列为:",x);DepthFirstSearch(g1,Visit);}elseprintf("不存在顶点%d\n",x);}第五章时间复杂度分析算法的时间复杂度和空间复杂度(1)图的邻接矩阵存储:空间复杂度为O(n2) 时间复杂度都为O(n)。

相关主题