数据结构实验报告(四)

实验报告4 图的有关操作

无向网的创建、求度、深度遍历、广度遍历

  1 #include <iostream>
  2 #include <stdlib.h>
  3 #include <stdio.h>
  4 #include <string>
  5 #define MAX_VERTEX_NUM 20
  6 
  7 using namespace std;
  8 //1.建立无向网的邻接表
  9 
 10 typedef int  InfoType;//权值
 11 typedef  char VertexType ;
 12 
 13 typedef struct ArcNode
 14 {
 15     int adjvex;//该弧的弧尾
 16     struct ArcNode *nextarc;//指向的下一个弧
 17     InfoType *info;
 18 }ArcNode;
 19 typedef struct VNode
 20 {
 21     VertexType data;//顶点类型和数据
 22     ArcNode *firstarc;//指向的第一条邻接弧
 23 }VNode,AdjList[MAX_VERTEX_NUM];//表头
 24 typedef struct
 25 {
 26     AdjList vertices;//
 27     int vexnum,arcnum;
 28     int kind; //DG 0 DN 1 UDG 2 UDN 3
 29 }ALGraph;//adjacency list graph 邻接表
 30 
 31 int locate(ALGraph &g,char v)
 32 {
 33     int i=0;
 34     for (i;i<g.vexnum;i++)
 35     {
 36         if (g.vertices[i].data == v)
 37             return i;
 38     }
 39 
 40 }
 41 void createUDN(ALGraph &g)
 42 {
 43     cout<<"构造无向网:请输入网的顶点个数和弧的个数"<<endl;
 44     cin>>g.vexnum>>g.arcnum;
 45     g.kind = 3;
 46 
 47     //构造顶点向量
 48     int i,j,k;
 49     //请输入每个顶点的值
 50     for (i=0;i<g.vexnum;i++)//初始化
 51     {
 52        cin>> g.vertices[i].data;
 53        g.vertices[i].firstarc  = NULL;//头结点置空
 54     }
 55 
 56     //构造链表们
 57     char v1,v2;
 58     int w;
 59     cout<<"请输入每条弧的弧头 、弧尾、权值"<<endl;
 60     for(k=0;k<g.arcnum;k++)
 61     {
 62         cin>>v1>>v2>>w;
 63         i = locate(g,v1);//弧尾
 64         j = locate(g,v2);//弧头
 65         ArcNode *p ;
 66         p = (ArcNode *)malloc(sizeof(ArcNode));//新建一块表结点空间
 67         p->adjvex = j;
 68         p->info = (int *)malloc(sizeof(int));//对于网,用来存放权值
 69         p->info = &w;
 70         p->nextarc = g.vertices[i].firstarc;//置空
 71         g.vertices[i].firstarc = p;//头插法建表
 72         if (g.kind >= 2) //如果是无向图或者无向网,需要做对称
 73     {
 74         p = (ArcNode *)malloc(sizeof(ArcNode));
 75         p->adjvex = i;
 76         p->info = (int *)malloc(sizeof(int));
 77         p->info = &w;
 78         p->nextarc = g.vertices[j].firstarc ;
 79         g.vertices[j].firstarc = p;
 80     }
 81 
 82     }
 83 
 84 }
 85 
 86 //求邻接表的入度和出度
 87 int* out(ALGraph &g)
 88 {
 89     int *p,*q;
 90     p = (int *) malloc((g.vexnum)*sizeof(int));//申请一个动态数组,存放的是每一个顶点对应的出度
 91     q=p;
 92     int i =0;
 93     int cou =1;//计数器
 94     for (i;i<g.vexnum ; i++)
 95     {
 96         //对每一个结点进行计算出度,循环一遍
 97         ArcNode *q=g.vertices[i].firstarc;//q指向第一个结点
 98         while (q->nextarc)
 99         {
100          cou++;
101          q=q->nextarc;
102         }
103         *p = cou;
104         p++;
105         cou=0;//清空计数器
106     }
107     return q;
108 }
109 int * in(ALGraph &g)
110 {
111     int *p;
112     p = (int *)malloc((g.vexnum)*sizeof(int));
113     int i=0;
114     int j=0;
115     int cou=0;
116     ArcNode *q;
117     for (i;i<g.vexnum;i++)
118     {//外层循环遍历每个结点,计算入度
119         for (j;j<g.vexnum;j++)
120         {
121             //内层循环遍历全部表元素
122             q = g.vertices[j].firstarc;
123             while (q->nextarc)
124             {
125                 if (q->adjvex == i)
126                     cou++;
127             }
128 
129         }
130         *p=cou;
131         p++;
132         cou=0;
133 
134     }
135     return p;
136 }
137 //深度优先搜索
138 bool visited[MAX_VERTEX_NUM];
139 
140 void DFSTraverse(ALGraph g)
141 {
142     void DFS(ALGraph g,int v);
143     int v;
144     //visited数组初始化
145     for (v=0;v<g.vexnum;v++)
146     visited[v]=false;
147 
148     for(v=0;v<g.vexnum;v++)
149     if (!visited[v])//如果结点未被访问过 ,则深度遍历该结点
150     DFS(g,v);
151 }
152 int FirstAdjVex(ALGraph &g,int v)
153 {
154     //对于无向网来说,每个顶点必定有一个邻接点
155     return g.vertices[v].firstarc->adjvex;//返回V结点的第一个邻接结点的序号
156 }
157 int NextAdjVex(ALGraph &g,int v,int w)
158 {//必须要讨论有没有除了第一个邻接点之外的第二个邻接点
159     //注意要找
160     ArcNode *p=g.vertices[v].firstarc;
161     while (p->adjvex!=w)
162         p=p->nextarc;
163     p = p->nextarc;
164     if (!p)
165         return -1;
166     else
167         return p->adjvex;//所以我们的条件为w>=0
168 }
169 void DFS(ALGraph g,int v)
170 {
171     visited[v]=true;//置标志
172     cout<<g.vertices[v].data<<" ";
173     int w;
174     for (w = FirstAdjVex(g,v);w>=0;w=NextAdjVex(g,v,w))
175         if (!visited[w])
176         DFS(g,w);
177 }
178 //广度优先搜索
179 typedef int Elemtype;
180 //进队出队为序号,输出时打印char数据,这样比较方便
181 typedef struct
182 {
183     Elemtype data[MAX_VERTEX_NUM];
184     int rear,front;
185 }SeqQueue;
186 void InitQueue(SeqQueue &q)
187 {
188     q.rear = q.front = -1;
189 }
190 void EnQueue(SeqQueue &q,Elemtype e )
191 {
192     q.rear = (q.rear+1)%MAX_VERTEX_NUM;
193     q.data[q.rear] = e;
194 }
195 void deQueue(SeqQueue &q,Elemtype &e)
196 {
197     if (q.rear == q.front)
198     {
199         printf("empty queue");
200     }
201     q.front = (q.front + 1)% MAX_VERTEX_NUM;
202     e = q.data[q.front];
203 
204 }
205 int QueueEmpty(SeqQueue &q)
206 {
207     return q.rear == q.front;
208 }
209 void BFSTraverse(ALGraph &g)
210 {
211     int v,u,w;
212     for (v=0;v<g.vexnum;v++)
213         visited[v]=false;
214     SeqQueue q;
215     InitQueue(q);
216     for (v=0;v<g.vexnum;v++)
217     {
218         if (!visited[v])
219         {
220             visited[v]=true;
221             printf("%c ",g.vertices[v].data);
222             EnQueue(q,v);
223             while (!QueueEmpty(q))
224             {
225                 deQueue(q,u);
226                 for ( w = FirstAdjVex(g,u);w>=0;w=NextAdjVex(g,u,w))
227                 {
228                     if (!visited[w])
229                     {
230                         visited[w]=true;
231                         printf("%c ",g.vertices[w].data);
232                         EnQueue(q,w);
233 
234                     }
235                 }
236 
237 
238 
239             }
240         }
241     }
242 
243 
244 }
245 int main()
246 {
247     ALGraph g;
248     createUDN(g);
249     //1.求无向网的度
250     cout<<"无向图的度为"<<endl;
251     int *p;p=out(g);int i=0;
252     for (p,i;i<g.vexnum;i++,p++)
253         cout<<*p<<" ";
254     cout<<endl;
255     //2.深度优先遍历
256     cout<<"深度优先遍历无向图"<<endl;
257     DFSTraverse(g);
258     //3.广度优先遍历
259     cout<<"广度优先遍历无向图"<<endl;
260     BFSTraverse(g);
261 
262     return 0;
263 }

实验报告内容:
1.键盘输入数据,建立一个有向图的邻接表。
2.输出该邻接表。
*3.建立一个无向图的十字链表。
4.在有向图的邻接表的基础上计算各顶点的度,并输出。
5.以有向图的邻接表为基础实现输出它的拓扑排序序列。
*6.采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径。
7.采用邻接表存储实现无向图的深度优先非递归遍历。
8.采用邻接表存储实现无向图的广度优先遍历。
*9.采用邻接矩阵存储实现无向图的最小生成树的PRIM算法。
*10.判断无向图任意两个顶点间是否有路径,若有输出路径上的顶点序列。
11.在主函数中设计一个简单的菜单,分别调试上述算法。
*12.综合训练:为计算机专业设计教学计划:4个学年,每学年2个学期,开设50门课程,每学期所开课程门数尽量均衡,课程的安排必须满足先修关系。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 20

using namespace std;
//1.定义有向网的邻接表结构

typedef int  InfoType;//权值
typedef  char VertexType ;

typedef struct ArcNode
{
    int adjvex;//该弧的弧尾
    struct ArcNode *nextarc;//指向的下一个弧
    InfoType info;
}ArcNode;
typedef struct VNode
{
    VertexType data;//顶点类型和数据
    ArcNode *firstarc;//指向的第一条邻接弧
}VNode,AdjList[MAX_VERTEX_NUM];//表头
typedef struct
{
    AdjList vertices;
    int vexnum,arcnum;
    int kind; //DG 0 DN 1 UDG 2 UDN 3 kind =1
}ALGraph;//adjacency list graph 邻接表

//一个桟
typedef int Elemtype;
typedef struct
{
    VertexType data[MAX_VERTEX_NUM];
    int top;
}SeqStack;
void InitStack(SeqStack &s)
{
    s.top=-1;
}
int isEmpty(SeqStack &s)
{
    return s.top==-1;
}
void push(SeqStack &s,Elemtype e)
{
    if (s.top == MAX_VERTEX_NUM)
        printf("full stack!");
    s.top++;
    s.data[s.top]=e;
}
void pop(SeqStack &s,Elemtype &e)
{
    if (isEmpty(s))
        printf("empty stack !");
    e = s.data[s.top--];
}
int getTop(SeqStack &s)
{
    return s.data[s.top];
}


//2.创建有向网
//定位函数
int locate(ALGraph &g,char v)
{
    int i=0;
    for (i;i<g.vexnum;i++)
    {
        if (g.vertices[i].data == v)
            return i;
    }

}
void createDN(ALGraph &g)
{
    cout<<"构造有向网:请输入网的顶点个数和弧的个数"<<endl;
    cin>>g.vexnum>>g.arcnum;
    g.kind = 1;

    //构造顶点向量
    int i,j,k;
    cout<<"请输入每个顶点的值"<<endl;
    for (i=0;i<g.vexnum;i++)//初始化
    {
       cin>> g.vertices[i].data;
       g.vertices[i].firstarc  = NULL;//头结点置空
    }

    //构造链表们
    char v1,v2;
    int w;
    cout<<"请输入每条弧的弧头 、弧尾、权值"<<endl;
    for(k=0;k<g.arcnum;k++)
    {
        cin>>v1>>v2>>w;
        i = locate(g,v1);//弧尾
        j = locate(g,v2);//弧头
        ArcNode *p ;
        p = (ArcNode *)malloc(sizeof(ArcNode));//新建一块表结点空间
        p->adjvex = j;
//        InfoType *info;
//        p->info = (int *)malloc(sizeof(int));//对于网,用来存放权值
//        p->info = &w;
        p->info = w;
        p->nextarc = g.vertices[i].firstarc;//置空
        g.vertices[i].firstarc = p;//头插法建表

    }

}
// 创建无向网
void createUDN(ALGraph &g)
{
    cout<<"构造无向网:请输入网的顶点个数和弧的个数"<<endl;
    cin>>g.vexnum>>g.arcnum;
    g.kind = 3;

    //构造顶点向量
    int i,j,k;
    //请输入每个顶点的值
    for (i=0;i<g.vexnum;i++)//初始化
    {
       cin>> g.vertices[i].data;
       g.vertices[i].firstarc  = NULL;//头结点置空
    }

    //构造链表们
    char v1,v2;
    int w;
    cout<<"请输入每条弧的弧头 、弧尾、权值"<<endl;
    for(k=0;k<g.arcnum;k++)
    {
        cin>>v1>>v2>>w;
        i = locate(g,v1);//弧尾
        j = locate(g,v2);//弧头
        ArcNode *p ;
        p = (ArcNode *)malloc(sizeof(ArcNode));//新建一块表结点空间
        p->adjvex = j;
        p->info = w;
        p->nextarc = g.vertices[i].firstarc;//置空
        g.vertices[i].firstarc = p;//头插法建表
        if (g.kind >= 2) //如果是无向图或者无向网,需要做对称
    {
        p = (ArcNode *)malloc(sizeof(ArcNode));
        p->adjvex = i;
        p->info = w;
        p->nextarc = g.vertices[j].firstarc ;
        g.vertices[j].firstarc = p;
    }

    }

}

//3.输出邻接表
void printALGraph(ALGraph &g)
{
  int i=0;
  ArcNode *p;

  for (i;i< g.vexnum ;i++)
  {
      printf("弧头:%c ",g.vertices[i].data);
      p=g.vertices[i].firstarc;//P指向链表的第一个结点
      while (p)
      {
          printf("(弧尾:%d,权值:%d) ",p->adjvex,p->info);
          p=p->nextarc;
      }
      cout<<endl;
  }
}
// 4.有向网的十字链表
typedef struct ArcBox
{
    int tailvex,headvex;
    struct ArcBox *hlink,*tlink;
    InfoType info;
}ArcBox;

typedef struct VexNode
{
    VertexType data;
    ArcBox *firstin,*firstout;
}VexNode;

typedef struct
{
    VexNode xlist[MAX_VERTEX_NUM];//表头向量
    int vexnum,arcnum;
}OLGraph;

int locate(OLGraph &g,char v)
{
    int i=0;
    for (i;i<g.vexnum;i++)
    {
        if (g.xlist[i].data == v)
        {
            return i;
        }
    }
}

void createOLDN(OLGraph &g)
{
    cout <<"请输入有向网的顶点个数、弧的个数"<<endl;
    cin>>g.vexnum>>g.arcnum;

    int i,j,k;
    cout<<"请输入顶点值"<<endl;
    for (i=0;i<g.vexnum;i++)
    {
        cin>>g.xlist[i].data;
        g.xlist[i].firstin=g.xlist[i].firstout=NULL;
    }
    cout<<"请输入每条弧的弧头和弧尾和权值"<<endl;
    char v1,v2;int w;
    ArcBox *p;
    fflush(stdin);
    for (k=0;k<g.arcnum;k++)
    {
        cin>>v1>>v2>>w;
        i=locate(g,v1);
        j=locate(g,v2);
        p=(ArcBox *)malloc(sizeof(ArcBox));
        //对弧结点赋值
        p->headvex = j;//弧的弧头
        p->tailvex = i;//弧的弧尾 逆邻接表
        p->hlink = g.xlist[j].firstin;//弧头相同的结点 逆邻接表
        p->tlink = g.xlist[i].firstout;//弧尾相同的结点
        p->info = w;
        g.xlist[j].firstin = g.xlist[i].firstout = p;


    }
}
//输出有向网的十字链表,分为邻接表和逆邻接表
void printOLGraph(OLGraph &g)
{
  cout<<"输出邻接表"<<endl;
  int i=0;
  ArcBox *p;

  for (i;i< g.vexnum ;i++)
  {
      printf("弧头:%c ",g.xlist[i].data);
      p=g.xlist[i].firstout;//P指向链表的第一个结点
      while (p)
      {
          printf("(弧尾:%d,权值:%d) ",p->headvex,p->info);
          p=p->tlink;
      }
      cout<<endl;
  }
  cout<<"输出逆邻接表"<<endl;
  for (i=0;i< g.vexnum ;i++)
  {
      printf("弧头:%c ",g.xlist[i].data);
      p=g.xlist[i].firstin;//P指向链表的第一个结点
      while (p)
      {
          printf("(弧尾:%d,权值:%d) ",p->tailvex,p->info);
          p=p->hlink;
      }
      cout<<endl;
  }
}
//5.无向图的十字链表
void createOLUDG(OLGraph &g)
{
    cout <<"请输入有向网的顶点个数、弧的个数"<<endl;
    cin>>g.vexnum>>g.arcnum;

    int i,j,k;
    cout<<"请输入顶点值"<<endl;
    for (i=0;i<g.vexnum;i++)
    {
        cin>>g.xlist[i].data;
        g.xlist[i].firstin=g.xlist[i].firstout=NULL;
    }
    cout<<"请输入每条弧的弧头和弧尾"<<endl;
    char v1,v2;
    ArcBox *p;
    fflush(stdin);
    for (k=0;k<g.arcnum;k++)
    {
        cin>>v1>>v2;
        i=locate(g,v1);
        j=locate(g,v2);
        p=(ArcBox *)malloc(sizeof(ArcBox));
        //对弧结点赋值
        p->headvex = j;//弧的弧头
        p->tailvex = i;//弧的弧尾 逆邻接表
        p->hlink = g.xlist[j].firstin;//弧头相同的结点 逆邻接表
        p->tlink = g.xlist[i].firstout;//弧尾相同的结点
        g.xlist[j].firstin = g.xlist[i].firstout = p;
        //无向图做对称
        p=(ArcBox *)malloc(sizeof(ArcBox));
        //对弧结点赋值
        p->headvex = i;//弧的弧头
        p->tailvex = j;//弧的弧尾 逆邻接表
        p->hlink = g.xlist[i].firstin;//弧头相同的结点 逆邻接表
        p->tlink = g.xlist[j].firstout;//弧尾相同的结点
        g.xlist[i].firstin = g.xlist[j].firstout = p;



    }
}
//输出无向图
void printOLGraph2(OLGraph &g)
{

  cout<<"输出邻接表"<<endl;
  int i=0;
  ArcBox *p;

  for (i=0;i< g.vexnum ;i++)
  {
      printf("弧头:%c->",g.xlist[i].data);
      p=g.xlist[i].firstout;//P指向链表的第一个结点
      while (p)
      {
          printf("%d->",p->headvex);
          p=p->tlink;
      }
      cout<<"NULL"<<endl;
  }
  cout<<"输出逆邻接表"<<endl;
  for (i=0;i< g.vexnum ;i++)
  {
      printf("弧头:%c->",g.xlist[i].data);
      p=g.xlist[i].firstin;//P指向链表的第一个结点
      while (p)
      {
          printf("%d->",p->tailvex);
          p=p->hlink;
      }
      cout<<"NULL"<<endl;
  }
}

//6.求邻接表的入度和出度
int* out(ALGraph &g)
{
    int *p,*q;
    p = (int *) malloc((g.vexnum)*sizeof(int));//申请一个动态数组,存放的是每一个顶点对应的出度
    q=p;
    int i =0;
    int cou =0;//计数器
    for (i=0;i<g.vexnum ; i++)
    {
        //对每一个结点进行计算出度,循环一遍
        ArcNode *q=g.vertices[i].firstarc;//q指向第一个结点
        while (q)
        {
         cou++;
         q=q->nextarc;
        }
        *p = cou;
        p++;
        cou=0;//清空计数器
    }
    return q;
}
int * in(ALGraph &g)
{
    int *p;
    p = (int *)malloc((g.vexnum)*sizeof(int));
    int i=0;
    int j=0;
    int cou=0;
    ArcNode *q;
    for (i=0;i<g.vexnum;i++)
    {//外层循环遍历每个结点,计算入度
        for (j=0;j<g.vexnum;j++)
        {
            //内层循环遍历全部表元素
            q = g.vertices[j].firstarc;
            while (q)
            {
                if (q->adjvex == i)
                    cou++;
                q=q->nextarc;
            }

        }
        p[i]=cou;
        cou=0;

    }
    return p;
}
int *InAndOut(ALGraph &g)
{
    int *p=in(g);
    int *q=out(g);
    int *k;
    k=(int *)malloc((g.vexnum)*sizeof(int));
    for (int i=0;i<g.vexnum;i++)
    {
        k[i]=p[i]+q[i];
    }
    return k;
}

//7.深度优先搜索
bool visited[MAX_VERTEX_NUM];

void DFSTraverse(ALGraph g)
{
    void DFS(ALGraph g,int v);
    int v;
    //visited数组初始化
    for (v=0;v<g.vexnum;v++)
    visited[v]=false;

    for(v=0;v<g.vexnum;v++)
    if (!visited[v])//如果结点未被访问过 ,则深度遍历该结点
    DFS(g,v);
}
int FirstAdjVex(ALGraph &g,int v)
{
    //对于无向网来说,每个顶点必定有一个邻接点
    return g.vertices[v].firstarc->adjvex;//返回V结点的第一个邻接结点的序号
}
int NextAdjVex(ALGraph &g,int v,int w)
{//必须要讨论有没有除了第一个邻接点之外的第二个邻接点
    //注意要找
    ArcNode *p=g.vertices[v].firstarc;
    while (p->adjvex!=w)
        p=p->nextarc;
    p = p->nextarc;
    if (!p)
        return -1;
    else
        return p->adjvex;//所以我们的条件为w>=0
}
void DFS(ALGraph g,int v)
{
    visited[v]=true;//置标志
    cout<<g.vertices[v].data<<" ";
    int w;
    for (w = FirstAdjVex(g,v);w>=0;w=NextAdjVex(g,v,w))
        if (!visited[w])
        DFS(g,w);
}
// 非递归
/*
1.栈初始化
2.输出起始顶点;起始顶点改为“已访问”标记;将起始顶点进桟
3.重复直到桟空
  3.1 取栈顶元素(不出桟)
  3.2 栈顶元素顶点存在未被访问过的邻接点W,则
    3.2.1 输出顶点W
    3.2.2 将顶点W改为已访问标志
    3.2.3 将顶点W进桟
  3.3 否则,当前顶点退桟
*/


int hasNextAdjVex(ALGraph &g,int h)
{
    //找到H的未被访问过的邻接点
    ArcNode *p=g.vertices[h].firstarc;
    if (!p)
        return -1;
    while (visited[p->adjvex])
    {
        p=p->nextarc;
    }
    return p->adjvex;

}
void DFS_2(ALGraph &g,int v)
{
    SeqStack s;
    InitStack(s);
    printf("%c",g.vertices[v].data);
    visited[v]=true;
    push(s,v);
    int h,w,e;
    while (!isEmpty(s))
    {
        h=getTop(s);
        w=hasNextAdjVex(g,h);
        if (w>=0)
        {
          printf("%c",g.vertices[w].data);
          visited[w]=true;
          push(s,w);
        }
        else
            pop(s,e);

    }

}
void DFSTraverse_2(ALGraph g)
{
    int v;
    //visited数组初始化
    for (v=0;v<g.vexnum;v++)
    visited[v]=false;

    for(v=0;v<g.vexnum;v++)
    if (!visited[v])//如果结点未被访问过 ,则深度遍历该结点
    DFS_2(g,v);
}
//8.广度优先搜索
typedef int Elemtype;
//进队出队为序号,输出时打印char数据,这样比较方便
typedef struct
{
    Elemtype data[MAX_VERTEX_NUM];
    int rear,front;
}SeqQueue;
void InitQueue(SeqQueue &q)
{
    q.rear = q.front = -1;
}
void EnQueue(SeqQueue &q,Elemtype e )
{
    q.rear = (q.rear+1)%MAX_VERTEX_NUM;
    q.data[q.rear] = e;
}
void deQueue(SeqQueue &q,Elemtype &e)
{
    if (q.rear == q.front)
    {
        printf("empty queue");
    }
    q.front = (q.front + 1)% MAX_VERTEX_NUM;
    e = q.data[q.front];

}
int QueueEmpty(SeqQueue &q)
{
    return q.rear == q.front;
}
void BFSTraverse(ALGraph &g)
{
    int v,u,w;
    for (v=0;v<g.vexnum;v++)
        visited[v]=false;
    SeqQueue q;
    InitQueue(q);
    for (v=0;v<g.vexnum;v++)
    {
        if (!visited[v])
        {
            visited[v]=true;
            printf("%c ",g.vertices[v].data);
            EnQueue(q,v);
            while (!QueueEmpty(q))
            {
                deQueue(q,u);
                for ( w = FirstAdjVex(g,u);w>=0;w=NextAdjVex(g,u,w))
                {
                    if (!visited[w])
                    {
                        visited[w]=true;
                        printf("%c ",g.vertices[w].data);
                        EnQueue(q,w);

                    }
                }



            }
        }
    }


}
//9.拓扑排序
// 建立辅助数组indegree 存放每个顶点的入度
void FindInDegree(ALGraph &g,int in[])
{
    int i=0,j=0;
    ArcNode *p;
    int count=0;
    for (i;i<g.vexnum;i++)
    {
        for (j=0;j<g.vexnum;j++)
        {
           p=g.vertices[j].firstarc;
           while (p)
           {
               if (p->adjvex == i)
                count++;
               p=p->nextarc;
           }
        }
        in[i] = count;
        cout<<count<<' ' ;
        count = 0;
    }
}
//这里需要一个栈

//拓扑排序算法
void TopologicalSort(ALGraph g)
{
    int indegree[g.vexnum];//定义一个入度的辅助数组
    int i,k;
    for (i=0;i<g.vexnum;i++)
    indegree[i]=0;
    FindInDegree(g,indegree);
    SeqStack s;
    InitStack(s);
    //如果入度为零则进栈
   for (i=0;i<g.vexnum;i++)
   {
       if (!indegree[i])
        push(s,i);//序号进栈
   }
   int count = 0;//对输出顶点个数进行计数
   ArcNode *p;
   while (!isEmpty(s))
   {
       pop(s,i);
       printf("%d:%c ",i,g.vertices[i].data);
       count++;
       for (p=g.vertices[i].firstarc;p;p=p->nextarc)
       {
           k=p->adjvex;
           if (!(--indegree[k]))
            push(s,k);
       }
   }
   if (count < g.vexnum)
    printf("该有向图有回路\n");
   else
    printf("该有向图无回路\n");


}

//10. PRIM 算法
//prim algorithm
//邻接矩阵
typedef int VRType;
typedef int VertexType2;
typedef int InfoType;
typedef struct ArcCell
{
    VRType adj;
    InfoType info;
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct
{
    VertexType2 vex[MAX_VERTEX_NUM];//顶点向量
    AdjMatrix arcs;//邻接矩阵
    int vexnum,arcnum;
    int kind;
}MGraph;
int locate(MGraph &g,int v)
{
    int i;
    for (i=0;i<g.vexnum;i++)
    {
       if (g.vex[i] == v)
            return i;
    }
}
//邻接数组创建无向图
void createUDG(MGraph &g)
{
    cout<<"请输入无向图的顶点个数和边的个数"<<endl;
    cin>>g.vexnum>>g.arcnum;
    int i,j,k;
    //初始化顶点向量
    for (i=0;i<g.vexnum;i++)
        cin>>g.vex[i];
        //初始化邻接矩阵
    for (i=0;i<g.vexnum;i++)
        for (j=0;j<g.vexnum;j++)
        g.arcs[i][j].adj = INFINITY;
        cout<<"请输入每条边的顶点和权值"<<endl;
    for (k=0;k<g.arcnum;k++)
    {
        int v1,v2;
        int w;
        cin>>v1>>v2>>w;
        i=locate(g,v1);
        j=locate(g,v2);
        g.arcs[i][j].adj=w;
        g.arcs[j][i].adj=g.arcs[i][j].adj;//无向图为对称的!
    }

}
typedef struct node {
    VertexType2 adjvex;//权最小的顶点
    VRType lowcost;//最小的权
    }closedge[MAX_VERTEX_NUM];

int mininum(closedge close,int n)
{
    int i=0;
    int min = 999;
    int k;
    for (i=1;i<n;i++)
    {
      if (close[i].lowcost < min && close[i].lowcost !=0)
      {
          min = close[i].lowcost;
          k = i;
      }
    }
    return k;
    //k记录最小权值顶点的序号

}
//最小生成树——PRIM算法
void MinispanTree_PRIM(MGraph g,VertexType2 u)
{

    closedge close;
    int k=locate(g,u);
    int i,j;
    //辅助数组初始化
    for (j=0;j<g.vexnum;j++)
        if (j!=k)
    {
      close[j].adjvex=u;
      close[j].lowcost = g.arcs[k][j].adj;
    }
    close[k].lowcost = 0;
    for (i=1;i<g.vexnum;i++)
    {
        k = mininum(close,g.vexnum);
        cout<<"("<<close[k].adjvex<<","<<g.vex[k]<<")";//输出这条边的两个顶点
        close[k].lowcost = 0;
        for (j=0;j<g.vexnum;j++)
        {
            if (g.arcs[k][j].adj < close[j].lowcost)
            {
                close[j].adjvex = g.vex[k];
                close[j].lowcost = g.arcs[k][j].adj;
            }

        }


    }

}
int main()
{
    cout << "------------------------------------"<<endl;
    cout << "1.createDN():建立一个有向网的邻接表 "<<endl;
    cout << "2.printALGraph():输出邻接表"<<endl;
    cout << "3.createOLDN():创建有向网十字链表并输出其邻接表和逆邻接表"<<endl;
    cout << "4.createOLUDG():创建无向图十字链表并输出其邻接表和逆邻接表"<<endl;
    cout << "5.in():求有向图/网的出度"<<endl;
    cout << "6.out():求有向图/网的入度"<<endl;
    cout << "7.InAndOut():求有向图的度"<<endl;
    cout << "8.DFSTraverse():无向图的深度优先遍历"<<endl;
    cout << "9.BFSTraverse():无向图的广度优先遍历"<<endl;
    cout << "10.TopologicalSort():以有向图的邻接表为基础实现输出它的拓扑排序序列。"<<endl;
    cout << "11.MinispanTree_PRIM():采用邻接矩阵存储实现无向图的最小生成树的PRIM算法"<<endl;
    cout << "12.DFS_2():非递归实现深度优先搜索"<<endl;
    cout << "------------------------------------"<<endl;

LL1:

    cout<< "请输入您要选择的函数序号:)"<<endl;
    int num,i;cin>>num;int *p;
    switch(num)
    {
    case 1:
    ALGraph g;
    createDN(g);
    cout<<"创建一个有向网的邻接表成功!"<<endl;
        break;
    case 2:
        createDN(g);
        printALGraph(g);
        break;
    case 3:
        OLGraph g1;
        createOLDN(g1);
        printOLGraph(g1);
        break;
    case 4:
        createOLUDG(g1);
        printOLGraph2(g1);
        break;
    case 5:
        createDN(g);
        p=in(g);
        for (i=0;i<g.vexnum;i++,p++)
            cout<<g.vertices[i].data<<":"<<*p<<" ";
        cout<<endl;
        break;
    case 6:
        createDN(g);
        p=out(g);
        for (i=0;i<g.vexnum;i++,p++)
            cout<<g.vertices[i].data<<":"<<*p<<" ";
        cout<<endl;
        break;
    case 7:
        createDN(g);
        p=InAndOut(g);
        for (i=0;i<g.vexnum;i++)
            cout<<g.vertices[i].data<<":"<<(p[i])<<" ";
        cout<<endl;

        break;
    case 8:
        createUDN(g);
        DFSTraverse(g);
        break;
    case 9:
        createUDN(g);
        BFSTraverse(g);
        break;
    case 10:
        createDN(g);
        TopologicalSort(g);
        break;
    case 11:
        MGraph gg;
        createUDG(gg);
        MinispanTree_PRIM(gg,0);
        break;
    case 12:
        createUDN(g);
        DFSTraverse_2(g);
    }
    fflush(stdin);
    char c;
cout <<"您是否要继续测试函数?y/n"<<endl;
cin >> c;
if (c == 'y')
    goto LL1;
else
    return 0;
}

第6,10题在此单独测试:

  1 #include <iostream>
  2 #define MAX_VERTEX_NUM 20
  3 #define INFINITY INT_MAX
  4 using namespace std;
  5 //判断无向图任意两个顶点间是否有路径,若有输出路径上的顶点序列。
  6 //floid 算法
  7 //邻接矩阵
  8 
  9 typedef char VertexType;
 10 typedef int VRType;
 11 typedef int InfoType;
 12 typedef struct ArcCell
 13 {
 14     VRType adj;
 15     InfoType *info;
 16 }ArcCell,ArcMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
 17 
 18 typedef struct
 19 {
 20     int kind ;
 21     int vexnum,arcnum;
 22     VertexType vexs[MAX_VERTEX_NUM];
 23     ArcMatrix arcs;
 24 }MGraph;
 25 
 26 int locate(MGraph &g,VertexType v)
 27 {
 28     int i;
 29     for (i=0;i<g.vexnum;i++)
 30     {
 31         if (g.vexs[i] == v)
 32         return i;
 33     }
 34 }
 35 void createUDN(MGraph &g)
 36 {
 37     cout <<"请输入顶点个数和弧的条数"<<endl;
 38     cin >> g.vexnum>>g.arcnum;
 39     int i,j,k;
 40     cout <<"请输入顶点集合"<<endl;
 41     for (i=0;i<g.vexnum;i++)
 42     {
 43       cin >>g.vexs[i];
 44       for (j=0;j<g.vexnum;j++)
 45       {
 46           if (i!=j)
 47              g.arcs[i][j].adj=INFINITY;
 48           else
 49              g.arcs[i][j].adj=0;
 50       }
 51 
 52     }
 53 
 54 
 55     cout <<"请输入各条弧的弧头、弧尾以及权值"<<endl;
 56     char v1,v2;
 57     int w;
 58     for (k=0;k<g.arcnum;k++)
 59     {
 60         cin >>v1>>v2>>w;
 61         i=locate(g,v1);
 62         j=locate(g,v2);
 63         g.arcs[i][j].adj=w;
 64         //无向网做对称
 65         g.arcs[j][i].adj=w;
 66 
 67     }
 68 }
 69 void printAdjMatrix(MGraph &g)
 70 {
 71     int i,j;
 72     for (i=0;i<g.vexnum;i++)
 73     {
 74     for (j=0;j<g.vexnum;j++)
 75     cout <<g.arcs[i][j].adj<<" ";
 76     cout <<endl;
 77     }
 78 
 79 }
 80 typedef bool PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];
 81 typedef int distanceMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
 82 
 83 void ShortestPath_FLOYD(MGraph &g,PathMatrix &p,distanceMatrix &d)
 84 {
 85     void printD(MGraph g,distanceMatrix &d);
 86     int v,w,u,i;
 87     for (v=0;v<g.vexnum;v++)
 88         for (w=0;w<g.vexnum;w++)
 89     {
 90         d[v][w]=g.arcs[v][w].adj;
 91     for (u=0;u<g.vexnum;u++)
 92     {
 93         p[v][w][u]=false;
 94     }
 95     if (d[v][w] < INFINITY )
 96     {
 97         p[v][w][v]=true;
 98         p[v][w][w]=true;
 99     }
100     }
101 
102     for (u=0;u<g.vexnum;u++)
103         for (v=0;v<g.vexnum;v++)
104         for (w=0;w<g.vexnum;w++)
105         {
106             if (d[v][u]!=INFINITY && d[u][w]!=INFINITY )
107         if (d[v][u] + d[u][w] < d[v][w])
108     {
109         d[v][w] = d[v][u]+d[u][w];
110         for (i=0;i<g.vexnum ;i++)
111         p[v][w][i]=p[v][u][i] || p[u][w][i];
112 
113     }
114 
115         }
116 
117 }
118 void printD(MGraph g,distanceMatrix &d)
119 {
120     int i,j;
121     for(i=0;i<g.vexnum;i++)
122     {
123          for (j=0;j<g.vexnum;j++)
124          {
125              cout << d[i][j]<<" ";
126          }
127          cout <<endl;
128     }
129 
130 }
131 
132 void printShortestPath_FLOIY(MGraph g,PathMatrix &p,distanceMatrix &d)
133 {
134     int i,j,k;
135     for (i=0;i<g.vexnum;i++)
136     {
137         for (j=0;j<=i;j++) // 输出一半即可
138         {
139             cout <<"顶点对:  <"<<g.vexs[i]<<","<<g.vexs[j]<<">   (";
140             for (k=0;k<g.vexnum;k++)
141             {
142                 if (p[i][j][k])
143                     cout <<g.vexs[k]<<" ";
144             }
145             cout <<" )"<<"   路径长度:"<<d[i][j]<<endl;
146         }
147     }
148 }
149 int main()
150 {
151     MGraph g;
152     createUDN(g);
153     PathMatrix p;
154     distanceMatrix d;
155     ShortestPath_FLOYD(g,p,d);
156     cout << " 输出每对顶点的最短路径"<<endl;
157     printShortestPath_FLOIY(g,p,d);
158 
159 
160 
161     return 0;
162 }
163 #include <iostream>
164 #define MAX_VERTEX_NUM 20
165 #define INFINITY INT_MAX
166 using namespace std;
167 //采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径。
168 //迪杰特斯拉
169 
170 typedef char VertexType;
171 typedef int VRType;
172 typedef int InfoType;
173 typedef struct ArcCell
174 {
175     VRType adj;
176     InfoType *info;
177 }ArcCell,ArcMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
178 
179 typedef struct
180 {
181     int kind ;
182     int vexnum,arcnum;
183     VertexType vexs[MAX_VERTEX_NUM];
184     ArcMatrix arcs;
185 }MGraph;
186 
187 int locate(MGraph &g,VertexType v)
188 {
189     int i;
190     for (i=0;i<g.vexnum;i++)
191     {
192         if (g.vexs[i] == v)
193         return i;
194     }
195 }
196 void createDN(MGraph &g)
197 {
198     cout <<"请输入顶点个数和弧的条数"<<endl;
199     cin >> g.vexnum>>g.arcnum;
200     int i,j,k;
201     cout <<"请输入顶点集合"<<endl;
202     for (i=0;i<g.vexnum;i++)
203     {
204       cin >>g.vexs[i];
205       for (j=0;j<g.vexnum;j++)
206       g.arcs[i][j].adj=INFINITY;
207     }
208 
209 
210     cout <<"请输入各条弧的弧头、弧尾以及权值"<<endl;
211     char v1,v2;
212     int w;
213     for (k=0;k<g.arcnum;k++)
214     {
215         cin >>v1>>v2>>w;
216         i=locate(g,v1);
217         j=locate(g,v2);
218         g.arcs[i][j].adj=w;
219 
220     }
221 }
222 
223 void printAdjMatrix(MGraph &g)
224 {
225     int i,j;
226     for (i=0;i<g.vexnum;i++)
227     {
228     for (j=0;j<g.vexnum;j++)
229     cout <<g.arcs[i][j].adj<<" ";
230     cout <<endl;
231     }
232 
233 }
234 
235 typedef int ShortPathTable[MAX_VERTEX_NUM];
236 typedef bool PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
237 
238 void shortestPath_DIJ(MGraph &g,int v0,PathMatrix &p,ShortPathTable &d)
239 {
240 // final d p
241     bool final[g.vexnum];
242     int v,w,i,j;
243     for (v=0;v<g.vexnum;v++)
244     {
245         final[v]=false;
246         d[v]=g.arcs[v0][v].adj;
247         for (w=0;w<g.vexnum;w++)
248         p[v][w]=false;
249 
250         if (d[v] < INFINITY)
251         {
252             p[v][v0]=true;
253             p[v][v]=true;
254         }
255     }
256 
257     d[v0]=0;//自己到自己
258     final[v0]=true;//并到S集合中
259     int min;
260     for (i=0;i<g.vexnum;i++)
261     {
262         min = INFINITY;
263         for (w=0;w<g.vexnum;w++)
264         {
265             if (!final[w])
266             if (d[w]<min)
267             {
268                 v=w;
269                 min=d[w];
270             }
271         }
272         final[v]=true;
273         for (w=0;w<g.vexnum;w++)
274         {
275             //对于每个顶点,在介入离V0最近的点之后是否会离v0更近呢?
276             if (!final[w]&&(min+g.arcs[v][w].adj<d[w]))
277             {
278                 d[w]=min+g.arcs[v][w].adj;
279                 //p[w]=p[v];
280                 for (j=0;j<g.vexnum;j++)
281                 p[w][j]=p[v][j];
282                 p[w][w]=true;
283             }
284         }
285     }
286 }
287 void printP(PathMatrix &p)
288 {
289     int i,j;
290     for (i=0;i<6;i++)
291     {
292       for (j=0;j<6;j++)
293     cout << p[i][j]<<" ";
294     cout <<endl;
295     }
296 
297 }
298 void printD(ShortPathTable &d)
299 {
300     int i;
301     for (i=0;i<6;i++)
302     cout<<d[i]<<" ";
303     cout<<endl;
304 }
305 void printShortestPath(MGraph &g,PathMatrix &p,ShortPathTable &d)
306 {
307     int i,j;
308     for (i=1;i<g.vexnum;i++)
309     {
310         cout <<g.vexs[i]<<":";
311         cout <<"    最短路径:(";
312         for (j=0;j<g.vexnum;j++)
313         if (p[i][j])
314         cout <<g.vexs[j]<<" ";
315         cout <<")    路径长度:"<<d[i]<<endl;
316     }
317 }
318 int main()
319 {
320     MGraph g;
321     createDN(g);
322     printAdjMatrix(g);
323     PathMatrix p;
324     ShortPathTable d;
325     shortestPath_DIJ(g,0,p,d);
326     // v0 = 0 为单源点
327     printP(p);
328     printD(d);
329     printShortestPath(g,p,d);
330     return 0;
331 }

猜你喜欢

转载自www.cnblogs.com/twomeng/p/9476701.html