c++实验9 图及图的操作实验

我的梦境 提交于 2020-03-08 04:24:49

实验9 图及图的操作实验

--博客后半部分有程序的所有代码--

1、图邻接矩阵存储结构表示及基本操作算法实现

(1)邻接矩阵存储结构类定义:

#include "SeqList.h"        //包含动态数组结构的顺序表类
#include "SeqQueue.h"        //包含静态数组结构的顺序队列类
typedef char VerT;    //定义邻接矩阵图类中的VerT

class AdjMWGraph
{
private:
    SeqList Vertices;            //顶点顺序表
    int Edge[MaxVertices][MaxVertices];    //边权值数组
    double numOfEdges;            //边的个数
    void DepthFirstSearch(const int v, int visited[]);
    void BroadFirstSearch(const int v, int visited[]);
public:
    AdjMWGraph(const int sz=MaxVertices);    //构造函数
    ~AdjMWGraph(void){};                //析构函数
    int NumOfVertices(void)                //取顶点个数
        {return Vertices.Size();}
    int NumOfEdges(void)                //取边的个数
        {return numOfEdges;}
    Void Show();                         //输出邻接矩阵结果
    VerT GetValue(const int v);            //取顶点数值
    int GetWeight(const int v1, const int v2);        //取边的权值
    void InsertVertex(const VerT &vertex);        //插入顶点
    void InsertWayEdge(const int v1, const int v2, int weight);//插入边
    void InsertNoWayEdge(const int v1, const int v2, int weight);//插入边
    void DeleteVertex(const int v);            //删除顶点
    void DeleteEdge(const int v1, const int v2);    //删除边
    int GetFirstNeighbor(const int v);        //取第一个邻接顶点
    int GetNextNeighbor(const int v1, const int v2);//取下一个邻接顶点
    void DepthFirstSearch();    //深度优先遍历
    void BroadFirstSearch();    //广度优先遍历
};
struct RowColWeight           //网的结构体
{    int row;                //行下标
    int col;                    //列下标
    int weight;                //权值
};
struct RowCol             //图的结构体
{
    int row;                //行下标
    int col;                    //列下标
};

 

(2)创建邻接矩阵算法

①创建无向图邻接矩阵算法:

void CreatNoWayGraph(AdjMWGraph &G,  DataType V[],int n,RowCol E[],  int e)
{
        //在图G中插入n个顶点
    for(int i = 0; i < n; i++)
        G.InsertVertex(V[i]);
        //在图G中插入e条边
    for(int k = 0; k < e; k++)
    {
        if(E[k].row>E[k].col)
            {
                cout<<"无向图参数输入错误";
                exit(0);
            }
        G.InsertNoWayEdge(E[k].row, E[k].col, 1);
        G.InsertNoWayEdge(E[k].col, E[k].row, 1);
    }
}

②创建无向网邻接矩阵算法:

void CreatNoWayWeb(AdjMWGraph &G,  DataType V[],int n,RowColWeight E[],  int e)
{
        //在图G中插入n个顶点
    for(int i = 0; i < n; i++)
        G.InsertVertex(V[i]);
        //在图G中插入e条边
    for(int k = 0; k < e; k++)
    {
        if(E[k].row>E[k].col)
            {
                cout<<"无向网参数输入错误";
                exit(0);
            }
        G.InsertNoWayEdge(E[k].row, E[k].col, E[k].weight);
        G.InsertNoWayEdge(E[k].col, E[k].row, E[k].weight);
    }

③创建有向图邻接矩阵算法:

void CreatWayGraph(AdjMWGraph &G,  DataType V[],int n,RowCol E[],  int e)
//在图G中插入n个顶点V 和  e条边E
{
    //在图G中插入n个顶点
    for(int i = 0; i < n; i++)
        G.InsertVertex(V[i]);
    //在图G中插入e条边
    for(int k = 0; k < e; k++)
        G.InsertWayEdge(E[k].row, E[k].col,1);
}

创建有向网邻接矩阵算法:

void CreatWayWeb(AdjMWGraph &G,  DataType V[],int n,RowColWeight E[],  int e)
//在图G中插入n个顶点V 和  e条边E
{
    //在图G中插入n个顶点
    for(int i = 0; i < n; i++)
        G.InsertVertex(V[i]);
    //在图G中插入e条边
    for(int k = 0; k < e; k++)
        G.InsertWayEdge(E[k].row, E[k].col, E[k].weight);
}

 

(3)输出邻接矩阵结果算法

int AdjMWGraph::Show()
{
    for(int i=0;i<Vertices.Size();i++)
    {
        for(int j=0;j<Vertices.Size();j++)
        {
            int a=GetWeight(i,j);
            if(a==MaxWeight)
                cout<<"∞ ";
            else
                cout<<a<<" ";
        }
        cout<<endl;
    }
}

测试数据:

int main()
{
    AdjMWGraph g,f;
    char a[] = {'A','B','C','D','E'};
    char b[] = {'A','B','C','D','E','F'};

    RowColWeight r1[] ={{0,1,10},{0,4,20},{1,3,30},{2,1,40},{3,2,50}};
    RowColWeight r2[] ={{0,1,10},{0,4,20},{1,3,30},{1,2,40},{2,3,50},{4,5,15}};
    int n1,n2,e1,e2;
    n1=sizeof(a)/sizeof(a[0]);
    n2=sizeof(b)/sizeof(b[0]);
    e1=sizeof(r1)/sizeof(r1[0]);
    e2=sizeof(r2)/sizeof(r2[0]);
    CreatWayWeb(g, a, n1, r1, e1);        //创建有向网
    CreatNoWayWeb(f, b, n2, r2, e2);        //创建无向网

    cout<<"有向网:"<<endl;
    g.Show();

    cout<<"\n\n无向网"<<endl;
    f.Show();

    return 0;
}

结果:

2、图的遍历递归算法

(1)(存储结构为邻接矩阵)深度优先遍历算法

void AdjMWGraph::DepthFirstSearch(const int v, int visited[])
//连通图G以v为初始顶点序号
//数组visited标记了相应顶点是否已访问过,
// 0表示未访问,1表示已访问
{
     cout<<GetValue(v)<<" ";  //访问该顶点
    visited[v] = 1;        //置已访问标记
  //取第一个邻接顶点
    int w = GetFirstNeighbor(v);
 //当邻接顶点存在时循环
    while(w != -1)
    {
         if(! visited[w])
               DepthFirstSearch(w, visited);     //递归
         w = GetNextNeighbor(v, w);    //取下一个邻接顶点
    }
}
void AdjMWGraph::DepthFirstSearch()
{
    int *visited = new int[NumOfVertices()];
    //初始化访问标记
    for(int i = 0; i < NumOfVertices(); i++)
         visited[i] = 0;
    //深度优先遍历
    for(int i = 0; i < NumOfVertices(); i++)
         if(! visited[i])
            DepthFirstSearch(i, visited);
    delete []visited;
}

 

有向/无向网的测试结果:

 

(2)广度优先遍历算法

void AdjMWGraph::BroadFirstSearch(const int v, int visited[])
{
    VerT u;
    int w;
    SeqQueue queue;                //定义队列
    cout<<GetValue(v)<<" ";            //访问该顶点
    visited[v] = 1;                    //置已访问标记
    queue.Append(v);                //顶点v入队列
    while(queue.NotEmpty())            //队列非空时循环
   {
        u = queue.Delete();            //出队列
        w = GetFirstNeighbor(u);         //取顶点u的第一个邻接顶点
        while(w != -1)            //邻接顶点存在时
        {
            if(!visited[w])        //若该顶点没有访问过
            {
                cout<<GetValue(w)<<" ";    //访问该顶点
                visited[w] = 1;        //置已访问标记
                queue.Append(w);    //顶点w入队列
            }
            w = GetNextNeighbor(u, w);
        }
   }
}

void AdjMWGraph::BroadFirstSearch()
//非连通图G访问操作为Visit()的广度优先遍历
{
    int *visited = new int[NumOfVertices()];
    for(int i = 0; i < NumOfVertices(); i++)
        visited[i] = 0;
    for(int i = 0; i < NumOfVertices(); i++)
        if(!visited[i])
              BroadFirstSearch(i, visited);
    delete []visited;
}

 有向网/无向网的测试结果:

 

最后附上整体代码结构与结果

 

AdjMWGraph.h

#include "SeqList.h"        //包含动态数组结构的顺序表类
#include "SeqQueue.h"        //包含静态数组结构的顺序队列类
typedef char VerT;    //定义邻接矩阵图类中的VerT

class AdjMWGraph
{
private:
    SeqList Vertices;            //顶点顺序表
    int Edge[MaxVertices][MaxVertices];    //边权值数组
    double numOfEdges;            //边的个数
    void DepthFirstSearch(const int v, int visited[]);
    void BroadFirstSearch(const int v, int visited[]);
public:
    AdjMWGraph(const int sz=MaxVertices);    //构造函数
    ~AdjMWGraph(void){};                //析构函数
    void Show();                         //输出邻接矩阵结果
    int NumOfVertices(void)                //取顶点个数
        {return Vertices.Size();}
    int NumOfEdges(void)                //取边的个数
        {return numOfEdges;}
    VerT GetValue(const int v);            //取顶点数值
    int GetWeight(const int v1, const int v2);        //取边的权值
    void InsertVertex(const VerT &vertex);        //插入顶点
    void InsertWayEdge(const int v1, const int v2, int weight);//插入边
    void InsertNoWayEdge(const int v1, const int v2, int weight);//插入边
    void DeleteVertex(const int v);            //删除顶点
    void DeleteEdge(const int v1, const int v2);    //删除边
    int GetFirstNeighbor(const int v);        //取第一个邻接顶点
    int GetNextNeighbor(const int v1, const int v2);//取下一个邻接顶点
    void DepthFirstSearch();    //深度优先遍历
    void BroadFirstSearch();    //广度优先遍历
};
AdjMWGraph::AdjMWGraph(const int sz): Vertices(sz)
//构造函数  ,构造顶点个数为sz个,没有边的图
{
    for(int i = 0; i < sz; i++)
        for(int j = 0; j < sz; j++)
        {
            if(i == j)
                Edge[i][j] = 0;
            else
                Edge[i][j] = MaxWeight;
         } // MaxWeight权值的无穷大
    numOfEdges = 0;
}
VerT AdjMWGraph::GetValue(const int v)
//取顶点v的数值
{
    if(v < 0 || v >= Vertices.Size())
    {
        cout << "参数v越界出错!" << endl;
        exit(0);
    }
    return Vertices.GetData(v);
}
int AdjMWGraph::GetWeight(const int v1, const int v2)
//取起始顶点为v1、终止顶点为 v2的边的权值
{
    if(v1 < 0 || v1 >= Vertices.Size() || v2 < 0 || v2 >= Vertices.Size())
    {
        cout << "参数v1或v2越界出错!" << endl;
        exit(0);
    }
    return Edge[v1][v2];
}

void AdjMWGraph::InsertVertex(const VerT &vertex)
//插入顶点vertex   //把顶点vertex插入到顺序表的当前表尾位置
{

    Vertices.Insert(vertex, Vertices.Size());
}
void AdjMWGraph::InsertWayEdge(const int v1, const int v2, int weight)
//插入一条起始顶点为v1、终止顶点为 v2、权值为weight的边
{
      if(v1 < 0||v1>=Vertices.Size()||v2 < 0||v2 >=Vertices.Size())
    {
        cout << "参数v1或v2越界出错!" << endl;
        exit(0);
    }
    Edge[v1][v2] = weight;                            //插入边
    numOfEdges++;                            //边的个数加1
}void AdjMWGraph::InsertNoWayEdge(const int v1, const int v2, int weight)
//插入一条起始顶点为v1、终止顶点为 v2、权值为weight的边
{
      if(v1 < 0||v1>=Vertices.Size()||v2 < 0||v2 >=Vertices.Size())
    {
        cout << "参数v1或v2越界出错!" << endl;
        exit(0);
    }
    Edge[v1][v2] = weight;                            //插入边
    numOfEdges+=0.5;                            //边的个数加0.5
}
void AdjMWGraph::DeleteVertex(const int v)
//删除顶点v
{
    //删除所有包含顶点v的边
    for(int i = 0; i < Vertices.Size(); i++)
        for(int j = 0; j < Vertices.Size(); j++)
            if((i == v || j == v) && i != j && Edge[i][j] > 0 && Edge[i][j] < MaxWeight)
            {
               Edge[i][j] = MaxWeight;   //把该边的权值置为无穷大
               numOfEdges--;            //边的个数减1
            }
    Vertices.Delete(v);    //删除顶点v
}
void AdjMWGraph::DeleteEdge(const int v1, const int v2)
//删除一条起始顶点为v1、终止顶点为 v2的边
{
    if(v1 < 0 || v1 >Vertices.Size()||v2<0||v2>Vertices.Size())
    {
        cout<<Vertices.Size();
        cout << "参数v1或v2出错!" << endl;
        exit(0);
    }
    if(Edge[v1][v2] == MaxWeight )
    {
        cout << "该边不存在!" << endl;
        exit(0);
    }
    Edge[v1][v2] = MaxWeight;    //把该边的权值置为无穷大
    numOfEdges--;            //边的个数减1
}
int AdjMWGraph::GetFirstNeighbor(const int v)
//取顶点v的第一个邻接顶点。若存在返回该顶点的下标序号,否则返回-1
{
    if(v< 0 || v> Vertices.Size())
    {
        cout << "参数v1越界出错!" << endl;
        exit(0);
    }
    for(int col = 0; col <=Vertices.Size(); col++)
          if(Edge[v][col] > 0 && Edge[v][col] < MaxWeight)
         return col;
    return -1;
}

int AdjMWGraph::GetNextNeighbor(const int v1, const int v2)
//取顶点v1的邻接顶点v2后的邻接顶点
//若存在返回该顶点的下标序号,否则返回-1
{
    if(v1 < 0 || v1 > Vertices.Size() || v2 < 0 || v2 >Vertices.Size())
    {
        cout << "参数v1或v2越界出错!" << endl;
        exit(0);
    }
    for(int col = v2+1; col < Vertices.Size(); col++)
        if(Edge[v1][col] > 0 && Edge[v1][col] < MaxWeight)
             return col;
    return -1;
}
void AdjMWGraph::DepthFirstSearch(const int v, int visited[])
//连通图G以v为初始顶点序号
//数组visited标记了相应顶点是否已访问过,
// 0表示未访问,1表示已访问
{
     cout<<GetValue(v)<<" ";  //访问该顶点
    visited[v] = 1;        //置已访问标记
  //取第一个邻接顶点
    int w = GetFirstNeighbor(v);
 //当邻接顶点存在时循环
    while(w != -1)
    {
         if(! visited[w])
               DepthFirstSearch(w, visited);     //递归
         w = GetNextNeighbor(v, w);    //取下一个邻接顶点
    }
}
void AdjMWGraph::DepthFirstSearch()
{
    int *visited = new int[NumOfVertices()];
    //初始化访问标记
    for(int i = 0; i < NumOfVertices(); i++)
         visited[i] = 0;
    //深度优先遍历
    for(int i = 0; i < NumOfVertices(); i++)
         if(! visited[i])
            DepthFirstSearch(i, visited);
    delete []visited;
}

void AdjMWGraph::BroadFirstSearch(const int v, int visited[])
{
    VerT u;
    int w;
    SeqQueue queue;                //定义队列
    cout<<GetValue(v)<<" ";            //访问该顶点
    visited[v] = 1;                    //置已访问标记
    queue.Append(v);                //顶点v入队列
    while(queue.NotEmpty())            //队列非空时循环
   {
        u = queue.Delete();            //出队列
        w = GetFirstNeighbor(u);         //取顶点u的第一个邻接顶点
        while(w != -1)            //邻接顶点存在时
        {
            if(!visited[w])        //若该顶点没有访问过
            {
                cout<<GetValue(w)<<" ";    //访问该顶点
                visited[w] = 1;        //置已访问标记
                queue.Append(w);    //顶点w入队列
            }
            w = GetNextNeighbor(u, w);
        }
   }
}

void AdjMWGraph::BroadFirstSearch()
//非连通图G访问操作为Visit()的广度优先遍历
{
    int *visited = new int[NumOfVertices()];
    for(int i = 0; i < NumOfVertices(); i++)
        visited[i] = 0;
    for(int i = 0; i < NumOfVertices(); i++)
        if(!visited[i])
              BroadFirstSearch(i, visited);
    delete []visited;
}
void AdjMWGraph::Show()
{
    for(int i=0;i<Vertices.Size();i++)
    {
        for(int j=0;j<Vertices.Size();j++)
        {
            int a=GetWeight(i,j);
            if(a==MaxWeight)
                cout<<"∞ ";
            else
                cout<<a<<" ";
        }
        cout<<endl;
    }
}

 

CreatAdjMWGraph.h

struct RowColWeight           //网的结构体
{    int row;                //行下标
    int col;                    //列下标
    int weight;                //权值
};
struct RowCol             //图的结构体
{
    int row;                //行下标
    int col;                    //列下标
};

void CreatWayWeb(AdjMWGraph &G,  DataType V[],int n,RowColWeight E[],  int e)
//在图G中插入n个顶点V 和  e条边E
{
    //在图G中插入n个顶点
    for(int i = 0; i < n; i++)
        G.InsertVertex(V[i]);
    //在图G中插入e条边
    for(int k = 0; k < e; k++)
        G.InsertWayEdge(E[k].row, E[k].col, E[k].weight);
}
void CreatNoWayWeb(AdjMWGraph &G,  DataType V[],int n,RowColWeight E[],  int e)
{
        //在图G中插入n个顶点
    for(int i = 0; i < n; i++)
        G.InsertVertex(V[i]);
        //在图G中插入e条边
    for(int k = 0; k < e; k++)
    {
        if(E[k].row>E[k].col)
            {
                cout<<"无向网参数输入错误";
                exit(0);
            }
        G.InsertNoWayEdge(E[k].row, E[k].col, E[k].weight);
        G.InsertNoWayEdge(E[k].col, E[k].row, E[k].weight);
    }
}
void CreatWayGraph(AdjMWGraph &G,  DataType V[],int n,RowCol E[],  int e)
//在图G中插入n个顶点V 和  e条边E
{
    //在图G中插入n个顶点
    for(int i = 0; i < n; i++)
        G.InsertVertex(V[i]);
    //在图G中插入e条边
    for(int k = 0; k < e; k++)
        G.InsertWayEdge(E[k].row, E[k].col,1);
}
void CreatNoWayGraph(AdjMWGraph &G,  DataType V[],int n,RowCol E[],  int e)
{
        //在图G中插入n个顶点
    for(int i = 0; i < n; i++)
        G.InsertVertex(V[i]);
        //在图G中插入e条边
    for(int k = 0; k < e; k++)
    {
        if(E[k].row>E[k].col)
            {
                cout<<"无向图参数输入错误";
                exit(0);
            }
        G.InsertNoWayEdge(E[k].row, E[k].col, 1);
        G.InsertNoWayEdge(E[k].col, E[k].row, 1);
    }
}

 

SeqList.h

class SeqList
{
protected:
    DataType *list;                            //数组
    int maxSize;                            //最大元素个数
    int size;                                //当前元素个数
public:
    SeqList(int max=0);                          //构造函数
    ~SeqList(void);                              //析构函数

    int Size(void) const;                    //取当前数据元素个数
    void Insert(const DataType& item, int i);//插入
    DataType Delete(const int i);            //删除
    DataType GetData(int i) const;            //取数据元素
};

SeqList::SeqList(int max)                    //构造函数
{
    maxSize = max;
    size = 0;
    list = new DataType[maxSize];
}

SeqList::~SeqList(void)                        //析构函数
{
    delete []list;
}

int SeqList::Size(void) const            //取当前数据元素个数
{
    return size;
}

void SeqList::Insert(const DataType& item, int i)    //插入
//在指定位置i前插入一个数据元素item
{
    if (size == maxSize)
    {
         cout << "顺序表已满无法插入!" << endl;
        exit(0);
    }
    if(i < 0 || i > size)                    //参数正确与否判断
    {
        cout << "参数i越界出错!" << endl;
        exit(0);
    }

    //从size-1至i逐个元素后移
    for(int j = size; j > i; j--) list[j] = list[j-1];

    list[i] = item;                        //在i位置插入item
    size++;                                //当前元素个数加1
}

DataType SeqList::Delete(const int i)                //删除
//删除指定位置i的数据元素,删除的元素由函数返回
{
    if (size == 0)
    {
        cout << "顺序表已空无元素可删!" << endl;
        exit(0);
    }
    if(i < 0 || i > size - 1)            //参数正确与否判断
    {
        cout<<"参数i越界出错!"<<endl;
        exit(0);
    }

    DataType x = list[i];                //取到要删除的元素

    //从i+1至size-1逐个元素前移
    for(int j = i;j < size-1; j++) list[j] = list[j+1];

    size--;                                //当前元素个数减1
    return x;                            //返回删除的元素
}

DataType SeqList::GetData(int i) const    //取数据元素
//取位置i的数据元素,取到的数据元素由函数返回
{
    if(i < 0 || i > size - 1)            //参数正确与否判断
    {
        cout << "参数i越界出错!" << endl;
        exit(0);
    }

    return list[i];                        //返回取到的元素
}

 

SeqQueue.h

class SeqQueue{
private:
    DataType data[20];                    //顺序队列数组
    int front;                         //队头指示器
    int rear;                          //队尾指示器
    int count;                         //元素个数计数器
    int maxsize;
public:
    SeqQueue();                     //构造函数
    ~SeqQueue(void){};                 //析构函数
    void Append(const DataType& item); //入队列
    int NotEmpty(void)const            //非空否
        {return count!=0;}
    DataType Delete(void);             //出队列
};
SeqQueue::SeqQueue()
{
    front=rear=0;
    count=0;
};
void SeqQueue::Append(const DataType& item)  //入队列
//把数据元素item插入队列作为当前的新队尾
{
    if(count>0&&front==rear)
    {
        cout<<"队列已满!"<<endl;
        exit(0);
    }
    data[rear]=item;                //把元素item加在队尾
    rear=(rear+1) % maxsize;      //队尾指示器加1
    count++;                            //计数器加1
}
DataType SeqQueue::Delete(void)        //出队列
//把队头元素出队列,出队列元素由函数返回
{
    if(count==0)
    {
        cout<<"队列已空!"<<endl;
        exit(0);
    }
    DataType temp=data[front];         //保存原队头元素
    front=(front+1) % maxsize;    //队头指示器加1
    count--;                           //计数器减1
    return temp;                       //返回原队头元素
}

 

main.cpp

#include <iostream>
#include <stdlib.h>
using namespace std;
typedef char VerT;            //定义邻接矩阵图类中的VerT
typedef char DataType;        //定义顺序表类中的DataType
const int MaxVertices = 100;        //定义最大顶点个数
const int MaxWeight = 10000;        //定义权值的无穷大
#include "AdjMWGraph.h"//包含邻接矩阵的图类
#include "CreatAdjMWGraph.h"//包含邻接矩阵图的创建函数

int main()
{
    AdjMWGraph g,f;
    char a[] = {'A','B','C','D','E'};
    char b[] = {'A','B','C','D','E','F'};

    RowColWeight r1[] ={{0,1,10},{0,4,20},{1,3,30},{2,1,40},{3,2,50}};
    RowColWeight r2[] ={{0,1,10},{0,4,20},{1,3,30},{1,2,40},{2,3,50},{4,5,15}};
    int n1,n2,e1,e2;
    n1=sizeof(a)/sizeof(a[0]);
    n2=sizeof(b)/sizeof(b[0]);
    e1=sizeof(r1)/sizeof(r1[0]);
    e2=sizeof(r2)/sizeof(r2[0]);
    CreatWayWeb(g, a, n1, r1, e1);        //创建有向网
    CreatNoWayWeb(f, b, n2, r2, e2);        //创建无向网

    cout<<"有向网:"<<endl;
    g.Show();
    cout << "\n顶点个数为:" << g.NumOfVertices();
    cout << "\n边的条数为:" << g.NumOfEdges();
    cout << "\n深度优先搜索序列为:";
    g.DepthFirstSearch();
    cout << "\n广度优先搜索序列为:";
    g.BroadFirstSearch();


    cout<<"\n\n无向网"<<endl;
    f.Show();
    cout << "\n顶点个数为:" << f.NumOfVertices();
    cout << "\n边的条数为:" << f.NumOfEdges();
    cout << "\n深度优先搜索序列为:";
    f.DepthFirstSearch();
    cout << "\n广度优先搜索序列为:";
    f.BroadFirstSearch();
    return 0;
}

 

最终结果

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!