首页 > 技术文章 > c++实验10 图的应用实验

cc123nice 2019-05-21 13:48 原文

大体与上次实验相同,特点为图是邻接表存储结构

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

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

 所加载的库函数或常量定义及类的定义:

#include "SeqQueue.h"
const int MaxVertices = 100;
const int MaxWeight=10000;

 

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

struct EdgeType
{
    int dest;
    DistT weight;
    EdgeType *next;

    EdgeType(){};
    EdgeType(int d, DistT w): dest(d), weight(w), next(NULL){}
};
struct ItemType
{
    VerT data;
    EdgeType *adj;
};

class AdjTWGraph
{
private:
    ItemType Vertices[MaxVertices];
    int numVertices;
    double numOfEdges;

    void DepthFirstSearch(const int v, int visited[]);
    void BroadFirstSearch(const int v, int visited[]);
public:
    AdjTWGraph(void);
    ~AdjTWGraph(void);

    int NumOfVertices(void)
        {return numVertices;}
    double NumOfEdges(void)
        {return numOfEdges;}
    VerT GetValue(const int i);
    int GetWeight(const int v1, const int v2);
    void Show();                         //输出邻接矩阵结果
    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();
};

 

(2)创建邻接表算法

创建无向网邻接表算法:

void CreatNoWayWeb(AdjTWGraph &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 CreatWayWeb(AdjTWGraph &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)输出邻接表结果算法

void AdjTWGraph::Show()
{
    for(int i=0;i<numVertices;i++)
    {
        for(int j=0;j<numVertices;j++)
        {
            int a=GetWeight(i,j);
            if(a==MaxWeight)
                cout<<"";
            else
                cout<<a<<" ";
        }
        cout<<endl;
    }
}

 

测试结果粘贴如下:

 

 

2、图的遍历递归算法

(1)(存储结构为邻接表)深度优先遍历算法-递归算法

void AdjTWGraph::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 AdjTWGraph::DepthFirstSearch(const int v, int visited[])
{
    cout<<GetValue(v)<<" ";
    visited[v] = 1;

    int w = GetFirstNeighbor(v);
    while(w != -1)
    {
        if(! visited[w])
            DepthFirstSearch(w, visited);
        w = GetNextNeighbor(v, w);
    }
}

 

测试结果粘贴如下:

int main()
{
    AdjTWGraph 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},{2,4,25}};
    RowColWeight r2[] ={{0,1,10},{0,4,20},{1,3,30},{1,2,40},{2,3,50},{4,5,15},{3,4,12}};
    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;
    cout << "\n深度优先搜索序列为:";
    g.DepthFirstSearch();
    cout<<"\n\n无向网"<<endl;
    cout << "\n深度优先搜索序列为:";
    f.DepthFirstSearch();
       return 0;
}

 

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

 

(2)广度优先遍历算法(递归算法)

void AdjTWGraph::BroadFirstSearch()
{
    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 AdjTWGraph::BroadFirstSearch(const int v, int visited[])
{
    VerT u, w;
    SeqQueue queue;
    cout<<GetValue(v)<<" ";
    visited[v] = 1;
    queue.Append(v);
    while(queue.NotEmpty())
    {
        u = queue.Delete();
        w = GetFirstNeighbor(u);
        while(w != -1)
        {
            if(!visited[w])
            {
                cout<<GetValue(w)<<" ";;
                visited[w] = 1;
                queue.Append(w);
            }
            w = GetNextNeighbor(u, w);
        }
    }
}

 

测试结果粘贴如下:

int main()
{
    AdjTWGraph 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},{2,4,25}};
    RowColWeight r2[] ={{0,1,10},{0,4,20},{1,3,30},{1,2,40},{2,3,50},{4,5,15},{3,4,12}};
    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;
    cout << "\n广度优先搜索序列为:";
    g.BroadFirstSearch();
    cout<<"\n\n无向网"<<endl;
    cout << "\n广度优先搜索序列为:";
    f.BroadFirstSearch();
       return 0;
}

 

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

 

 

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

 

AdjTWGraph.h

#include "SeqQueue.h"
const int MaxVertices = 100;
const int MaxWeight=10000;
struct EdgeType
{
    int dest;
    DistT weight;
    EdgeType *next;

    EdgeType(){};
    EdgeType(int d, DistT w): dest(d), weight(w), next(NULL){}
};
struct ItemType
{
    VerT data;
    EdgeType *adj;
};

class AdjTWGraph
{
private:
    ItemType Vertices[MaxVertices];
    int numVertices;
    double numOfEdges;

    void DepthFirstSearch(const int v, int visited[]);
    void BroadFirstSearch(const int v, int visited[]);
public:
    AdjTWGraph(void);
    ~AdjTWGraph(void);

    int NumOfVertices(void)
        {return numVertices;}
    double NumOfEdges(void)
        {return numOfEdges;}
    VerT GetValue(const int i);
    int GetWeight(const int v1, const int v2);
    void Show();                         //输出邻接矩阵结果
    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();
};

AdjTWGraph::AdjTWGraph(void)
{
    for(int i = 0; i < MaxVertices; i++) Vertices[i].adj = NULL;
    numVertices = 0;
    numOfEdges = 0;
}

AdjTWGraph::~AdjTWGraph(void)
{
    for(int i = 0; i < numVertices; i++)
    {
        EdgeType *p = Vertices[i].adj, *q;
        while(p != NULL)
        {
            q = p->next;
            delete p;
            p = q;
        }
    }
}

VerT AdjTWGraph::GetValue(const int i)
{
    if(i < 0 || i > numVertices)
    {
        cout << "参数i越界出错!" << endl;
        exit(0);
    }
    return Vertices[i].data;
}

int AdjTWGraph::GetWeight(const int v1, const int v2)
{

    if(v1 < 0 || v1 > numVertices || v2 < 0 || v2 > numVertices)
    {
        cout << "参数v1或v2越界出错!" << endl;
        exit(0);
    }
    EdgeType *p = Vertices[v1].adj;
    while(p != NULL && p->dest < v2)
        p = p->next;
    if(p==NULL||v2 != p->dest)
    {
        return MaxWeight;
    }
    return p->weight;
}

void AdjTWGraph::InsertVertex(const VerT &vertex)
{
    Vertices[numVertices].data = vertex;
    numVertices++;
}

void AdjTWGraph::InsertWayEdge(const int v1, const int v2, int weight)
{
    if(v1 < 0 || v1 > numVertices || v2 < 0 || v2 > numVertices)
    {
        cout << "参数v1或v2越界出错!" << endl;
        exit(0);
    }

    EdgeType *q = new EdgeType(v2, weight);
    if(Vertices[v1].adj == NULL)
        Vertices[v1].adj = q;
    else
    {
        EdgeType *curr = Vertices[v1].adj, *pre = NULL;
        while(curr != NULL && curr->dest < v2)
        {
            pre = curr;
            curr = curr->next;
        }
        if(pre == NULL)
        {
            q->next = Vertices[v1].adj;
            Vertices[v1].adj = q;
        }
        else
        {
            q->next = pre->next;
            pre->next = q;
        }
    }
    numOfEdges++;
}
void AdjTWGraph::InsertNoWayEdge(const int v1, const int v2, int weight)
//插入一条起始顶点为v1、终止顶点为 v2、权值为weight的边
{
        if(v1 < 0 || v1 > numVertices || v2 < 0 || v2 > numVertices)
    {
        cout << "参数v1或v2越界出错!" << endl;
        exit(0);
    }

    EdgeType *q = new EdgeType(v2, weight);
    if(Vertices[v1].adj == NULL)
        Vertices[v1].adj = q;
    else
    {
        EdgeType *curr = Vertices[v1].adj, *pre = NULL;
        while(curr != NULL && curr->dest < v2)
        {
            pre = curr;
            curr = curr->next;
        }
        if(pre == NULL)
        {
            q->next = Vertices[v1].adj;
            Vertices[v1].adj = q;
        }
        else
        {
            q->next = pre->next;
            pre->next = q;
        }
    }
    numOfEdges+=0.5;                            //边的个数加0.5
}
void AdjTWGraph::DeleteVertex(const int v)
{
    EdgeType *pre, *curr;
    for(int i = 0; i < numVertices; i++)
    {
        pre = NULL;
        curr = Vertices[i].adj;
        while(curr != NULL && curr->dest < v)
        {
            pre = curr;
            curr = curr->next;
        }

        if(pre == NULL && curr->dest == v)
        {
            Vertices[i].adj = curr->next;
            delete curr;
            numOfEdges--;
        }
        else if(curr != NULL && curr->dest == v)
        {
            pre->next = curr->next;
            delete curr;
            numOfEdges--;
        }
    }

    EdgeType *p = Vertices[v].adj, *q;
    for(int i = v; i < numVertices-1; i++)
        Vertices[i] = Vertices[i+1];
    numVertices--;

    while(p != NULL)
    {
        q = p->next;
        delete p;
        p = q;
        numOfEdges--;
    }
}

void AdjTWGraph::DeleteEdge(const int v1, const int v2)
{
    if(v1 < 0 || v1 > numVertices || v2 < 0 || v2 > numVertices)
    {
        cout << "参数v1或v2越界出错!" << endl;
        exit(0);
    }
    EdgeType *curr = Vertices[v1].adj, *pre = NULL;
    while(curr != NULL && curr->dest < v2)
    {
        pre = curr;
        curr = curr->next;
    }
    if(pre == NULL && curr->dest == v2)
    {
        Vertices[v1].adj = curr->next;
        delete curr;
        numOfEdges--;
    }
    else if(pre != NULL && curr->dest == v2)
    {
        pre->next = curr->next;
        delete curr;
        numOfEdges--;
    }
    else
    {
        cout << "边<v1, v2>不存在!" << endl;
        exit(0);
    }
}

int AdjTWGraph::GetFirstNeighbor(const int v)
{
    if(v < 0 || v > numVertices)
    {
        cout << "参数v1越界出错!" << endl;
        exit(0);
    }
    EdgeType *p = Vertices[v].adj;
    if(p != NULL) return p->dest;
    else return -1;
}

int AdjTWGraph::GetNextNeighbor(const int v1, const int v2)
{
    if(v1 < 0 || v1 > numVertices || v2 < 0 || v2 > numVertices)
    {
        cout << "参数v1或v2越界出错!" << endl;
        exit(0);
    }
    EdgeType *p = Vertices[v1].adj;
    while(p != NULL)
    {
        if(p->next != NULL && p->dest == v2) return p->next->dest;
        else p = p->next;
    }
    return -1;
}

void AdjTWGraph::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 AdjTWGraph::DepthFirstSearch(const int v, int visited[])
{
    cout<<GetValue(v)<<" ";
    visited[v] = 1;

    int w = GetFirstNeighbor(v);
    while(w != -1)
    {
        if(! visited[w])
            DepthFirstSearch(w, visited);
        w = GetNextNeighbor(v, w);
    }
}

void AdjTWGraph::BroadFirstSearch()
{
    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 AdjTWGraph::BroadFirstSearch(const int v, int visited[])
{
    VerT u, w;
    SeqQueue queue;
    cout<<GetValue(v)<<" ";
    visited[v] = 1;
    queue.Append(v);
    while(queue.NotEmpty())
    {
        u = queue.Delete();
        w = GetFirstNeighbor(u);
        while(w != -1)
        {
            if(!visited[w])
            {
                cout<<GetValue(w)<<" ";;
                visited[w] = 1;
                queue.Append(w);
            }
            w = GetNextNeighbor(u, w);
        }
    }
}
void AdjTWGraph::Show()
{
    for(int i=0;i<numVertices;i++)
    {
        for(int j=0;j<numVertices;j++)
        {
            int a=GetWeight(i,j);
            if(a==MaxWeight)
                cout<<"";
            else
                cout<<a<<" ";
        }
        cout<<endl;
    }
}

 

CreatAdjTWGraph.h

struct RowColWeight
{
    int row;                            //行下标
    int col;                            //列下标
    int weight;                            //权值
};

void CreatWayWeb(AdjTWGraph &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(AdjTWGraph &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);
    }
}

 

SeqQueue.h

#include<iostream>
using namespace std;
class SeqQueue
{
private:
    DataType data[MaxQueueSize];        //顺序队列数组
    int front;                            //队头指示器
    int rear;                            //队尾指示器
    int count;                            //元素个数计数器
public:
    SeqQueue(void)                          //构造函数
        {front = rear = 0; count = 0;};
    ~SeqQueue(void){};                  //析构函数

    void Append(const DataType& item);    //入队列
    DataType Delete(void);               //出队列
    DataType GetFront(void)const;         //取队头数据元素
    int NotEmpty(void)const              //非空否
        {return 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) % MaxQueueSize;        ///队尾指示器加1
   count++;                                    //计数器加1
}

DataType SeqQueue::Delete(void)                    //出队列
//把队头元素出队列,出队列元素由函数返回
{
   if(count == 0)
   {
      cout << "队列已空!" << endl;
      exit(0);
   }

   DataType temp = data[front];                //保存原队头元素
   front = (front + 1) % MaxQueueSize;        //队头指示器加1
   count--;                                    //计数器减1
   return temp;                                //返回原队头元素
}

DataType SeqQueue::GetFront(void)const        //取队头数据元素
//取队头元素并由函数返回
{
   if(count == 0)
   {
      cout << "队列空!" << endl;
      exit(0);
   }
   return data[front];                        //返回队头元素
}

 

GraphTest.cpp

 

#include <iostream>
#include <stdlib.h>
const int MaxQueueSize = 100;

typedef char VerT;
typedef int DistT;
typedef char DataType;

#include "AdjTWGraph.h"
#include "CreatAdjTWGraph.h"

int main()
{
    AdjTWGraph 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},{2,4,25}};
    RowColWeight r2[] ={{0,1,10},{0,4,20},{1,3,30},{1,2,40},{2,3,50},{4,5,15},{3,4,12}};
    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.BroadFirstSearch();
    cout << "\n深度优先搜索序列为:";
    g.DepthFirstSearch();

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

 

最终结果

 

推荐阅读