1. #ifndef _PIC_H 
  2. #define _PIC_H 
  3.  
  4. #define MAXV 50 
  5.  
  6. typedef int InfoType; 
  7. typedef char ElemType; 
  8. int visited[MAXV]; 
  9. //邻接矩阵的数据类型  
  10. typedef struct  
  11.     int no;                     //顶点编号 
  12.     ElemType info;              //顶点信息 
  13. }VertexType;                    //顶点类型    
  14.  
  15. typedef struct  
  16.     int edge[MAXV][MAXV];       //邻接矩阵 
  17.     int n,e;                    //顶点数,边数 
  18.     VertexType vexs[MAXV]; 
  19. }MGraph;                        //图的定义 
  20.  
  21. //邻接表 
  22. typedef struct ANode            //边的定义 
  23.     int adjvex;                 //该边的终点位置 
  24.     struct ANode *nextarc;      //指向下一条边得指针 
  25.     InfoType  info;             //该边得相关信息  例如权 
  26. }ArcNode; 
  27.  
  28. typedef struct Vnode            //头结点的定义 
  29.     ElemType data;              //顶点的信息 
  30.     ArcNode *firstarc;          //指向这个顶点的第一条边 
  31. }VNode; 
  32.  
  33. typedef VNode *AdjList[MAXV]; 
  34. typedef struct                  //图的定义 
  35.     AdjList adjlist; 
  36.     int n,e; 
  37. }AGraph; 
  38.  
  39. #endif 
  40.  
  41. #include <stdio.h> 
  42. #include "stdlib.h" 
  43. #include "pic.h" 
  44.  
  45. void CreateMat(MGraph *g, int A[][MAXV], int n) //生成图的邻接矩阵 
  46.     int i=0,j=0; 
  47.     g->n = n; 
  48.     g->e = 0; 
  49.  
  50.     for(i=0; i<n; i++) 
  51.         for(j=0; j<n; j++)           
  52.             { 
  53.                 g->edge[i][j] = A[i][j]; 
  54.                 if(A[i][j] != 0) 
  55.                     g->e ++; 
  56.             } 
  57.  
  58. void DispMat(MGraph *g)    //输出图的邻接矩阵   
  59.     int i,j; 
  60.     for(i=0; i<g->n; i++) 
  61.     { 
  62.         for(j=0; j<g->n; j++) 
  63.         { 
  64.             printf("%c  ",g->edge[i][j]); 
  65.         } 
  66.         printf("\n"); 
  67.     } 
  68.  
  69. void CreateAdj(AGraph *g, int A[][MAXV], int n)       //生成图的邻接表 
  70.     int i=0, j=0; 
  71.     ArcNode *p = NULL;              
  72.     g = (AGraph *)malloc(sizeof(AGraph)); 
  73.     g->n = n; 
  74.     g->e = 0; 
  75.          
  76.     for(i=0; i<n; i++)   g->adjlist[i]->firstarc = NULL; 
  77.  
  78.     for(i=0; i<n; i++) 
  79.         for(j=0; j<n; j++) 
  80.             if(A[i][j] != 0) 
  81.             { 
  82.                 p = (ArcNode *)malloc(sizeof(ArcNode)); 
  83.                 p->adjvex = j; 
  84.                 p->nextarc = g->adjlist[j]->firstarc;           //倒着插入  并且数组的第一列为头结点 
  85.                 g->adjlist[j]->firstarc = p; 
  86.                 g->e++; 
  87.             } 
  88.  
  89. void DispAdj(AGraph *g)                                         //输出邻接表 
  90.     int i=0; 
  91.     ArcNode *p = NULL; 
  92.  
  93.     for(i=0; i<g->n; i++) 
  94.     { 
  95.         printf("%d  ",i); 
  96.         p = g->adjlist[i]->firstarc;                             //把p指向每个头结点对应的边的指针 
  97.         while(p != NULL) 
  98.         { 
  99.             printf("%c ",p->adjvex); 
  100.             p = p->nextarc;                                      //下一个边的指针 
  101.         } 
  102.         printf("\n"); 
  103.     } 
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112. void InDs(AGraph *g)       //ru du 
  113.     ArcNode *p; 
  114.     int A[MAXV],i;         // store ru du 
  115.  
  116.     for(i=0; i<g->n; i++)  A[i] = 0; 
  117.  
  118.     for(i=0; i<g->n; i++) 
  119.     { 
  120.         p = (g->adjlist[i]->firstarc); 
  121.         while(p != NULL) 
  122.         { 
  123.             A[i]++; 
  124.             p = p->nextarc; 
  125.         } 
  126.     } 
  127.  
  128.     for(i=0; i<g->n; i++) 
  129.         printf("%d   ",A[i]); 
  130.  
  131. void OutDs(AGraph *g)             //chu du 
  132.     int i,n; 
  133.     ArcNode *p; 
  134.     for(i=0; i<g->n; i++) 
  135.     { 
  136.         n=0; 
  137.         p = g->adjlist[i]->firstarc; 
  138.         while(p != NULL) 
  139.         { 
  140.             n ++; 
  141.             p = p->nextarc; 
  142.             printf("%d    ",n); 
  143.         } 
  144.     } 
  145.  
  146. void Arc(AGraph *g, int i, int j)   //if there is line between i and j 
  147.     ArcNode *p = NULL; 
  148.     p = g->adjlist[i]->firstarc; 
  149.  
  150.     while(p->adjvex != j && p != NULL) 
  151.         p = p->nextarc; 
  152.     if(p == NULL)  printf("不存在"); 
  153.     else printf("存在"); 
  154.  
  155.  
  156.  
  157.  
  158. void InDs1(MGraph *g)                 //计算邻接矩阵的入度,对于顶点 j,累计第j列中非零元素的个数即为入度 
  159.     int i,j,n; 
  160.  
  161.     for(j=0; j<g->n; j++) 
  162.     { 
  163.         n = 0; 
  164.         for(i=0; i<g->n; i++) 
  165.         { 
  166.             if(g->edge[i][j] != 0) 
  167.                 n++; 
  168.         } 
  169.         printf("%d    ",n); 
  170.     } 
  171.  
  172. void OutDs2(MGraph *g)                       //计算出度只要计算那一行中非零的个数即可 
  173.     int  i=0,j=0,n=0; 
  174.  
  175.     for(i=0; i<g->n; i++) 
  176.     {   n=0; 
  177.         for(j=0; j<g->n; j++) 
  178.                 if(g->edge[i][j] != 0) 
  179.                     n++; 
  180.         printf("%d ",n); 
  181.     } 
  182.  
  183. void ListToMat(AGraph *g1, MGraph *g2)          //把邻接表转换为邻接矩阵 
  184.     int i=0, j=0; 
  185.     ArcNode *p = NULL; 
  186.     g2 = (MGraph *)malloc(sizeof(MGraph)); 
  187.     g2->n = g1->n; 
  188.  
  189.     for(i=0; i<g1->n; i++)  
  190.         for(j=0; j<g1->n; j++) 
  191.             g2->edge[i][j] = 0; 
  192.  
  193.     for(i=0; i<g1->n; i++) 
  194.     { 
  195.         p = g1->adjlist[i]->firstarc; 
  196.         while(p != NULL) 
  197.         { 
  198.             g2->edge[i][p->adjvex] = 1;                     //此处通过p->adjvex来决定第二维的坐标 
  199.             p = p->nextaec; 
  200.         } 
  201.     } 
  202.      
  203.  
  204. //深度优先遍历 
  205. void DFS(AGraph *g, int v)     //v表示第几个节点 
  206.     ArcNode *p = NULL; 
  207.     visited[v] = 1; 
  208.     p = g->adjlist[v]->firstarc;    //p代表第v个节点 
  209.     while(p != NULL)       
  210.     { 
  211.         if(visited[p->adjvex] == 0)        //此处表示此节点未被访问过 
  212.             DFS(g,p->adjvex); 
  213.         p = p->nextarc ; 
  214.     } 
  215. /* 
  216.     * * * * 
  217.     * * * * 
  218.     * * * * 
  219.     * * * * 
  220.     两者的差别是 深度遍历遇到一个可以访问的节点就会以它为头结点跳到相应的 行 继续重复前面类似的访问 
  221.     而广度遍历则是一直遍历完一行后 才开始下一行 
  222. */ 
  223.  
  224. //广度优先遍历   需要借助队列 
  225. void BFS(AGraph *g,int v) 
  226.     ArcNode *p = NULL; 
  227.     int w,i,front =0, rear = 0; 
  228.     int queue[MAXV]; 
  229.     rear = (rear + 1) % MAXV; 
  230.     queue[rear] = v; 
  231.     for(i=0; i<g->n ; i++) visited[i] = 0; 
  232.     visited[v] = 1; 
  233.  
  234.     while(front != rear) 
  235.     { 
  236.         front = (front + 1) % MAXV; 
  237.         w = queue[front]; 
  238.         p = g->adjlist[w]->firstarc; 
  239.  
  240.         while(p != NULL)                    //此处的作用是把那一行的节点如队列 
  241.         { 
  242.             if(visited[p->adjvex] == 0) 
  243.             { 
  244.                 visited[p->adjvex] = 1; 
  245.                 rear = (rear + 1) % MAXV; 
  246.                 queue[rear] = p->adjvex; 
  247.             } 
  248.             p = p->nextarc ;                     //在深度遍历的时候,也用到了它,不过在深度遍历后指针跳到其他行了,而此处仍然在那一行 
  249.         } 
  250.     } 
  251.  
  252. //非连通图的遍历 需要选择不同的节点重复进行遍历 
  253. void DFS1(AGraph *g) 
  254.     int i=0; 
  255.     for(i=0; i<g->n; i++) 
  256.         if(visited[i] == 0) 
  257.             DFS(g,i); 
  258.  
  259. void BFS1(AGraph *g) 
  260.     int i=0; 
  261.     for(i=0; i<g->n; i++) 
  262.         if(visited[i] == 0) 
  263.             BFS(g,i); 
  264.  
  265. //深度遍历的非递归的思想是 采用一个栈 
  266. //把节点的那一行  di yi ge 没有访问过的全部入栈,通过一个while循环,然后就像广度优先遍历采用队列的判断条件类似,此处的判断条件是栈不空 
  267. void DFS2(AGraph *g, int v) 
  268.     ArcNode *p = NULL; 
  269.     ArcNode *st[MAXV] ; 
  270.  
  271.     int i ,top = -1; 
  272.  
  273.     for(i=0; i<g->n; i++)  visited[i] = 0; 
  274.  
  275.     top++; 
  276.     st[top] = g->adjlist[v]->firstarc; 
  277.     i = st[top]->adjvex;  
  278.  
  279.     while(top > -1) 
  280.     { 
  281.         p = st[top]; top--; 
  282.         while(p != NULL) 
  283.         { 
  284.             i = st[top]->adjvex; 
  285.             if(visited[i] == 0) 
  286.             { 
  287.                 visited[i] = 1; 
  288.                 top++; 
  289.                 st[top] = g->adjlist[i]->firstarc;               
  290.                 break;                              // 因为是只让第一个节点入栈,所以指向仍然是跳到 头结点 
  291.             } 
  292.             p = p->nextarc; 
  293.         } 
  294.     } 
  295.  
  296.  
  297. //判断从i节点到j节点是否有路径 
  298. int DFSTrave(AGraph *g, int i,int j) 
  299.     int k=0; 
  300.     for(k=0; k>g->n; k++) visited[k] = 0; 
  301.     DFS(g,i);   //通过调用DFS函数来改变数组visited的值 
  302.     if(visited[j] == 0)  return 0; 
  303.     else return 1; 
  304.  
  305. int BFSTrave(AGraph *g, int i,int j) 
  306.     int k=0; 
  307.     for(k=0; k>g->n; k++) visited[k] = 0; 
  308.     BFS(g,i); 
  309.     if(visited[j] == 0)  return 0; 
  310.     else return 1; 
  311.  
  312. //判断一个图是否为一个树,则必须是无回路的连通图,或者有n-1条边的连通图,对于连通的判断,可用能否遍历全部顶点来实现 
  313. void DFS3(AGraph *g, int v) 
  314.     ArcNode *p; 
  315.     int vn=0; 
  316.     visited[v] = 1;  
  317.      
  318.  
  319.  
  320. #include <stdio.h> 
  321.  
  322. typedef struct 
  323.     int u; //边的起始顶点 
  324.     int v; //边的终止顶点 
  325.     int w; //边的权值 
  326. }EdgeType; 
  327.  
  328. void Prim(MGraph g, int v0) 
  329.     int lowcost[MAXV], vset[MAXV],v; //其中新加入的节点放在vset数组内,lowcost数组盛放的权值的最小值 
  330.     int i,j,k,min; 
  331.     v =v0; 
  332.     vset[v0] = 1; 
  333.  
  334.     for(i=0; i<g.n; i++)  //此循环的目的是为了初始化表示新加入节点的vset数组,还有表示权值大小的lowcost数组    
  335.         if(i != v0) 
  336.         { 
  337.             lowcost[i] = g.edge[v0][i]; 
  338.             vset[i] = 0; 
  339.         }    
  340.  
  341.     for(j=1; j<g.n; j++) //次循环是为了找到其他n-1个节点 
  342.     { 
  343.         min = INF; 
  344.         for(k=0; k<g.n; k++)       //此循环是为了找到 与v0邻接的节点的权值最小值 
  345.         { 
  346.             if(vset[k] != 0 && lowcost[k] < min) 
  347.             { 
  348.                 min = lowcost[k]; 
  349.                 k = j; 
  350.             } 
  351.         } 
  352.         printf("  边(%d, %d)权为: %d\n", v,k,min); 
  353.         v=k;                            //v表示刚刚找到的一个与v0相邻的点,然后下面就会以v为点 查找相应的候选边 
  354.         vset[k] = 1; 
  355.  
  356.         for(j=0; j<g.n; j++)           //此循环的作用是为了修正候选边 
  357.             if(vset[v][j] == 0 && g.edge[v][j] < lowcost[j]) 
  358.                 lowcost[j] = g.edge[v][j]; 
  359.  
  360.     } 
  361.  
  362.  
  363. void InsetSort(EdgeType E[], int n) 
  364.     int i,j; 
  365.     EdgeType temp; 
  366.     for(i=0; i<n; i++) 
  367.     { 
  368.         temp = E[i]; 
  369.         j = i-1;                        //此处取前一个节点 
  370.  
  371.         while(j>=0 && E[j].w > temp.w)    //此循环的目的是把比 E[i] 大的元素移送到后面 
  372.         { 
  373.             E[j+1] = E[j]; 
  374.             j--; 
  375.         } 
  376.         E[j+1] = temp; 
  377.     } 
  378.  
  379. void Kruskal(MGraph g) 
  380.     EdgeType E[MAXV]; 
  381.     int i,j,m1,m2,sn1,sn2,k; 
  382.     int vset[MAXV]; 
  383.     k=0; 
  384.     for(i=0; i<g.n; i++)               //将各个边存到E[]数组中 
  385.         for(j=0; j<g.n; j++) 
  386.             if(g.edge[i][j] != 0 && g.edge[i][j] != INF) 
  387.             { 
  388.                 E[k].u = i; E[k].v = j; E[k].w = g.edge[i][j]; 
  389.                 k++; 
  390.             } 
  391.     InseSort(E,g.e); 
  392.  
  393.     for(i=0; i<g.n; i++)  vset[i] = i; 
  394.     k=1; j=0;            //k最后应为 n-1 表示把其余的节点都加入到了数组,j只是为了遍历边的需要 
  395.     while(k<g.n) 
  396.     { 
  397.         m1= E[j].u; m2 = E[j].v;  
  398.         sn1 = vset[m1]; sn2 = vset[m2]; 
  399.         if(sn1 != sn2)           //判断选取的边是否与生成树中已保留的边构成回路 通过vset数组 
  400.         { 
  401.             printf("边(%d, %d) :%d",m1,m2,E[j].w); 
  402.             k++; 
  403.             for(i=0; i<g.n; i++) 
  404.                 if(vset[i] == sn2) 
  405.                     vset[i] = sn1; 
  406.         } 
  407.         j++; 
  408.     } 
  409.  
  410. //遍历路径中是否包括某节点 
  411. #include <stdio.h> 
  412.  
  413. int path[MAXV]; 
  414. int v1[MAXV],v2[MAXV]; 
  415. int vn,vm;                  //vn保存的是必经节点的个数,v1数组保存的是必经节点,vm 对应的是 必避 节点 
  416.  
  417. int cond(int path[],int d)     //d保存的是path数组里的 元素个数 
  418.     int i,j; 
  419.     int flag1=0, f1, flag2=0, f2; 
  420.  
  421.     for(i=0; i<vn; i++) 
  422.     { 
  423.         f1=1; 
  424.         for(j=0; j<=d; j++) 
  425.             if(path[j] == v1[i]) 
  426.             { 
  427.                 f1=0; 
  428.                 break
  429.             } 
  430.         flag1 += f1; 
  431.     } 
  432.  
  433.     for(i=0; i<vm; i++) 
  434.     { 
  435.         f2=0; 
  436.         for(j=0; j<=d; j++)      
  437.             if(path[j] == vm[i]) 
  438.             { 
  439.                 f2=1; 
  440.                 break
  441.             }        
  442.         flag2 += f2; 
  443.     } 
  444.  
  445.     if(flag1 == 0 && flag2 == 0)  return 1; 
  446.     else return 0; 
  447.  
  448.  
  449. //搜索从vi到vj的路径  采用深度优先算法 
  450.  
  451. void TravPath(AGraph *g, int vi, int vj, int d) 
  452.     int v,i; 
  453.     ArcNode *p; 
  454.     d++; 
  455.     visited[vi] = 1;     
  456.     path[d] = vi;                //此处进行设置 路径的值 和 visited数组 
  457.  
  458.     if(vi == vj && Cond(path,d) == 1) 
  459.     { 
  460.         for(i=0; i<=d; i++)  printf("%d  ",path[i]); 
  461.         printf("\n"); 
  462.     } 
  463.  
  464.     p = g->adjlist[vi]->firstarc; 
  465.     while(p != NULL) 
  466.     { 
  467.         v = p->adjvex; 
  468.         if(visited[v] == 0)      
  469.             TravPath(g,v,vj,d); 
  470.         p = p->nextarc ; 
  471.     } 
  472.     visited[vi] = 0;        //这两步取消标记,使该顶点重新可用 
  473.     d--; 
  474.  
  475.  
  476.  
  477.  
  478.  
  479. //求邻接矩阵的根,通过遍历每个节点逐个遍历是否满足条件 
  480. //也就是求从一个顶点遍历是否能够到达全部其他顶点,标志量是visited数组的值全部为1 
  481.  
  482. void MDFS(MGraph g, int v) 
  483.     int j; 
  484.     visited[v] = 1;              //此visited数组的更改在此进行 
  485.     for(j=0; j<g.n; j++) 
  486.         if(g.edge[v][j] != 0 && g.edge[v][j] != INF && visited[j] == 0) 
  487.             MDFS(g,j); 
  488.  
  489. int DGRoot1(MGraph g) 
  490.     int i,j,k,n; 
  491.     for(i=0; i<g.n; i++) 
  492.     { 
  493.         for(j=0; j<g.n; j++)  visited[j] = 0; 
  494.         MDFS(g,i); 
  495.         n = 0; 
  496.         for(k=0; k<g.n; k++) 
  497.             if(visited[k] == 1) n++; 
  498.         if(n == g.n) return i; 
  499.     } 
  500.  
  501. void MBFS(MGraph g, int v) 
  502.     int qu[MAXV], front =0, rear = 0; 
  503.     int i,j; 
  504.  
  505.     visited[v] = 1; 
  506.     rear = (rear + 1) % MAXV; 
  507.     qu[rear] = v; 
  508.  
  509.     while(front != rear)  
  510.     { 
  511.         front = (front + 1) % MAXV; 
  512.         i = qu[front]; 
  513.  
  514.         for(j=0; j<g.n; j++)      //因为此种方法是基于广度的搜索法,所以此处的目的是为了进行一行的计算i表示的具体的行数 
  515.         { 
  516.             if(g.edge[i][j] != 0 && g.edge[i][j] != INF) 
  517.             { 
  518.                 if(visited[j] == 0) 
  519.                 { 
  520.                     visited[j] = 1; 
  521.                     rear = (rear + 1) % MAXV; 
  522.                     qu[rear] = j; 
  523.                 } 
  524.             } 
  525.         } 
  526.     } 
  527.  
  528. int DGRoot2(MGraph g) 
  529.     int i,j,k,n; 
  530.     for(i=0;  i<g.n; i++) 
  531.     { 
  532.         for(j=0; j<g.n; j++)  visited[j] = 0; 
  533.         BDFS(g,i); 
  534.         n=0; 
  535.         for(k=0; k<g.n; k++) 
  536.             if(visited[k] == 1)  n++; 
  537.         if(n == g.n)  return 1; 
  538.         else return 0; 
  539.     }