数据结构之图(图的基本操作)
2014-04-06 18:56
435 查看
由于图的基本操作的代码较多,我放到这一章来写。图可以用两种方法来存储,但是本人偏爱链表的表示方法,所以以下代码也都是是基于邻接链表的存储方式。
//图的创建
//图的销毁
//向图中增加结点
//从图中删除一个结点
//向图中增加一条弧,有有向图和无向图之分
//从图中删除一条弧
//深度优先遍历
/* 以下存储结构参考严蔚敏版数据结构,不懂的可以翻阅查看 */ const int UNDIGRAPH = 0; //无向图 const int DIGRAPH = 1; //有向图 const int MAX_VERTEX_NUM = 20; typedef struct ArchNode { int vertexIndex; //该弧指向顶点在图中顶点数组的索引,对应vertexs[20]的下标 ArchNode *nextarc; //指向下一条弧的指针 InfoTypde info; //比如弧的权重 }ArchNode; typedef struct Vertex { VertexType data; //顶点信息 ArchNode *firstarc; //指向第一条弧的指针 }Vertex; //这样定义图有个坏处,一旦定义好,图中结点的个数就固定了! typedef struct Graph { Vertex *vertexs[MAX_VERTEX_NUM]; //存储顶点的数组,存放的是指向顶点的指针 int vexNum; //当前图中的定点数 int arcNum; //当前图中的弧的个数 int kind; //图的种类,有向图还是无向图 }Graph;
//图的创建
/* 初始条件:kind是图的类型,目前有有向图和无向图 两种. 返回值 :无。---大部分函数都无返回值,是对图的引用进行操作的 */ void createGraph(Graph *&G,int kind) { if(G) G = NULL; G = (Graph *)malloc(sizeof(struct Graph)); assert(NULL != G); for(int i = 0; i < MAX_VERTEX_NUM; ++i) { G->vertexs[i] = NULL; //初始化指向顶点的指针为NULL } G->kind = kind; //设置图的种类 G->vexNum = 0; //初始化图中顶点的个数 G->arcNum = 0; //初始化图中弧的个数 }
//图的销毁
/* 初始条件:G存在 返回值 :无。---大部分函数都无返回值,是对图的引用进行操作的 */ void destoryGraph(Graph *&G) { ArchNode *cur,*next; if(NULL == G) return; //遍历顶点 for(int i = 0; i < G->vexNum; ++i) { if(!G->vertexs[i]) continue; next = G->vertexs[i]->firstarc; cur = G->vertexs[i]->firstarc; while(cur) { next = cur->nextarc; free(cur); cur = next; } G->vertexs[i]->firstarc = NULL; } free(G); G = NULL; }
//向图中增加结点
//向图中增加结点 /* 初始条件:G存在,data是结点的数据值 */ void addVertexToGraph(Graph *&G,VertexType data) { if(G->vexNum >= MAX_VERTEX_NUM) { cout << "Too many vertex!" << endl; return ; } for(int i = 0; i < G->vexNum; ++i) { if(!G->vertexs[i]) continue; if(G->vertexs[i]->data == data) { cout << "Already exists!" << endl; return; //不允许重复 } } Vertex *pVeterx; pVeterx = (Vertex *)malloc(sizeof(struct Vertex)); pVeterx->data = data; pVeterx->firstarc = NULL; G->vertexs[G->vexNum] = pVeterx; G->vexNum++; }
//从图中删除一个结点
void delVertexFromGraph(Graph *&G,VertexType data) { bool haveThisVertex = false; ArchNode *cur,*next,*temp,*pre; Vertex *anotherVertex; if(NULL == G) return; if(G->vexNum <= 0) { cout << "Have no vertex!" << endl; return ; } for(int i = 0; i < G->vexNum; ++i) { if(!G->vertexs[i]) continue; if(G->vertexs[i]->data == data) { haveThisVertex = true; //以下循环用来删除顶点所指向的弧链表 next = cur = G->vertexs[i]->firstarc; if(G->kind == DIGRAPH) //如果是有向图 { while(cur) { next = cur->nextarc; free(cur); G->arcNum --; //弧的个数减一 cur = next; } G->vertexs[i] = NULL; } else if(G->kind == UNDIGRAPH) //如果是无向图,这个麻烦点 { while(cur) { //找到待删除的弧的另一个结点,将它的弧链表中指向被删除结点的弧也删掉 anotherVertex = G->vertexs[cur->vertexIndex]; //找到待删除弧对应的另一个结点 temp = anotherVertex->firstarc,pre = NULL; while(temp) //这个循环是为了删除另一个结点中保存弧信息 { if(temp->vertexIndex == i) { //如果是首节点 if(NULL == pre) //或者if(NULL == pre) { anotherVertex->firstarc = temp->nextarc; free(temp); } else { pre->nextarc = temp->nextarc; free(temp); } break; //找到即停止循环 } pre = temp; temp = temp->nextarc; } next = cur->nextarc; free(cur); G->arcNum --; //弧的个数减一 cur = next; } G->vertexs[i] = NULL; } for(int j = i; j < G->vexNum - 1; ++j) { G->vertexs[j] = G->vertexs[j + 1]; } G->vertexs[j] = NULL; // G->vexNum-- ; //结点的个数减一 break; } } if(!haveThisVertex) cout << "没有该结点!" << endl; }
//从图中查找一个值为指定值的结点的索引
//初始条件:G存在,data是指定结点的数据值 int findVertexIndexInGraph(const Graph *G,VertexType data) { if(NULL == G) return -1; for(int i = 0; i < G->vexNum; ++i) { if(!G->vertexs[i]) continue; if(G->vertexs[i]->data == data) { return i; break; } } return -1; }
//向图中增加一条弧,有有向图和无向图之分
//初始条件:G存在,指定起始点,和弧的权重 void addArchToGraph(Graph *&G,VertexType startData,VertexType endData,InfoTypde weight = 0) { ArchNode *pArchNode,*cur; //先要找到start和end if(NULL == G) return; int startVertexIndex = findVertexIndexInGraph(G,startData); int endVertexIndex = findVertexIndexInGraph(G,endData); cur = G->vertexs[startVertexIndex]->firstarc; while(cur) { if(cur->vertexIndex == endVertexIndex) { cout << "Already have this arch!" << endl; return ; } cur = cur->nextarc; } if(startVertexIndex >= 0 && endVertexIndex >= 0) { if(G->kind == DIGRAPH) //如果是有向图 { pArchNode = (ArchNode *)malloc(sizeof(struct ArchNode)); //创建一个弧结点 pArchNode->info = weight; pArchNode->nextarc = NULL; pArchNode->vertexIndex = endVertexIndex; cur = G->vertexs[startVertexIndex]->firstarc; if(NULL == cur) { G->vertexs[startVertexIndex]->firstarc = pArchNode; } else { while(cur->nextarc) { cur = cur->nextarc; } cur->nextarc = pArchNode; } G->arcNum ++; //弧的条数加一 } else if(G->kind == UNDIGRAPH) //如果是无向图 { pArchNode = (ArchNode *)malloc(sizeof(struct ArchNode)); //创建一个弧结点 pArchNode->info = weight; pArchNode->nextarc = NULL; pArchNode->vertexIndex = endVertexIndex; cur = G->vertexs[startVertexIndex]->firstarc; if(NULL == cur) { G->vertexs[startVertexIndex]->firstarc = pArchNode; } else { while(cur->nextarc) { cur = cur->nextarc; } cur->nextarc = pArchNode; } pArchNode = (ArchNode *)malloc(sizeof(struct ArchNode)); //再创建一个弧结点 pArchNode->info = weight; pArchNode->nextarc = NULL; pArchNode->vertexIndex = startVertexIndex; cur = G->vertexs[endVertexIndex]->firstarc; if(NULL == cur) { G->vertexs[endVertexIndex]->firstarc = pArchNode; } else { while(cur->nextarc) { cur = cur->nextarc; } cur->nextarc = pArchNode; } G->arcNum ++; //弧的条数加一 } } else { cout << "起点或终点不存在!" << endl; return ; } }
//从图中删除一条弧
//初始条件:G存在,指定要删除弧连接的两个顶点 void delArchFromGraph(Graph *&G,VertexType startData,VertexType endData) { ArchNode *cur,*pre; //先要找到start和end if(NULL == G) return; int startVertexIndex = findVertexIndexInGraph(G,startData); int endVertexIndex = findVertexIndexInGraph(G,endData); if(startVertexIndex >= 0 && endVertexIndex >= 0) { if(G->kind == DIGRAPH) { cur = G->vertexs[startVertexIndex]->firstarc,pre = NULL; while(cur) { if(cur->vertexIndex == endVertexIndex) { break; } pre = cur; cur = cur->nextarc; } if(NULL == cur) { cout << "这两个结点之间没有弧!" << endl; return ; } else { if(NULL == pre) //是首节点 G->vertexs[startVertexIndex]->firstarc = cur->nextarc; else pre->nextarc = cur->nextarc; free(cur); G->arcNum --; } } else if(G->kind == UNDIGRAPH) { cur = G->vertexs[startVertexIndex]->firstarc,pre = NULL; while(cur) { if(cur->vertexIndex == endVertexIndex) { break; } pre = cur; cur = cur->nextarc; } if(NULL == cur) { cout << "这两个结点之间没有弧!" << endl; return ; } else { if(NULL == pre) //是首节点 G->vertexs[startVertexIndex]->firstarc = cur->nextarc; else pre->nextarc = cur->nextarc; free(cur); //G->arcNum --; } cur = G->vertexs[endVertexIndex]->firstarc,pre = NULL; while(cur) { if(cur->vertexIndex == startVertexIndex) { break; } pre = cur; cur = cur->nextarc; } if(NULL == cur) { cout << "这两个结点之间没有弧!" << endl; return ; } else { if(NULL == pre) //是首节点 G->vertexs[endVertexIndex]->firstarc = cur->nextarc; else pre->nextarc = cur->nextarc; free(cur); G->arcNum --; } } } else { cout << "起点或终点不存在!" << endl; return ; } }
//深度优先遍历
//初始条件:图G存在 void DFSdetails(const Graph *G,int i,int satusArr[]) { ArchNode *cur; if(satusArr[i] == 1 ) return; cout << G->vertexs[i]->data << " "; satusArr[i] = 1; cur = G->vertexs[i]->firstarc; while(cur) { DFSdetails(G,cur->vertexIndex,satusArr); cur = cur->nextarc; } } void DFS(const Graph *G) { int satusArr[MAX_VERTEX_NUM] = {0}; cout << "深度优先遍历:"; if(NULL == G) return; for(int i = 0; i < G->vexNum; ++i) { DFSdetails(G,i,satusArr); } cout << endl; }
相关文章推荐
- 数据结构之单链表、双链表的基本操作
- 数据结构—单链表的部分基本操作(C语言)
- 【数据结构与算法C】利用两个栈S1S2模拟一个队列,用栈的基本操作实线EnQueue,DeQueue,QueueEmpty
- 数据结构3:检验线性表的基本操作和线性表的合并
- 数据结构之队列的基本操作入队出队初始化删除-c++代码实现及运行实例结果
- mysql数据表的基本操作:表结构操作,字段操作
- 数据结构之数组定义及基本操作
- 数据结构——栈的基本操作
- 数据结构之——队列的基本操作
- 数据库学习--B树(B-Tree)的由来、数据结构、基本操作以及数据库索引的应用
- 数据结构中顺序表的基本操作(纯C语言)
- 数据结构—基本树的操作小结
- 【数据结构】顺序栈的基本操作操作---C/C++
- 【数据结构】顺序表的基本操作
- 数据结构——字符串的基本操作
- 数据结构——树(2)——二叉堆的基本操作原理
- 数据结构与算法:顺序串基本操作
- 数据结构之队列的基本操作入队出队初始化删除-c++代码实现及运行实例结果
- (总结)数据结构之链表的基本操作说明和示例(待补充)
- 数据结构(五)树2:树的基本操作