数据结构——图的存储及转换

大一萌新,大佬轻喷^ _ ^ 有什么建议可以提出来一起学习OAO

图的邻接矩阵存储

先看无向图和有向图的邻接矩阵
图示例无向图
有向图有向图的邻接矩阵
可以看到无向图的邻接矩阵一定是对称的,而有向图不一定,在不考虑环的情况下主对角线全为0

先康康我们需要定义什么
1.一个存储结点的数组
2.一个MAX * MAX的矩阵
3.还要知道结点数和边数以便进行操作

再康康我们需要做什么
1.在结点数组中存入结点
2.让用户输入边的信息,根据信息对矩阵特定元素进行变 1
3.还要区分有向图与无向图(无向图的邻接矩阵一定是对称的)
4.格式化输出

#include <iostream>

using namespace std;

typedef char datatype;

const int Max_number=10;

class Mgraph
{
public:
    datatype node[Max_number];
    int Martix[Max_number][Max_number];
    int num_of_node,num_of_edge;
public:
    Mgraph();
    int CreatMgraph();
    void Travell();
};
Mgraph::Mgraph()
{
    num_of_node=0;
    num_of_edge=0;
}
int Mgraph::CreatMgraph()
{
    char judge;
    cout<<"有向图(Y),无向图(N),请输入Y/N"<<endl;
    cin>>judge;
    for(int i=0;i<num_of_node;i++)
    {
        for(int j=0;j<num_of_node;j++)
            Martix[i][j]=0;
    }
    for(int i=0;i<num_of_node;i++)
    {
        cout<<"输入第 "<<i+1<<" 结点的值"<<endl;
        cin>>node[i];
    }
    int row,clo;
    cout<<"输入每条边对应的两个顶点序号"<<endl;
    for(int i=0;i<num_of_edge;i++)
    {
        cout<<"V<i,j> : ";
        cin>>row>>clo;
        if(row<=0||clo<=0||row>num_of_node||clo>num_of_node)
        {
            cout<<"value is illegal!"<<endl;
            return -1;
        }
        Martix[row-1][clo-1]=1;
        if(judge=='N'||judge=='n')
            Martix[clo-1][row-1]=1;
    }
    return 1;
}

void Mgraph::Travell()
{
    cout<<"  ";
    for(int i=0;i<num_of_node;i++)
        cout<<node[i]<<" ";
        cout<<endl;
    for(int i=0;i<num_of_node;i++)
    {
        cout<<node[i]<<" ";
        for(int j=0;j<num_of_node;j++)
        {
            cout<<Martix[i][j]<<" ";
        }
        cout<<endl;
    }
}

int main()
{
    Mgraph mygraph;
    cout<<"请输入图的结点个数"<<endl;
    cin>>mygraph.num_of_node;
    if(mygraph.num_of_node>Max_number)
    {
        cout<<"你的输入超出大小限制"<<endl;
        return -1;
    }
    cout<<"请输入图的边个数"<<endl;
    cin>>mygraph.num_of_edge;
    if(mygraph.num_of_edge>mygraph.num_of_node*mygraph.num_of_node)
    {
        cout<<"你的输入超出大小限制"<<endl;
        return -1;
    }
    int j=mygraph.CreatMgraph();
    if(j!=-1)
    mygraph.Travell();
}

运行结果
运行结果

图的邻接表存储

分别看上方无向图与有向图的邻接表
邻接表是一种链式存储方式,对每个头结点建立一个单链表,表中结点为表结点。
表结点要包括:1.代表的结点的值。 2.指向下一个表结点的指针。 3.边的权值。
头结点要包括:1.头结点的值。2.一个指向表结点的指针。
无向图邻接表
有向图邻接表
先康康我们需要定义什么

  1. 表结点的结构体
  2. 头结点的结构体
  3. 创建一个邻接表的类,数据域包括:一个头结点数组,结点数,边数。

再康康我们要做什么

  1. 将结点的值存入头结点数组
  2. 让用户输入边的信息,创建一个表结点(区分有向图与无向图的不同)
  3. 将表结点与对应的头结点连接起来
  4. 格式化输出
#include <iostream>

using namespace std;

const int Max_of_nodes=10;

typedef char datatype;

typedef int weighttype;

class Listnode
{
public:
    int node;
    Listnode* next;
    weighttype weight;
public:
    Listnode()
    {
        node=0;
        next=NULL;
        weight=1;
    }
};

class Headnode
{
public:
    datatype data;
    Listnode* firnode;
public:
    Headnode()
    {
       firnode=NULL;
    }
};

class Map
{
public:
    Headnode mylist[Max_of_nodes];
    int num_of_node;
    int num_of_edge;
public:
    Map();
    int CreatMap();
    void ShowMap();
};

Map::Map()
{
    num_of_node=0;
    num_of_edge=0;
}
int Map::CreatMap()
{
    char judge;
    cout<<"有向图(Y),无向图(N),请输入Y/N"<<endl;
    cin>>judge;
    for(int i=0;i<num_of_node;i++)
    {
        cout<<"请输入第 "<<i+1<<" 个结点的值"<<endl;
        cin>>mylist[i].data;
    }
    cout<<"请输入边的信息,例 :1,2代表由第一个结点到第二个结点的边"<<endl;
    int beginn=1;
    int over=1;
    for(int i=0;i<num_of_edge;i++)
    {
        cout<<"V<i,j> : ";
        cin>>beginn>>over;
        if(beginn<1||over<1||beginn>num_of_node||over>num_of_node)
    {
        cout<<"输入的边信息不合法"<<endl;
        return -1;
    }
        Listnode* p;
        p=new Listnode;
        p->node=over;
        p->next=mylist[beginn-1].firnode;
        mylist[beginn-1].firnode=p;
        if(beginn!=over&&(judge=='N'||judge=='n'))
        {Listnode* q;
        q=new Listnode;
        q->node=beginn;
        q->next=mylist[over-1].firnode;
        mylist[over-1].firnode=q;}
    }
    return 1;
}

void Map::ShowMap()
{
    for(int i=0;i<num_of_node;i++)
    {
        cout<<mylist[i].data;
        while(mylist[i].firnode!=NULL)
        {
            cout<<" "<<mylist[i].firnode->node;
            mylist[i].firnode=mylist[i].firnode->next;
        }
        cout<<endl;
    }
}
int main()
{
    Map mymap;
    cout<<"请输入图中结点个数与边个数"<<endl;
    cin>>mymap.num_of_node>>mymap.num_of_edge;
    if(mymap.num_of_node>Max_of_nodes||mymap.num_of_node<1)
    {
        cout<<"输入信息超出范围"<<endl;
        return -1;
    }
    if(mymap.num_of_edge>Max_of_nodes*Max_of_nodes||mymap.num_of_edge<1)
    {
        cout<<"输入信息超出范围"<<endl;
        return -1;
    }
    {
        cout<<"输入信息超过设定最大值"<<endl;
        return -1;
    }
    if(mymap.CreatMap()!=-1)
    mymap.ShowMap();
}


运行结果
运行结果

网络的邻接矩阵存储

网络就是带权重的图,因此,我们只需要将原来矩阵中的值变成权重就好。
不连通的两点距离用 # 表示

#include <iostream>
#include <stdio.h>
using namespace std;

typedef char datatype;

const int Max_number=10;

class Mgraph
{
public:
    datatype node[Max_number];
    int Martix[Max_number][Max_number];
    int num_of_node,num_of_edge;
public:
    Mgraph();
    int CreatMgraph();
    void Travell();
};
Mgraph::Mgraph()
{
    num_of_node=0;
    num_of_edge=0;
}
int Mgraph::CreatMgraph()
{
    for(int i=0;i<num_of_node;i++)
    {
        for(int j=0;j<num_of_node;j++)
            Martix[i][j]=-1;
    }
    for(int i=0;i<num_of_node;i++)
    {
        cout<<"输入第 "<<i+1<<" 结点的值"<<endl;
        cin>>node[i];
    }
    char head,tail;
    int row,clo,weight;
    cout<<"输入每条边对应的两个顶点,权重"<<endl;
    for(int i=0;i<num_of_edge;i++)
    {
        cout<<"V<i,j> weight: ";
        cin>>head>>tail>>weight;
        for(int i=0;i<num_of_node;i++)
        {
            if(node[i]==head)
                {
                    row=i;
                    break;
                }
            else if(i==num_of_node-1)
            {
                cout<<"输入的值不合法"<<endl;
                return -1;
            }
        }
        for(int i=0;i<num_of_node;i++)
        {
            if(node[i]==tail)
                clo=i;
        }
        Martix[row][clo]=weight;
    }
    return 1;
}

void Mgraph::Travell()
{
    cout<<"  ";
    for(int i=0;i<num_of_node;i++)
        cout<<node[i]<<" ";
        cout<<endl;
    for(int i=0;i<num_of_node;i++)
    {
        cout<<node[i]<<" ";
        for(int j=0;j<num_of_node;j++)
        {
            if(Martix[i][j]==-1)
                cout<<'#'<<" ";
            else
            cout<<Martix[i][j]<<" ";
        }
        cout<<endl;
    }
}

int main()
{
    Mgraph mygraph;
    cout<<"请输入图的结点个数"<<endl;
    cin>>mygraph.num_of_node;
    if(mygraph.num_of_node>Max_number)
    {
        cout<<"你的输入超出大小限制"<<endl;
        return -1;
    }
    cout<<"请输入图的边个数"<<endl;
    cin>>mygraph.num_of_edge;
    if(mygraph.num_of_edge>mygraph.num_of_node*mygraph.num_of_node)
    {
        cout<<"你的输入超出大小限制"<<endl;
        return -1;
    }
    int j=mygraph.CreatMgraph();
    if(j!=-1)
    {
        cout<<endl;
        cout<<"邻接矩阵如下,#代表无穷"<<endl;
        mygraph.Travell();
    }
    cout<<"按任意键结束程序"<<endl;
    getchar();
    getchar();
}

运行结果:
![![在这里插入图片描述](https://img-blog.csdnimg.cn/20200509135233892.png](https://img-blog.csdnimg.cn/20200509135431951.png

网络的邻接矩阵存储

我们需要在上面的邻接矩阵中边结点的数据结构中加上 weight 这个变量,以便我们存储权重

#include <iostream>
#include <stdio.h>
using namespace std;

const int Max_of_nodes=10;

typedef char datatype;

typedef int weighttype;

class Listnode
{
public:
    datatype node;
    Listnode* next;
    weighttype weight;
public:
    Listnode()
    {
        node=0;
        next=NULL;
        weight=1;
    }
};

class Headnode
{
public:
    datatype data;
    Listnode* firnode;
public:
    Headnode()
    {
       firnode=NULL;
    }
};

class Map
{
public:
    Headnode mylist[Max_of_nodes];
    int num_of_node;
    int num_of_edge;
public:
    Map();
    int CreatMap();
    void ShowMap();
};

Map::Map()
{
    num_of_node=0;
    num_of_edge=0;
}
int Map::CreatMap()
{
    for(int i=0;i<num_of_node;i++)
    {
        cout<<"请输入第 "<<i+1<<" 个结点的值"<<endl;
        cin>>mylist[i].data;
    }
    cout<<"输入每条边对应的两个顶点,权重"<<endl;
    char head,tail;
    int beginn;
    weighttype weight;
    for(int i=0;i<num_of_edge;i++)
    {
        cout<<"V<i,j> weight: ";
        cin>>head>>tail>>weight;
         for(int i=0;i<num_of_node;i++)
        {
            if(mylist[i].data==head)
               {
                 beginn=i;
                 break;
               }
            else if(i==num_of_node-1)
            {
                cout<<"输入的值不合法"<<endl;
                return -1;
            }
        }
        Listnode* p;
        p=new Listnode;
        p->node=tail;
        p->weight=weight;
        p->next=mylist[beginn].firnode;
        mylist[beginn].firnode=p;
    }
    return 1;
}

void Map::ShowMap()
{
    for(int i=0;i<num_of_node;i++)
    {
        cout<<mylist[i].data;
        while(mylist[i].firnode!=NULL)
        {
            cout<<" "<<mylist[i].firnode->node;
            mylist[i].firnode=mylist[i].firnode->next;
        }
        cout<<endl;
    }
}
int main()
{
    Map mymap;
    cout<<"请输入图中结点个数与边个数"<<endl;
    cin>>mymap.num_of_node>>mymap.num_of_edge;
    if(mymap.num_of_node>Max_of_nodes||mymap.num_of_node<1)
    {
        cout<<"输入信息超出范围"<<endl;
        return -1;
    }
    if(mymap.num_of_edge>Max_of_nodes*Max_of_nodes||mymap.num_of_edge<1)
    {
        cout<<"输入信息超出范围"<<endl;
        return -1;
    }
    if(mymap.CreatMap()!=-1)
    {
        cout<<"邻接表如下"<<endl;
        mymap.ShowMap();
    }
    cout<<"按任意键结束程序"<<endl;
    getchar();
    getchar();
}

运行结果
在这里插入图片描述

邻接矩阵与邻接表的互相转换

邻接矩阵转换为邻接表

因为邻接矩阵中存储的内容包括了权重,但没有明确的给出结点次序
所以我们需要用户先输入结点次序,再通过邻接矩阵对应各个边的权重
才能构造出邻接表

#include <iostream>
#include <stdio.h>
using namespace std;

const int Max_of_nodes=10;

typedef char datatype;

typedef char weighttype;

class Listnode
{
public:
    datatype node;
    Listnode* next;
    weighttype weight;
public:
    Listnode()
    {
        node=0;
        next=NULL;
        weight=1;
    }
};

class Headnode
{
public:
    datatype data;
    Listnode* firnode;
public:
    Headnode()
    {
       firnode=NULL;
    }
};

class Map
{
public:
    Headnode mylist[Max_of_nodes];
    int num_of_node;
    int num_of_edge;
public:
    Map();
    int CreatMap(char mymartix[Max_of_nodes][Max_of_nodes]);
    void ShowMap();
};

Map::Map()
{
    num_of_node=0;
    num_of_edge=0;
}
int Map::CreatMap(char mymartix[Max_of_nodes][Max_of_nodes])
{
    int head,tail;
    char weightt;
    char judge;
    for(int i=0;i<num_of_node;i++)
    {
        for(int j=0;j<num_of_node;j++)
        {
            if(mymartix[i][j]!='#')
            {
                head=i;
                tail=j;
                weightt=mymartix[i][j];
                Listnode* p;
                p=new Listnode;
                p->node=mylist[tail].data;
                p->next=mylist[head].firnode;
                p->weight=weightt;
                mylist[head].firnode=p;
            }
        }
    }
}
void Map::ShowMap()
{
    for(int i=0;i<num_of_node;i++)
    {
        cout<<mylist[i].data;
        while(mylist[i].firnode!=NULL)
        {
            cout<<" "<<mylist[i].firnode->node;
            mylist[i].firnode=mylist[i].firnode->next;
        }
        cout<<endl;
    }
}

int main()
{
    Map mymap;
    cout<<"请输入结点个数,边数"<<endl;
    cin>>mymap.num_of_node>>mymap.num_of_edge;
    char mymartix[Max_of_nodes][Max_of_nodes];
    cout<<"请输入各个结点的值"<<endl;
    for(int i=0;i<mymap.num_of_node;i++)
    {
        cin>>mymap.mylist[i].data;
    }
    cout<<"请按行输入邻接矩阵,(输入#代表无穷)!"<<endl;
    for(int i=0;i<mymap.num_of_node;i++)
    {
        for(int j=0;j<mymap.num_of_node;j++)
            cin>>mymartix[i][j];
    }
    mymap.CreatMap(mymartix);
    cout<<"转换后的邻接表为"<<endl;
    mymap.ShowMap();
    cout<<"按任意键结束程序"<<endl;
    getchar();
    getchar();
}

运行结果
在这里插入图片描述

邻接表转换为邻接矩阵

由于邻接表中权重并没有显示地表现在表中
所以我们需要用户输入,创建一个邻接表就像前面那样
然后我们再对邻接表进行处理,生成我们的邻接矩阵

为了方便操作,我定义了一个矩阵元素的类,包括了一个tag位,和一个int型的权重变量
这样,在输出矩阵时就可以很方便地输出# 代表不连通

#include <iostream>
#include <stdio.h>
using namespace std;

const int Max_of_nodes=10;

typedef char datatype;

typedef int weighttype;

class Martix_node
{
public:
    int tag;
    int value;
public:
    Martix_node()
    {
        tag=0;
        value=0;
    }
};

class Listnode
{
public:
    datatype node;
    Listnode* next;
    weighttype weight;
public:
    Listnode()
    {
        node=0;
        next=NULL;
        weight=1;
    }
};

class Headnode
{
public:
    datatype data;
    Listnode* firnode;
public:
    Headnode()
    {
       firnode=NULL;
    }
};

class Map
{
public:
    Headnode mylist[Max_of_nodes];
    int num_of_node;
    int num_of_edge;
public:
    Map();
    int CreatMap();
    int CreatMartix();
    void ShowMap();
};

Map::Map()
{
    num_of_node=0;
    num_of_edge=0;
}
int Map::CreatMap()
{
    for(int i=0;i<num_of_node;i++)
    {
        cout<<"请输入第 "<<i+1<<" 个结点的值"<<endl;
        cin>>mylist[i].data;
    }
    cout<<"输入每条边对应的两个顶点,权重"<<endl;
    char head,tail;
    int beginn;
    weighttype weight;
    for(int i=0;i<num_of_edge;i++)
    {
        cout<<"V<i,j> weight: ";
        cin>>head>>tail>>weight;
         for(int i=0;i<num_of_node;i++)
        {
            if(mylist[i].data==head)
                beginn=i;
        }
        Listnode* p;
        p=new Listnode;
        p->node=tail;
        p->weight=weight;
        p->next=mylist[beginn].firnode;
        mylist[beginn].firnode=p;
    }
    return 1;
}
void Map::ShowMap()
{

    for(int i=0;i<num_of_node;i++)
    {
        Listnode* p=mylist[i].firnode;
        cout<<mylist[i].data;
        while(p!=NULL)
        {
            cout<<" "<<p->node;
            p=p->next;
        }
        cout<<endl;
    }
}

int Map::CreatMartix()
{
   Martix_node mymartix[num_of_node][num_of_node];
   for(int i=0;i<num_of_node;i++)
    {
        while(mylist[i].firnode!=NULL)
        {
           for(int j=0;j<num_of_node;j++)
           {
               if(mylist[j].data==mylist[i].firnode->node)
                {
                    mymartix[i][j].value=mylist[i].firnode->weight;
                    mymartix[i][j].tag=1;
                }
           }
            mylist[i].firnode=mylist[i].firnode->next;
        }
    }
    cout<<"  ";
    for(int i=0;i<num_of_node;i++)
        cout<<mylist[i].data<<" ";
        cout<<endl;
   for(int i=0;i<num_of_node;i++)
   {
       cout<<mylist[i].data<<" ";
       for(int j=0;j<num_of_node;j++)
        {
            if(!mymartix[i][j].tag)
                cout<<'#'<<" ";
            else
                cout<<mymartix[i][j].value<<" ";
        }
       cout<<endl;
   }
}
int main()
{
    Map mymap;
    cout<<"请输入图中结点个数与边个数"<<endl;
    cin>>mymap.num_of_node>>mymap.num_of_edge;
    if(mymap.num_of_node>Max_of_nodes||mymap.num_of_node<1)
    {
        cout<<"输入信息超出范围"<<endl;
        return -1;
    }
    if(mymap.num_of_edge>Max_of_nodes*Max_of_nodes||mymap.num_of_edge<1)
    {
        cout<<"输入信息超出范围"<<endl;
        return -1;
    }
    mymap.CreatMap();
    cout<<"邻接表为"<<endl;
    mymap.ShowMap();
    cout<<"转换后的邻接矩阵为(#代表无穷大)"<<endl;
    mymap.CreatMartix();
    cout<<"按任意键结束程序"<<endl;
    getchar();
    getchar();
}

运行结果
在这里插入图片描述

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值