• c++实验10 图的应用实验


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

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

    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 << "
    深度优先搜索序列为:";
        g.DepthFirstSearch();
        cout<<"
    
    无向网"<<endl;
        cout << "
    深度优先搜索序列为:";
        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 << "
    广度优先搜索序列为:";
        g.BroadFirstSearch();
        cout<<"
    
    无向网"<<endl;
        cout << "
    广度优先搜索序列为:";
        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 << "
    顶点个数为:" << g.NumOfVertices();
        cout << "
    边的条数为:" << g.NumOfEdges();
    
        cout << "
    广度优先搜索序列为:";
        g.BroadFirstSearch();
        cout << "
    深度优先搜索序列为:";
        g.DepthFirstSearch();
    
        cout<<"
    
    无向网"<<endl;
        f.Show();
        cout << "
    顶点个数为:" << f.NumOfVertices();
        cout << "
    边的条数为:" << f.NumOfEdges();
        cout << "
    深度优先搜索序列为:";
        f.DepthFirstSearch();
        cout << "
    广度优先搜索序列为:";
        f.BroadFirstSearch();
           return 0;
    }

    最终结果

  • 相关阅读:
    java常量池概念【转】
    IntelliJ IDEA 2016 汉化说明:
    intellij idea 添加动态 user library(java.lang.VerifyError)【转】
    IntelliJ IDEA 12 创建Web项目 教程 超详细版【转】
    IntelliJ IDEA 12详细开发教程(一)思想的转变与新手入门【转】
    接口请求时,charles修改请求参数
    monkey测试工具
    操作DOM
    操作表单
    jQuery扩展
  • 原文地址:https://www.cnblogs.com/cc123nice/p/10899334.html
Copyright © 2020-2023  润新知