数据结构实验报告(四)

实验报告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 }

原文地址:https://www.cnblogs.com/twomeng/p/9476701.html

时间: 2024-08-02 06:24:41

数据结构实验报告(四)的相关文章

20145123《实验报告四》

Java实验报告四:Android开发基础 实验要求: 1.安装Android Studio 2.运行安卓AVD模拟器 3.使用安卓运行出虚拟手机并显示HelloWorld以及自己的学号 实验过程 (一)SDK的安装 1. 2. 3.

操作系统实验报告四

操作系统实验4 题目1:编写页面内存的LRU替换算法 在实验3基础上考虑,如果当前分配的内存或保存页面的数据项已经被用完,这时再有新的网页请求,需要对已在内存中的网页数据进行替换,本实验内容需要使用LRU算法来对内存中的网页数据进行替换 题目2:编写页面内存的LFU替换算法 实现LFU(最少访问频率的页面替换)算法来管理内存页面 实验报告要求: 实验报告封面如下页所示. 按照题目要求,完成相关实验题目. 2.1报告中要包含完成此题目所查阅的一些关键技术材料.例如内存结构的设计.分配管理.回收方法

实验报告四

实验报告四 学   号201421450035   中国人民公安大学 Chinese people' public security university 网络对抗技术 实验报告   实验四 恶意代码技术     学生姓名 王雪洁 年级 2014级 区队 5 指导教师 高见     信息技术与网络安全学院 2016年11月7日   实验任务总纲 2016-2017 学年 第 一 学期 一.实验目的 1.通过对木马的练习,使读者理解和掌握木马传播和运行的机制:通过手动删除木马,掌握检查木马和删除木

java项目——数据结构实验报告

java项目——数据结构总结报告 20135315  宋宸宁 实验要求 1.用java语言实现数据结构中的线性表.哈希表.树.图.队列.堆栈.排序查找算法的类. 2.设计集合框架,使用泛型实现各类. 3.API的编写,并导出. 4.使用TDD模式,对程序进行测试,利用TestSuite将各测试类整合到一起. 5.与小组成员实现代码的整合. 实验设计过程 首先自学集合框架章节的内容,初步设计相关的类. 根据数据结构课本的章节分类,实验各数据结构类. 在类的编写过程中,经过老师的指导,我准备使用泛型

网络对抗技术 实验报告四

网络对抗技术 实验报告   实验四 恶意代码技术     学生姓名 李飞扬 年级 2014级 区队 二区队 指导教师 高见     信息技术与网络安全学院 2016年11月7日   实验任务总纲 2016-2017 学年 第 一 学期 一.实验目的 1.通过对木马的练习,使读者理解和掌握木马传播和运行的机制:通过手动删除木马,掌握检查木马和删除木马的技巧,学会防御木马的相关知识,加深对木马的安全防范意识. 2.了解并熟悉常用的网络攻击工具,木马的基本功能: 3.达到巩固课程知识和实际应用的目的.

实验报告 四(未完待续)

中国人民公安大学 Chinese people' public security university 网络对抗技术 实验报告   实验四 恶意代码技术     学生姓名 宋欣雨 年级 2015 区队 二 指导教师 高见     信息技术与网络安全学院 2016年11月7日   实验任务总纲 2016-2017 学年 第 一 学期 一.实验目的 1.通过对木马的练习,使读者理解和掌握木马传播和运行的机制:通过手动删除木马,掌握检查木马和删除木马的技巧,学会防御木马的相关知识,加深对木马的安全防范

实验报告 四

中国人民公安大学 Chinese people' public security university 网络对抗技术 实验报告   实验四 恶意代码技术     学生姓名 胥天浩 年级 2015 区队 5 指导教师 高见     信息技术与网络安全学院 2016年11月7日   实验任务总纲 2016-2017 学年 第 一 学期 一.实验目的 1.通过对木马的练习,使读者理解和掌握木马传播和运行的机制:通过手动删除木马,掌握检查木马和删除木马的技巧,学会防御木马的相关知识,加深对木马的安全防范

汇编语言程序设计实验报告四

南京信息工程大学实验报告 实验名称 实验 4 [bx]和loop的使用 实验日期 得分 学院 计软院 专业 计算机科学与技术 年级 2017级 班次 5班 姓名 陈奕明 学号 20171308194 一.实验目的 1. 理解和掌握寄存器间接寻址方式[bx] 2. 通过汇编指令loop的使用理解编程语言中循环的本质 3. 熟练掌握使用debug按需调试完整汇编源程序的方法 二.实验准备 1. 学习/复习第 5章使用[bx]和loop实现循环的编程应用示例(教材 5.5节,5.8节) 2. 复习第3

C语言程序设计实验报告四

C程序设计实验报告 姓 名:赖瑾 实验地点:家 实验时间:2020年4月9日 实验项目:5.3.1练习2 求数列的前n项和 5.3.2练习2 求水仙花数 5.3.4 十进制转换 5.3.5练习1 百马百担问题 5.3.5练习2 求等差数列 5.3.5练习3 食品分配问题 九九乘法表的实现 一.实验目的与要求 1.熟练地掌握while,do while及for语句实现循环的方法. 2.了解3种循环语句的区别和转换.各自的适应性.循环嵌套的使用. 3.掌握如何在循环语句种使用break,contin