• 数据结构(严版)课本代码重敲——第七章


    数据结构 第七章 图

    四种基本存储结构之邻接矩阵表示法

      1 /*
      2 * 范围:第七章 图
      3 * 日期:2018/4/1
      4 */
      5 
      6 /*
      7 笔记:
      8 enum < 枚举类型名> {< 枚举表>};
      9 enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
     10 day d1,d2,d3;
     11 d1 = Thu; d2 = Sat; d3 = Tue;
     12 定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
     13 */
     14 #include <iostream>
     15 #define INFINITY INT_MAX
     16 
     17 
     18 using namespace std;
     19 // 数组表示法/邻接矩阵表示法
     20 const int MAXSIZE = 20;
     21 typedef char vertexType;
     22 typedef int vrType;
     23 typedef char infoType;
     24 typedef enum{DG,DN,UDG,UDN} graphKind;
     25 
     26 typedef struct arcCell
     27 {
     28     vrType adj;
     29     infoType *info;
     30 }arcCell,adjMatrix[MAXSIZE][MAXSIZE];
     31 
     32 typedef struct
     33 {
     34     vertexType vex[MAXSIZE];
     35     adjMatrix arc;
     36     int vexnum,arcnum;
     37     graphKind kind;
     38 }MGraph;
     39 
     40 int locate(MGraph &g,vertexType v)
     41 {
     42     for (int i=0;i<g.vexnum;i++)
     43     {
     44         if( g.vex[i] == v)
     45             return i;
     46     }
     47     return -1;
     48 }
     49 void createUDN(MGraph &g)
     50 {
     51     int hasInfo;
     52     cout << "顶点数、边数、是否有信息"<<endl;
     53     cin >> g.vexnum >>g.arcnum >> hasInfo;
     54     int i,j;
     55     for (i=0;i<g.vexnum;i++)
     56     {
     57         cin >>g.vex[i];
     58     }
     59     for (i=0;i<g.vexnum;i++)
     60         for (j=0;j<g.vexnum;j++)
     61     {
     62         g.arc[i][j].adj = INFINITY;
     63         g.arc[i][j].info = NULL;
     64     }
     65     vertexType v1,v2;
     66     vrType w;
     67     cout << "边:" <<endl;
     68     for (int k=0;k<g.arcnum;k++)
     69     {
     70         cin >>v1 >>v2>>w;
     71         i = locate(g,v1);
     72         j = locate(g,v2);
     73         g.arc[i][j].adj = w;
     74         if (hasInfo)
     75             cin >> g.arc[i][j].info;
     76         g.arc[j][i] = g.arc[i][j];
     77     }
     78 }
     79 void createGraph(MGraph &g)
     80 {
     81     graphKind kind;
     82     cout << "graphkind"<<endl ;
     83     cin >> (int &)kind;
     84     switch(kind)
     85     {
     86         case UDN:createUDN(g);
     87     }
     88 }
     89 void printMatrix(MGraph &g)
     90 {
     91     int i,j;
     92     for (i=0;i< g.vexnum ; i++)
     93     {
     94          for (j = 0 ;j<g.arcnum;j++)
     95     {
     96         if (g.arc[i][j].adj == INFINITY)
     97             cout << '#' << ' ';
     98         else
     99             cout << g.arc[i][j].adj <<' ';
    100     }
    101     cout <<endl;
    102     }
    103 
    104 }
    105 // 深度优先搜索
    106 bool visited[MAXSIZE];
    107 
    108 int firstAdjVex(MGraph &g,int v)
    109 {
    110     // 邻接矩阵表示法中,点v的第一个邻接点,在矩阵中横着找不为无穷大的点
    111     int j;
    112     for (j = 0; j < g.vexnum ; j++)
    113     {
    114       if (g.arc[v][j].adj!=INFINITY)
    115         return j;
    116     }
    117     return -1;
    118 }
    119 int nextAdjVex(MGraph &g,int v,int w)
    120 {
    121     // v的邻接点中在w之后的第一个邻接点
    122     int j;
    123     for (j = w+1;j<g.vexnum;j++)
    124     {
    125         if (g.arc[v][j].adj!=INFINITY)
    126             return j;
    127     }
    128     return -1;
    129 }
    130 void DFS(MGraph &g,int v)
    131 {
    132     visited[v] = true; // 从V结点开始深度搜索
    133     cout << g.vex[v] << ' ';
    134     for (int w = firstAdjVex(g,v); w >= 0 ;w = nextAdjVex(g,v,w))
    135     {
    136         if (!visited[w])
    137             DFS(g,w);// 对未被访问过的邻接点递归调用DFS
    138     }
    139 }
    140 void DFSTraverse(MGraph &g)
    141 {
    142     int i;
    143     for (i=0;i<g.vexnum;i++)
    144         visited[i] = false; // 初始化visited,均未被访问
    145     for (i=0;i<g.vexnum;i++) // 一次寻找后可能有仍旧未被访问的点
    146     {
    147         if (!visited[i])
    148             DFS(g,i);
    149     }
    150 
    151 }
    152 int main()
    153 {
    154     MGraph g;
    155     createGraph(g);
    156    // printMatrix(g);
    157    DFSTraverse(g);
    158 
    159     return 0;
    160 }

    邻接表表示法

      1 /*
      2 * 范围:第七章 图
      3 * 日期:2018/4/1
      4 */
      5 
      6 /*
      7 笔记:
      8 enum < 枚举类型名> {< 枚举表>};
      9 enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
     10 day d1,d2,d3;
     11 d1 = Thu; d2 = Sat; d3 = Tue;
     12 定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
     13 */
     14 #include <iostream>
     15 #include <string>
     16 #include <stdlib.h>
     17 #define INFINITY INT_MAX
     18 
     19 
     20 using namespace std;
     21 
     22 // 邻接表
     23 
     24 const int MAXSIZE = 20;
     25 
     26 typedef char vertexType;
     27 typedef char infoType;
     28 typedef enum{DG,UDG} graphKind;
     29 
     30 typedef struct arcNode
     31 {
     32     int adjvex;
     33     infoType *info;
     34     struct arcNode *nextarc;
     35 }arcNode;
     36 
     37 typedef struct
     38 {
     39     vertexType data;
     40     struct arcNode *firstarc;
     41 }VNode;
     42 
     43 typedef struct
     44 {
     45     VNode adjList[MAXSIZE];
     46     int vexnum,arcnum;
     47     graphKind kind;
     48 }ALGraph;
     49 
     50 int locate(ALGraph &g,vertexType v)
     51 {
     52     int i;
     53     for (i = 0;i<g.vexnum;i++)
     54     {
     55         if ( g.adjList[i].data == v )
     56             return i;
     57     }
     58     return -1;
     59 }
     60 
     61 void createUDG(ALGraph &g)
     62 {
     63     int hasInfo;
     64     cout << "顶点数、边数、是否有信息"<<endl;
     65     cin >> g.vexnum >> g.arcnum>>hasInfo;
     66     int i,j,k;
     67     cout << "头结点" <<endl;
     68     for (i=0;i<g.vexnum;i++)
     69     {
     70         cin >> g.adjList[i].data ;
     71         g.adjList[i].firstarc = NULL;
     72     }
     73     vertexType v1,v2;
     74     arcNode *p,*q;
     75     cout << "边:" <<endl;
     76     for (k = 0; k < g.arcnum;k++)
     77     { // 头插法建立链表
     78         cin >> v1 >> v2;
     79         i = locate(g,v1);
     80         j = locate(g,v2);
     81         p = (arcNode*)malloc(sizeof(arcNode));
     82         if (hasInfo)
     83             cin >> p->info;
     84         p->adjvex = j;
     85         p->nextarc = g.adjList[i].firstarc;
     86         g.adjList[i].firstarc = p;
     87 
     88         // 无向图一条边建立两个节点
     89         q = (arcNode*)malloc(sizeof(arcNode));
     90         if (hasInfo)
     91             q->info = p->info;
     92         q->adjvex = i;
     93         q->nextarc = g.adjList[j].firstarc;
     94         g.adjList[j].firstarc = q;
     95     }
     96 }
     97 
     98 void createDG(ALGraph &g)
     99 {
    100     int hasInfo;
    101     cout << "顶点数、弧数、有无信息"<<endl;
    102     cin >>g.vexnum >>g.arcnum >> hasInfo;
    103 
    104     int i,j,k;
    105     cout << "顶点" <<endl;
    106     for (i=0;i<g.vexnum;i++)
    107     {
    108         cin >> g.adjList[i].data;
    109         g.adjList[i].firstarc = NULL;
    110     }
    111     arcNode *p;
    112     vertexType v1,v2;
    113     cout << "" <<endl ;
    114     for (k = 0;k<g.arcnum;k++)
    115     {
    116         cin >>v1>>v2;
    117         i = locate(g,v1);
    118         j = locate(g,v2);
    119         p = (arcNode*)malloc(sizeof(arcNode));
    120         p->adjvex = j;
    121         p->nextarc = g.adjList[i].firstarc;
    122         if (hasInfo)
    123             cin >> p->info;
    124         g.adjList[i].firstarc = p;
    125     }
    126 
    127 
    128 }
    129 
    130 void buildNALG(ALGraph &g,ALGraph &ng)
    131 {
    132     ng.vexnum = g.vexnum;
    133     ng.arcnum  = g.arcnum;
    134 
    135     int i,j;
    136     for (i=0;i<ng.vexnum;i++)
    137     {
    138         ng.adjList[i].data = g.adjList[i].data;
    139         ng.adjList[i].firstarc = NULL;
    140     }
    141     arcNode *p,*q;
    142     for (i = 0;i<g.vexnum;i++)
    143     {
    144         for (j = 0;j<g.vexnum;j++)
    145         {
    146             if (i==j)
    147                 continue;
    148             p = g.adjList[j].firstarc;
    149             while (p)
    150             {
    151                 if (p->adjvex == i)
    152                 {
    153                     q = (arcNode *)malloc(sizeof(arcNode));
    154                     q->adjvex = j;
    155                     q->info = p->info;
    156                     q->nextarc = ng.adjList[i].firstarc;
    157                     ng.adjList[i].firstarc = q;
    158                 }
    159                 p = p->nextarc;
    160             }
    161 
    162         }
    163     }
    164 }
    165 
    166 void createGraph(ALGraph &g)
    167 {
    168     graphKind kind;
    169     cout << "kind:"<<endl;
    170     cin >> (int &)kind;
    171     switch(kind)
    172     {
    173         case UDG:createUDG(g);break;
    174         case DG:createDG(g);
    175     }
    176 }
    177 void printGraph(ALGraph &g)
    178 {
    179     int i;
    180     arcNode *p;
    181     for (i=0;i<g.vexnum;i++)
    182     {
    183         if (!g.adjList[i].firstarc)
    184             cout <<g.adjList[i].data << "->NULL";
    185         else
    186             cout << g.adjList[i].data <<"->";
    187         p = g.adjList[i].firstarc;
    188         while (p)
    189         {
    190             if (!p->nextarc)
    191                 cout <<p->adjvex;
    192             else
    193                 cout <<p->adjvex << "->";
    194             p = p->nextarc;
    195         }
    196         cout <<endl;
    197     }
    198 
    199 }
    200 // 深度优先搜索
    201 bool visited[MAXSIZE];
    202 
    203 int firstAdjVex(ALGraph &g,int v)
    204 {
    205     if (g.adjList[v].firstarc)
    206         return g.adjList[v].firstarc->adjvex;
    207     else
    208         return -1;
    209 }
    210 int nextAdjVex(ALGraph &g,int v,int w)
    211 {
    212     arcNode *p;
    213     p = g.adjList[v].firstarc;
    214     for (p ; p ; p = p ->nextarc)
    215     {
    216         if (p->adjvex == w)
    217         {
    218             if (p->nextarc)
    219             {
    220                 return p->nextarc->adjvex;
    221             }
    222             else
    223                 return -1;
    224         }
    225     }
    226 }
    227 void DFS(ALGraph &g,int v)
    228 {
    229     visited[v] = true;
    230     cout << g.adjList[v].data<<' ';
    231     for (int w = firstAdjVex(g,v) ; w>=0 ; w = nextAdjVex(g,v,w)) // 注意这里不能写w,因为我的return值是-1!所以条件亦成立
    232     {
    233         if (!visited[w])
    234             DFS(g,w);
    235     }
    236 }
    237 void DFSTraverse(ALGraph &g)
    238 {
    239     int i;
    240     for (i=0;i<g.vexnum;i++)
    241     {
    242         visited[i] = false;
    243     }
    244     for (i = 0;i<g.vexnum;i++)
    245     {
    246         if (!visited[i])
    247             DFS(g,i);
    248     }
    249 }
    250 
    251 // 广度优先搜索
    252 void BFSTraverse(ALGraph &g)
    253 {
    254     for (int i = 0;i<g.vexnum;i++)
    255         visited[i] = false;
    256     queue<int> que;
    257     for (int i = 0;i<g.vexnum;i++)
    258     {
    259         if (!visited[i])
    260         {
    261             visited[i] = true;
    262             cout << g.adjList[i].data<<' ';
    263             que.push(i);
    264             while (!que.empty())
    265             {
    266                 int u = que.front();
    267                 que.pop();
    268                 for (int w = firstAdjVex(g,u) ; w >=0 ;w= nextAdjVex(g,u,w))
    269                 {
    270                     if (!visited[w])
    271                     {
    272                         visited[w] = true;
    273                         cout << g.adjList[w].data <<' ';
    274                         que.push(w);
    275                     }
    276                 }
    277             }
    278         }
    279     }
    280 }
    281 int main()
    282 {
    283    ALGraph g,ng;
    284    createGraph(g);
    285    //buildNALG(g,ng);
    286    printGraph(g);
    287    DFSTraverse(g);
    288 
    289 
    290     return 0;
    291 }

    十字链表表示法

     1 /*
     2 * 范围:第七章 图
     3 * 日期:2018/4/1
     4 */
     5 
     6 /*
     7 笔记:
     8 enum < 枚举类型名> {< 枚举表>};
     9 enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
    10 day d1,d2,d3;
    11 d1 = Thu; d2 = Sat; d3 = Tue;
    12 定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
    13 */
    14 #include <iostream>
    15 #include <string>
    16 #include <stdlib.h>
    17 
    18 
    19 using namespace std;
    20 // 十字链表
    21 const int MAXSIZE = 20;
    22 
    23 typedef char vertexType;
    24 typedef char infoType;
    25 
    26 typedef struct arcNode
    27 {
    28     int tailvex,headvex;//尾部邻接点和头部邻接点
    29     struct arcNode *hlink,*tlink;//hlink指向弧头相同的下一条弧
    30     infoType *info;
    31 }arcNode;
    32 
    33 typedef struct
    34 {
    35     vertexType data;
    36     struct arcNode *firstin,*firstout;
    37 }VNode;
    38 
    39 typedef struct
    40 {
    41     int vexnum,arcnum;
    42     VNode olist[MAXSIZE];
    43 }OLGraph;
    44 
    45 int locate(OLGraph &g,vertexType v)
    46 {
    47     int i;
    48     for (i=0;i<g.vexnum;i++)
    49     {
    50         if ( g.olist[i].data == v )
    51             return i;
    52     }return -1;
    53 }
    54 void createDG(OLGraph &g)
    55 {
    56     cout << "顶点数、弧数、有无信息" << endl;
    57     int hasInfo;
    58     cin >> g.vexnum >>g.arcnum >> hasInfo;
    59     int i,j,k;
    60     cout << "顶点:" << endl;
    61     for (i=0;i<g.vexnum;i++)
    62     {
    63         cin >> g.olist[i].data;
    64         g.olist[i].firstin = NULL;
    65         g.olist[i].firstout = NULL;
    66     }
    67     cout << "弧:"<<endl;
    68     vertexType v1,v2;
    69     arcNode *p;
    70     for (k = 0;k<g.arcnum;k++)
    71     {
    72         cin >> v1 >> v2;a
    73         i = locate(g,v1);
    74         j = locate(g,v2);
    75         p->tailvex = i;
    76         p->headvex = j;
    77         if (hasInfo)
    78             cin >> p->info;
    79         p->tlink = g.olist[i].firstout;
    80         g.olist[i].firstout = p;
    81         // 至此完成邻接表的工作,十字链表即为邻接表+逆邻接表的结合体
    82         p->hlink = g.olist[j].firstin;
    83         g.olist[j].firstin = p;
    84     }
    85 }
    86 int main()
    87 {
    88 
    89 
    90 
    91     return 0;
    92 }

    邻接多重表表示法

     1 /*
     2 * 范围:第七章 图
     3 * 日期:2018/4/1
     4 */
     5 
     6 /*
     7 笔记:
     8 enum < 枚举类型名> {< 枚举表>};
     9 enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
    10 day d1,d2,d3;
    11 d1 = Thu; d2 = Sat; d3 = Tue;
    12 定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
    13 */
    14 #include <iostream>
    15 #include <string>
    16 #include <stdlib.h>
    17 
    18 
    19 using namespace std;
    20 // 邻接多重表 无向图的存储形式
    21 const int MAXSIZE = 20;
    22 typedef char vertexType;
    23 
    24 typedef struct eNode
    25 {
    26     bool mark;
    27     int ivex,jvex;
    28     struct eNode *ilink,*jlink; // ilink 指向依附于ivex的边
    29 }eNode;
    30 
    31 typedef struct VNode
    32 {
    33     vertexType data;
    34     struct eNode *firstedge;
    35 }VNode;
    36 
    37 typedef struct
    38 {
    39     VNode adjmulist[MAXSIZE];
    40     int vexnum,edgenum;
    41 }AMLGraph;
    42 
    43 void createAMLGraph(AMLGraph &g)
    44 {
    45     cout << "顶点数、边数、有无信息"<<endl;
    46     int hasInfo;
    47     cin >> g.vexnum >> g.edgenum >> hasInfo;
    48 
    49     int i,j,k;
    50     for (i=0;i<g.vexnum;i++)
    51     {
    52         cin >> g.adjmulist[i].data;
    53         g.adjmulist[i].firstedge = NULL;
    54     }
    55 
    56     eNode *p;
    57     vertexType v1,v2;
    58     for (k=0;k<g.edgenum;k++)
    59     {
    60         cin >> v1 >> v2;
    61         i = locate(g,v1);
    62         j = locate(g,v2);
    63         p = (eNode *)malloc(sizeof(eNode));
    64         p->ivex = i;
    65         p->jvex = j;
    66         p->ilink = g.adjmulist[i].firstedge;
    67         p->jlink = g.adjmulist[j].firstedge;
    68         g.adjmulist[i].firstedge = p;
    69         g.adjmulist[j].firstedge = p;
    70     }
    71 }
    72 int main()
    73 {
    74 
    75 
    76 
    77     return 0;
    78 }

    无向图的连通分量和生成树

      1 /*
      2 * 7.4 知识点
      3 * 1. 遍历无向图时,对于连通图,从任一顶点出发进行深度或广度优先搜索即可;对于非联通图则需要从
      4 * 多个顶点出发进行搜索,每次获得的顶点序列则为各个连通分量的顶点集。
      5 * 2. 连通图有深度优先生成树和广度优先生成树,即搜索的路径形成的树。
      6 * 3. 非连通图每个连通分量均可形成一个生成树,即一个生成森林。
      7 * 4. 除了二叉树外的没有叉数限制的树一般用孩子-兄弟表示法表示成方便遍历的二叉树形式。
      8 * 5. 森林的树的根节点其实亦为兄弟,也可以用孩子-兄弟表示法来表示。
      9 */
     10 // 无向图的深度优先生成森林(非连通图)
     11 
     12 typedef char Elemtype;
     13 typedef struct CSNode
     14 {
     15     Elemtype data;
     16     struct CSNode *child,*sibling;
     17 }CSNode,*CSTree;
     18 
     19 
     20 void DFSTree(ALGraph &g,CSTree &t,int v)
     21 {
     22     // 从v顶点开始深度搜索生成树
     23     visited[v] = true;
     24     cout <<g.adjList[v].data << ' ';
     25     CSTree p,q;
     26     bool isfirst = true;
     27     for (int w = firstAdjVex(g,v) ; w>=0 ; w = nextAdjVex(g,v,w))
     28     {
     29         if (!visited[w])
     30         {
     31          p = (CSTree)malloc(sizeof(CSNode));
     32          p->data = g.adjList[w].data;
     33          p->child = NULL;
     34          p->sibling = NULL;
     35          // 创建新节点P作为根节点T的邻接点,但必须确定是第一个邻接点还是其他
     36          if (isfirst)
     37          {
     38              t->child = p;
     39              isfirst = false;
     40          }else
     41          {
     42              q->sibling = p;
     43          }
     44          q = p;
     45          DFSTree(g,p,w); // 递归寻找p的邻接点们!
     46 
     47         }
     48     }
     49 }
     50 void DFSForest(ALGraph &g,CSTree &t)
     51 {
     52     for (int i=0;i<g.vexnum;i++)
     53         visited[i] = false;
     54     CSTree p,q;
     55     for (int i=0;i<g.vexnum;i++)
     56     {
     57         if (!visited[i])
     58         {
     59             p = (CSTree)malloc(sizeof(CSNode));
     60             p->data = g.adjList[i].data;
     61             p->child = NULL;
     62             p->sibling = NULL;
     63             if (!t)
     64             {
     65                 t = p; // 第一棵生成树
     66             }else
     67             {
     68                 q->sibling = p; // 非第一棵生成树,则为上一棵生成树根节点的兄弟
     69             }
     70             q = p;
     71             DFSTree(g,p,i);// 从i顶点出发建立以p为根节点的生成子树
     72         }
     73     }
     74 
     75 
     76 }
     77 void level(CSTree &t)
     78 {
     79     queue<CSTree> q;
     80     CSTree p;
     81     if (t) // 空树没有必要遍历了
     82     {
     83         q.push(t); // 根节点入队
     84         while (!q.empty())
     85         {
     86            p =  q.front(); // 弹栈一个元素
     87            q.pop();
     88             cout << p->data << ' ';
     89 
     90             if (p->child)
     91             {
     92                 q.push(p->child);
     93             }
     94             if (p->sibling)
     95             {
     96                 q.push(p->sibling);
     97             }
     98         }
     99     }
    100 }
    测试数据

    3
    13 13 0
    ABCDEFGHIJKLM
    A C
    A F
    A L
    A B
    B M
    D E
    G H
    G K
    G I
    H K
    J L
    J M
    M L

    最小生成树 之 普利姆算法

     1 struct
     2 {
     3     vertexType adjvex;
     4     vrType lowcost;
     5 }closedge[MAXSIZE];
     6 // 辅助数组的意义:记录从U到V-U中具有最小代价的边
     7 
     8 int locateVex(MGraph &g,vertexType v)
     9 {
    10     int k = -1;
    11     for (int i = 0 ;i<g.vexnum;i++)
    12     {
    13         if (g.vex[i] == v)
    14             k = i;
    15             return k;
    16     }
    17     return k;
    18 }
    19 
    20 int minimum(MGraph &g)
    21 {
    22     int min1 = INFINITY;
    23     int k = -1;
    24 
    25     for (int i = 0;i<g.vexnum;i++)
    26     {
    27         if ( closedge[i].lowcost != 0  )
    28         {
    29             if ( closedge[i].lowcost < min1 )
    30             {
    31                 min1 = closedge[i].lowcost;
    32                 k = i;
    33             }
    34         }
    35     }
    36     return k;
    37 }
    38 
    39 void miniSpanTree_prim(MGraph &g,vertexType u)
    40 {
    41 
    42     int k = locate(g,u);
    43     for (int i=0;i<g.vexnum;i++)
    44     { // closedge 一开始并不包含K
    45         if (i != k )
    46         {
    47             closedge[i].adjvex = u;
    48             closedge[i].lowcost = g.arc[k][i].adj;  //不与u邻接的点的lowcost是INFINITY
    49         }
    50     }
    51     closedge[k].lowcost = 0; // 被选入U的顶点的权值均为0
    52 
    53     for (int i = 1;i<g.vexnum ;i++) // 选择g.vexnum -1此V-U中的顶点,直到U = V为止
    54     {
    55         // 选择最小的权值,把顶点加入到U中
    56         k = minimum(g); // 求出下一个结点K
    57         cout <<"( " <<closedge[k].adjvex<<" , "<<g.vex[k]<<" )" << endl;  // 打印找到的边
    58         closedge[k].lowcost = 0; // 把K划入U集合中
    59         // 更新closedge
    60         for (int j =  0;j<g.vexnum;j++)
    61         {
    62             if (g.arc[k][j].adj < closedge[j].lowcost)
    63             {
    64                 closedge[j].adjvex = g.vex[k];
    65                 closedge[j].lowcost = g.arc[k][j].adj;
    66             }
    67         }
    68 
    69     }
    70 }
    测试数据:

    3
    6 10 0
    ABCDEF
    A B 6
    A D 5
    A C 1
    B C 5
    B E 3
    C D 5
    C E 6
    C F 4
    D F 2
    E F 6

    拓扑排序

     1 /*
     2 有向无环图的介绍:
     3 1. 有向无环图:描述含有公共子式的工具,实现对相同子式地共享,从而节省存储空间
     4 2. 检查一个有向图是否存在环比无向图复杂。无向图:深度优先遍历过程中遇到已访问过的顶点的边则必定存在环;
     5 有向图:这条回边有可能是指向深度优先生成森林中另一棵生成树顶点的弧。
     6 解决:从某个顶点V出发的遍历,在DFS(V)结束之前出现一条从顶点U到顶点V的回边,有向图上必定存在环。
     7 3. 有向无环图是描述一项工程或系统的进行过程的有效工具。工程可分为若干个活动,活动之间存在条件的约束。
     8 人们关心:1)工程能否顺利完成 2)工程完成所必须的最短时间
     9 
    10 拓扑排序:
    11 1. 由某个集合上的一个偏序得到该集合的一个全序的过程
    12 2. 解释:偏序是指集合中仅有部分成员之间可比较,而全序为集合中全体成员之间均可比较,全序即为拓扑有序
    13 3. 由偏序定义得到拓扑有序的操作便是拓扑排序
    14 4. 顶点表示活动,弧表示活动之间优先关系的有向图称为顶点表示活动的网AOV网,直接前驱和直接后继
    15 5. 在AOV网中不应该出现有向环,因此检测有向网中是否存在环的方法是:构造顶点的拓扑排序序列,若网中的所有顶点都在拓扑有序序列中则必定不存在环。
    16 6. 如何进行拓扑排序?在有向图中选择一个没有前驱的顶点且输出,删除该顶点和所有以它为尾的弧
    17 
    18 */
    19 int indegree[MAXSIZE];
    20 void findInDegree(ALGraph &g)
    21 {
    22     ALGraph ng;
    23     buildNALG(g,ng);
    24     arcNode *p;
    25     int d = 0;
    26     for (int i=0;i<ng.vexnum;i++)
    27     {
    28         d = 0;
    29         p = ng.adjList[i].firstarc;
    30         while (p)
    31         {
    32             d ++ ;
    33             p = p->nextarc;
    34         }
    35         indegree[i] = d;
    36     }
    37 //    for (int i=0;i<g.vexnum;i++)
    38 //        cout <<indegree[i] <<  ' ';
    39 }
    40 int  topoLogicalSort(ALGraph &g)
    41 {
    42     findInDegree(g); // 找到各定点的入度
    43     stack<int> st;
    44     // 把所有入度为0的顶点入栈
    45     for (int i  =0;i<g.vexnum;i++)
    46     {
    47         if (!indegree[i])
    48             st.push(i);
    49     }
    50     int i;
    51     arcNode *p;
    52     int count = 0 ; // 对输出顶点计数
    53     while (!st.empty())
    54     {
    55         i = st.top();
    56         st.pop();
    57         cout << g.adjList[i].data << ' ';
    58         count ++;
    59         for (p = g.adjList[i].firstarc ; p ; p=p->nextarc)
    60         {
    61             // 对I号顶点的每个邻接点的入度都减1
    62             int k = p->adjvex;
    63             if (!(--indegree[k]))
    64                 st.push(k); // 若减1后变为入度为0,入栈
    65         }
    66     }
    67     if (count < g.vexnum)
    68         return -1;
    69     else
    70         return 1;
    71 }
     

    关键路径

     1 int ve[MAXSIZE]; // 各顶点的最早开始时间
     2 int vl[MAXSIZE]; // 各顶点的最迟开始时间
     3 
     4 /* 
     5 1. 计算各顶点的最早开始时间ve
     6 2. T为拓扑序列顶点栈
     7 3. S为零入度顶点栈
     8 4. 若G无回路,则用栈T返回G的一个拓扑序列
     9 */
    10 int topoLogicalOrder(ALGraph &g,stack<int> &t)
    11 {
    12     findInDegree(g,indegree);
    13     stack<int> s;
    14     for (int i = 0;i<g.vexnum;i++)
    15     {
    16         if (!indegree[i])
    17             s.push(i);
    18     }
    19     int count =  0;
    20     for (int i=0;i<g.vexnum;i++)
    21         ve[i] = 0;
    22     while (!s.empty())
    23     {
    24         int j = s.top();
    25         s.pop();
    26         t.push(j);
    27         count ++ ;
    28         for (arcNode *p = g->adjList[j].firstarc ; p ; p = p->nextarc)
    29         {
    30             int k = p->adjvex;
    31             if (!(--indegree[k]))
    32                 s.push(k);
    33             if (ve[j]+*(p->info) > ve[k])
    34                 ve[k] = ve[j] + *(p->info);
    35         }
    36     }
    37     if (count <g.vexnum)
    38         return -1;
    39     else return 1;
    40 }
    41 
    42 // 关键路径
    43 int criticalPath(ALGraph &g)
    44 {
    45     // 目的:输出G的各项关键活动
    46     stack<int> t;
    47     arcNode *p;
    48     if (!topoLogicalOrder(g,t))
    49         return -1;
    50     for (int i=0;i<g.vexnum;i++)
    51         vl[i] = ve[g.vexnum-1] ; // 初始化均为最大值
    52     while (!t.empty())
    53     {
    54         int j = t.top();
    55         t.pop();
    56         for (p = g.adjList[j].firstarc ; p ; p= p->nextarc)
    57         {
    58             int k = p->adjvex;
    59             dut = *(p->info);
    60             if (vl[k]-dut < vl[j])
    61                 vl[j] = vl[k] - dut;
    62         }
    63     }
    64     for (j = 0;j<g.vexnum;j++)
    65     {
    66         for (p = g.adjList[i].firstarc ; p;p=p->nextarc)
    67         {
    68             int k = p->adjvex;
    69             dut = *(p->info);
    70             int ee = ve[j];
    71             el = vl[k] - dut;
    72             tag = (ee == el) > 
    73 
    74         }
    75     }
    76 
    77 
    78 
    79 }

    最短路径-迪杰斯特拉

     1 /* 最短路径
     2 1. 交通路网上从原点A到达目的地B的所含边的数目最少的路径,只需要广度优先搜索,遇到B点时停止
     3 2. 源点到其余各个顶点的最短路径--迪杰斯特拉算法--按照路径长度递增的次序产生最短路径的算法
     4 3. 求从源点v0到其余各点v的最短路径P[v]和带权长度d[v]
     5 4. p[v][w] == true, 则w是v0 - v 上最短路径的一个顶点,该路径显然经过v0 和 v
     6 5. final[v]为已经归入点集合的点
     7 */
     8 bool p[MAXSIZE][MAXSIZE];
     9 int d[MAXSIZE];
    10 bool final[MAXSIZE];
    11 
    12 void shortestPath(MGraph &g,int v0)
    13 {
    14 
    15     for (int i=0;i<g.vexnum;i++)
    16     {
    17         final[i] = false;
    18         d[i] = g.arc[v0][i].adj;
    19         for (int j = 0;j<g.vexnum;j++)
    20             p[i][j] = false;
    21 
    22         if (d[i]!=INFINITY)
    23         {
    24             p[i][i] = true;
    25             p[i][v0] = true;
    26         }
    27     }
    28     final[v0] = true;
    29     d[v0] = 0;
    30     int v;
    31     int min = INFINITY;
    32     for (int i=1;i < g.vexnum;i++)
    33     { // 对其余的g.vexnum - 1个顶点,每次选择最短的一条路径的顶点加入final集合
    34         min = INFINITY;
    35         for (int j=0;j<g.vexnum;j++)
    36             if (!final[j])
    37             if (d[j] < min)
    38         {
    39             min = d[j];
    40             v = j; // v是此次选出的顶点
    41         }
    42         final[v] = true;
    43         // 更新最短路径及距离
    44         for (int j = 0;j<g.vexnum;j++)
    45         {
    46             if (!final[j] && d[j] > (g.arc[v][j].adj + min)) //此处注意INFINIT + INT 不会小于 INFINIT,因为已经到了能存储的最大数
    47             {
    48                 d[j] = min + g.arc[v][j].adj;
    49                 for (int k = 0;k<g.vexnum;k++)
    50                     p[j][k] = p[v][k];
    51                 p[j][j] = true;
    52             }
    53         }
    54     }
    55 }
    56 
    57 void printShortestPath(MGraph &g)
    58 {
    59     int i;
    60     for (i = 1;i<g.vexnum;i++)
    61     {
    62         cout << g.vex[i] << "	"<<'(';
    63         for (int j = 0;j<g.vexnum;j++)
    64             if (p[i][j])
    65             cout << g.vex[j] <<' ' ;
    66         cout << ')'<<"	" ;
    67         cout << d[i] <<endl;
    68     }
    69 }
    测试数据

    // 迪杰特斯拉
    1
    6 8 0
    ABCDEF
    A C 10
    A E 30
    A F 100
    B C 5
    C D 50
    E D 20
    E F 60
    D F 10

  • 相关阅读:
    SAP ABAP 性能优化技巧 — “where” 语句的正确结构
    SAP ABAP 性能优化技巧 — 正确使用”move” 语句
    ABAP中如何检查字母数字类型(alpha numeric)的变量
    SAP ABAP 性能优化技巧 — 使用 “for all entries”
    SAP ABAP 性能优化技巧 — 性能分析的工具
    SAP ABAP 性能优化技巧 — 正确使用”inner join”
    SAP ABAP 性能优化技巧 — 缓存表
    SAP ABAP 性能优化技巧 — 使用 ABAP “Sort” 取代 “Order By”
    scp命令详解
    java.nio.Buffer flip()方法的用法详解
  • 原文地址:https://www.cnblogs.com/twomeng/p/9509532.html
Copyright © 2020-2023  润新知