标签:无向图的深度优先生成树 无向图的广度优先生成树 无向图的生成森林 无向图的深度优先生成森林 无限图的广度优先恒昌森林
图的深度优先遍历 和 广度 优先 遍历 算法中的 每一次 最外层 循环 都 产生 一个 无向图 的 连通分量,每一个连通分量,都可以产生一个生成树,将这些生成树合在 一起 就是 一个 森林。 用 树的 孩子 兄弟 链表 表示法 来 表示 这个 森林, 就是 这一节 算法的 内容。
深度优先森林 代码 :
//深度优先生成森林 void dfsTree(AMLGraph g,int i,Tree * t,bool isVisited[]){ isVisited[i] = true; bool isFirst = true; Tree p,q = NULL; for (int next = firstAdj(g,i); next != -1; next = nextAdj(g,i,next)){ if (isVisited[next] == false){ p = makeTreeNode(g.adjMuList[next].vexName); if (isFirst){ (*t)->firstChild = p,isFirst = false; } else{ q->nextSibling = p; } q = p; dfsTree(g,next,&q,isVisited); } } } void dfsForest(AMLGraph g,Tree * t){ bool isVisited[MAX_VEX_NUM] = {false}; *t = NULL; Tree p,q; for (int i = 0; i < g.vexNum; i++){ if (isVisited[i] == false){ p = makeTreeNode(g.adjMuList[i].vexName);//每一次循环都是一颗生成树. if (*t == NULL){//第一个是根节点 *t = p; } else{//其余生成树 是 第一颗 生成树的 兄弟 q->nextSibling = p; } q = p;//保存上一个树 dfsTree(g,i,&q,isVisited); } } }广度优先生成森林代码:
//广度优先生成森林 void bfsForest(AMLGraph g,Tree * t){ bool isVisited[MAX_VEX_NUM] = {false}; Tree treeArray[MAX_VEX_NUM] = {NULL};//记录所有顶点的 树节点坐标. //因为要 找到 遍历的 树节点的 父亲 是谁.(这一句p = treeArray[top];) Tree p,q,r; LinkQueue queue; queueInit(&queue); for (int i = 0; i < g.vexNum; i++){ if (isVisited[i] == false){ p = makeTreeNode(g.adjMuList[i].vexName); if (i == 0){//第一颗生成树.. *t = p; } else{//其他生成树是 第一颗生成树的 孩子兄弟链表的 兄弟 //(*t)->nextSibling = p; 这样写 就只有 一个兄弟节点了.. q->nextSibling = p; } q = p; treeArray[i] = p; isVisited[i] = true; enqueue(&queue,i); while (!queueEmpty(queue)){ int top; dequeue(&queue,&top); bool isFirst = true; for (int next = firstAdj(g,top);next != -1; next = nextAdj(g,top,next)){ if (isVisited[next] == false){ isVisited[next] = true; r = makeTreeNode(g.adjMuList[next].vexName); treeArray[next] = r; if (isFirst){ p = treeArray[top]; p->firstChild = r,isFirst = false; } else{ p->nextSibling = r; } p = r; enqueue(&queue,next); } } } } } queueDestory(&queue); }在写广度 优先生成森林代码中,犯了 两个错误:
1.
//(*t)->nextSibling = p; 这样写 就只有 一个兄弟节点了..
q->nextSibling = p;
2.
没有 写 这句话:
p = treeArray[top];
后来 将所有 顶点的坐标 存到 数组中,好查找 节点的 父亲节点。
详细源代码如下:
工程文件网盘地址:点击打开链接
// AMLGraph.cpp : 定义控制台应用程序的入口点。 //无向图的邻接多重表 #include "stdafx.h" #include <cstdlib> #include "queue.h" #include "BinaryTree.h" #define MAX_VEX_NUM 20 enum E_VisitIf { unvisited = 0, visited = 1, }; struct ArcNode { E_VisitIf mark; int iIndex,jIndex;//顶点i,j在图中的位置 ArcNode * iNext;//与i顶点点相关的下一个弧 ArcNode * jNext;//与j顶点点相关的下一个弧 }; struct VNode { char vexName; ArcNode * head;//头指针 }; struct AMLGraph { VNode adjMuList[MAX_VEX_NUM];//顶点数组 int vexNum,arcNum; }; //获取弧 的 头节点 ArcNode * getHeadNode(){ ArcNode * pNode = (ArcNode *)malloc(sizeof(ArcNode)); if (pNode){ pNode->iIndex = pNode->jIndex = -1; pNode->iNext = pNode->jNext = NULL; pNode->mark = unvisited; } return pNode; } ArcNode * getArcNode(int iIndex,int jIndex){ ArcNode * pNode = getHeadNode(); if (pNode){ pNode->iIndex = iIndex; pNode->jIndex = jIndex; } return pNode; } int vexLocation(AMLGraph g,char vex){ for (int i = 0; i < g.vexNum; i++){ if (g.adjMuList[i].vexName == vex){ return i; } } return -1; } void createGrahp(AMLGraph * g){ printf("输入图的顶点数 和 边(弧)数\n"); scanf("%d%d%*c",&g->vexNum,&g->arcNum); //构造顶点集 printf("请输入顶点集\n"); for (int i = 0; i < g->vexNum; i++){ char name; scanf("%c",&name); g->adjMuList[i].vexName = name; g->adjMuList[i].head = getHeadNode();//建立 头节点,并让头指针指向头节点 } //构造顶点关系 fflush(stdin); printf("请输入顶点的关系\n"); for (int i = 0; i < g->arcNum; i++){ char vex1,vex2; scanf("%c%c%*c",&vex1,&vex2); int location1 = vexLocation(*g,vex1); int location2 = vexLocation(*g,vex2); ArcNode * pNode = getArcNode(location1,location2); pNode->iNext = g->adjMuList[location1].head->iNext; g->adjMuList[location1].head->iNext = pNode; pNode->jNext = g->adjMuList[location2].head->iNext; g->adjMuList[location2].head->iNext = pNode; } } void destoryGraph(AMLGraph * g){ for (int i = 0; i < g->vexNum; i++){ ArcNode * next = g->adjMuList[i].head->iNext; while (next != NULL){ ArcNode * freeNode = next; next = next->iIndex == i ? next->iNext : next->jNext; if (freeNode->iIndex == i){////只释放 iIndex 等于 i的节点,要不会多次释放 free(freeNode); } } free(g->adjMuList[i].head); g->adjMuList[i].head = NULL; g->adjMuList[i].vexName = ' '; g->vexNum = g->arcNum = 0; } } //顶点vex1 和顶点vex2 是否相邻 bool graphIsAdj(AMLGraph g,char vex1,char vex2){ int location = vexLocation(g,vex1); ArcNode * next = g.adjMuList[location].head->iNext; while (next != NULL){ if (g.adjMuList[next->iIndex].vexName == vex2 || g.adjMuList[next->jIndex].vexName == vex2){ return true; } next = next->iIndex == location ? next->iNext : next->jNext; } return false; } int graphDegree(AMLGraph g,char vex){ int degree = 0; int location = vexLocation(g,vex); ArcNode * next = g.adjMuList[location].head->iNext;//计算所有出度 while (next != NULL){ degree++; next = next->iIndex == location ? next->iNext : next->jNext; } return degree; } //插入边(弧) void insertArc(AMLGraph * g,char vex1,char vex2){ int location1 = vexLocation(*g,vex1); int location2 = vexLocation(*g,vex2); ArcNode * node = getArcNode(location1,location2); node->iNext = g->adjMuList[location1].head->iNext; g->adjMuList[location1].head->iNext = node; node->jNext = g->adjMuList[location2].head->iNext; g->adjMuList[location2].head->iNext = node; g->arcNum ++; } //删除边(弧) void deleteArc(AMLGraph * g,char vex1,char vex2){ g->arcNum--; int location1 = vexLocation(*g,vex1); int location2 = vexLocation(*g,vex2); ArcNode * next = g->adjMuList[location1].head->iNext; ArcNode * pre = g->adjMuList[location1].head; while (next != NULL){ if (next->iIndex == location2){ if (pre == g->adjMuList[location1].head || pre->iIndex == location1){//删除的是第一个节点.或者 前驱的index = location1 pre->iNext = next->jNext; } else{ pre->jNext = next->jNext; } break; } else if(next->jIndex == location2){ if (pre == g->adjMuList[location1].head || pre->iIndex == location1){//删除的是第一个节点.或者 前驱的index = location1 pre->iNext = next->iNext; } else{ pre->jNext = next->iNext; } break; } pre = next; next = next->iIndex == location1 ? next->iNext : next->jNext; } next = g->adjMuList[location2].head->iNext; pre = g->adjMuList[location2].head; while (next != NULL){ if (next->iIndex == location1){ if (pre == g->adjMuList[location2].head || pre->iIndex == location2){//删除的是第一个节点.或者 前驱的index = location1 pre->iNext = next->jNext; } else{ pre->jNext = next->jNext; } free(next); break; } else if(next->jIndex == location1){ if (pre == g->adjMuList[location2].head || pre->iIndex == location2){//删除的是第一个节点.或者 前驱的index = location1 pre->iNext = next->iNext; } else{ pre->jNext = next->iNext; } free(next); break; } pre = next; next = next->iIndex == location2 ? next->iNext : next->jNext; } } //插入顶点 void insertVex(AMLGraph * g, char vex){ if (g->vexNum < MAX_VEX_NUM){ g->adjMuList[g->vexNum].vexName = vex; g->adjMuList[g->vexNum].head = getHeadNode(); g->vexNum++; } } //删除顶点 void deleteVex(AMLGraph * g,char vex){ int location = vexLocation(*g,vex); //删除顶点 同样需要 遍历整个 图 查找 与 vex 相关的弧节点 for (int i = 0; i < g->vexNum; i++){ ArcNode * next = g->adjMuList[i].head->iNext; while (next != NULL){ if (next->iIndex == location || next->jIndex == location){ ArcNode * delNode = next; next = next->iIndex == location ? next->iNext : next->jNext; char delData1 = g->adjMuList[delNode->iIndex].vexName; char delData2 = g->adjMuList[delNode->jIndex].vexName; deleteArc(g,delData1,delData2); } else{ next = next->iIndex == location ? next->iNext : next->jNext; } } } //更改因删除顶点 而导致的元素位置变化.. for (int i = 0; i < g->vexNum; i++){ ArcNode * next = g->adjMuList[i].head->iNext; while (next != NULL){ if (next->iIndex == i){ if(next->iIndex > location){ next->iIndex --; } if(next->jIndex > location){ next->jIndex --; } } next = next->iIndex == location ? next->iNext : next->jNext; } } free(g->adjMuList[location].head);//释放头节点 //vex下面的 顶点上移 for (int i = location + 1; i < g->vexNum; i++){ g->adjMuList[i-1] = g->adjMuList[i]; } g->vexNum --; } void printGrahp(AMLGraph g){ for (int i = 0; i < g.vexNum; i++){ printf("%c的 邻接点有:",g.adjMuList[i].vexName); ArcNode * next = g.adjMuList[i].head->iNext;//删除所有弧尾 while (next != NULL){ int index = next->iIndex == i ? next->jIndex : next->iIndex; printf("%c",g.adjMuList[index].vexName); next = next->iIndex == i ? next->iNext : next->jNext; } printf("\n"); } } int firstAdj(AMLGraph g,int location){ ArcNode * next = g.adjMuList[location].head->iNext; if (next != NULL) { int index = next->iIndex == location ? next->jIndex : next->iIndex; return index; } return -1; } int nextAdj(AMLGraph g,int location1 ,int location2){ ArcNode * next = g.adjMuList[location1].head->iNext; while (next != NULL){ if (next->iIndex == location2 || next->jIndex == location2){ next = next->iIndex == location1 ? next->iNext : next->jNext; break; } next = next->iIndex == location1 ? next->iNext : next->jNext; } if (next != NULL){ int index = next->iIndex == location1 ? next->jIndex : next->iIndex; return index; } return -1; } /* void dfs(AMLGraph g,int i,bool * isVisitedArray){ printf("%c",g.adjMuList[i].vexName); isVisitedArray[i] = true; for (int next = firstAdj(g,i); next != -1 ; next = nextAdj(g,i,next)){ if (isVisitedArray[next] == false){ dfs(g,next,isVisitedArray); } } } //深度优先搜索遍历 void dfsTraver(AMLGraph g){ bool isVisited[MAX_VEX_NUM] = {false}; printf("----------深度优先遍历------------------\n"); for (int i = 0; i < g.vexNum; i++){ if (isVisited[i] == false){ dfs(g,i,isVisited); } } printf("\n"); } //广度优先搜索遍历 void bfsTraverse(AMLGraph g){ bool isVisited[MAX_VEX_NUM] = {false}; printf("----------广度优先遍历------------------\n"); LinkQueue queue; queueInit(&queue); for (int i = 0; i < g.vexNum; i++){ if (isVisited[i] == false){ printf("%c",g.adjMuList[i].vexName); isVisited[i] = true; enqueue(&queue,i); while (!queueEmpty(queue)){ int top; dequeue(&queue,&top); for (int next = firstAdj(g,top);next != -1 ; next = nextAdj(g,top,next)){ if (isVisited[next] == false){ printf("%c",g.adjMuList[next].vexName); isVisited[next] = true; enqueue(&queue,next); } } } } } queueDestory(&queue); } void dfsTree(AMLGraph g,int v,Tree * t,bool * isVisited){ isVisited[v] = true; bool first = true; Tree p,q= NULL; for (int next = firstAdj(g,v);next != -1 ;next = nextAdj(g,v,next)){ if (isVisited[next] == false){ p = makeTreeNode(g.adjMuList[next].vexName); if (first){ (*t)->firstChild = p;first = false; } else{ q->nextSibling = p; } q = p; dfsTree(g,next,&q,isVisited); } } } //深度优先遍历生成森林 void dfsForest(AMLGraph g,Tree * tree){ bool isVisited[MAX_VEX_NUM] = {false}; *tree = NULL; Tree p,q; for (int i = 0; i <g.vexNum ; i++){ if (isVisited[i] == false){ p = makeTreeNode(g.adjMuList[i].vexName); if (!*tree){ *tree = p;//根节点. } else{ q->nextSibling = p; } } q = p;//q指向当前生成树的根.. dfsTree(g,i,&p,isVisited); } } */ void dfs(AMLGraph g,int i,bool isVisited[]){ printf("%c",g.adjMuList[i].vexName); isVisited[i] = true; for (int next = firstAdj(g,i); next != -1; next = nextAdj(g,i,next)){ if (isVisited[next] == false){ dfs(g,next,isVisited); } } } //深搜 void dfsTraverse(AMLGraph g){ bool isVisited[MAX_VEX_NUM] = {false}; printf("---------深度优先搜索遍历---------\n"); for (int i = 0; i < g.vexNum; i++){ if (isVisited[i] == false){//未访问过 dfs(g,i,isVisited); } } printf("\n"); } //广搜 void bfsTraverse(AMLGraph g){ bool isVisited[MAX_VEX_NUM] = {false}; printf("---------广度优先搜索遍历---------\n"); LinkQueue queue; queueInit(&queue); for (int i = 0; i < g.vexNum; i++){ if (isVisited[i] == false){ enqueue(&queue,i); printf("%c",g.adjMuList[i].vexName); isVisited[i] = true; while (!queueEmpty(queue)){ int top; dequeue(&queue,&top); for (int next = firstAdj(g,top); next != -1; next = nextAdj(g,top,next)){ if (isVisited[next] == false){ printf("%c",g.adjMuList[next].vexName); isVisited[next] = true; enqueue(&queue,next); } } } } } queueDestory(&queue); printf("\n"); } //深度优先生成森林 void dfsTree(AMLGraph g,int i,Tree * t,bool isVisited[]){ isVisited[i] = true; bool isFirst = true; Tree p,q = NULL; for (int next = firstAdj(g,i); next != -1; next = nextAdj(g,i,next)){ if (isVisited[next] == false){ p = makeTreeNode(g.adjMuList[next].vexName); if (isFirst){ (*t)->firstChild = p,isFirst = false; } else{ q->nextSibling = p; } q = p; dfsTree(g,next,&q,isVisited); } } } void dfsForest(AMLGraph g,Tree * t){ bool isVisited[MAX_VEX_NUM] = {false}; *t = NULL; Tree p,q; for (int i = 0; i < g.vexNum; i++){ if (isVisited[i] == false){ p = makeTreeNode(g.adjMuList[i].vexName);//每一次循环都是一颗生成树. if (*t == NULL){//第一个是根节点 *t = p; } else{//其余生成树 是 第一颗 生成树的 兄弟 q->nextSibling = p; } q = p;//保存上一个树 dfsTree(g,i,&q,isVisited); } } } //广度优先生成森林 void bfsForest(AMLGraph g,Tree * t){ bool isVisited[MAX_VEX_NUM] = {false}; Tree treeArray[MAX_VEX_NUM] = {NULL};//记录所有顶点的 树节点坐标. //因为要 找到 遍历的 树节点的 父亲 是谁.(这一句p = treeArray[top];) Tree p,q,r; LinkQueue queue; queueInit(&queue); for (int i = 0; i < g.vexNum; i++){ if (isVisited[i] == false){ p = makeTreeNode(g.adjMuList[i].vexName); if (i == 0){//第一颗生成树.. *t = p; } else{//其他生成树是 第一颗生成树的 孩子兄弟链表的 兄弟 //(*t)->nextSibling = p; 这样写 就只有 一个兄弟节点了.. q->nextSibling = p; } q = p; treeArray[i] = p; isVisited[i] = true; enqueue(&queue,i); while (!queueEmpty(queue)){ int top; dequeue(&queue,&top); bool isFirst = true; for (int next = firstAdj(g,top);next != -1; next = nextAdj(g,top,next)){ if (isVisited[next] == false){ isVisited[next] = true; r = makeTreeNode(g.adjMuList[next].vexName); treeArray[next] = r; if (isFirst){ p = treeArray[top]; p->firstChild = r,isFirst = false; } else{ p->nextSibling = r; } p = r; enqueue(&queue,next); } } } } } queueDestory(&queue); } //邻接多重表 int _tmain(int argc, _TCHAR* argv[]) { AMLGraph g; createGrahp(&g); printGrahp(g); dfsTraverse(g); bfsTraverse(g); Tree tree; dfsForest(g,&tree); printf("\n----------深度优先遍历生成森林(先序遍历)------------------\n"); preOrderTraverse(tree); treeDestory(&tree); bfsForest(g,&tree); printf("\n----------广度优先遍历生成森林(先序遍历)------------------\n"); preOrderTraverse(tree); treeDestory(&tree); destoryGraph(&g); return 0; }
运行截图:
看数据结构写代码(40) 无向图的深度优先生成树与广度优先生成树
标签:无向图的深度优先生成树 无向图的广度优先生成树 无向图的生成森林 无向图的深度优先生成森林 无限图的广度优先恒昌森林
原文地址:http://blog.csdn.net/fuming0210sc/article/details/45000965