zoukankan      html  css  js  c++  java
  • 数据结构——图的建立与操作

    源码:

    #include<stdio.h>
    #include<windows.h>
    #define INFINITY 65535
    #define MAX_VARTEX_NUM 10
    #define Status int
    #define OK 0
    #define ERROR 1
    #define OVERFLOW -2
    //标志数组
    bool visited[MAX_VARTEX_NUM]={false};
    //图的类型的构建
    typedef enum {DG,DN,AG,AN} GraphKind;
    typedef struct AreCell
    {
    int adj;//顶点关系
    }ArCell,AdjMatrix[MAX_VARTEX_NUM][MAX_VARTEX_NUM];
    typedef struct
    {
    char vexs[MAX_VARTEX_NUM];//顶点向量
    AdjMatrix arcs;//邻接矩阵
    int vexnum,arcnum;//图的当前顶点数和弧数
    int flag;//标志变量
    GraphKind kind;//图的标志的种类
    }MGraph;
    //队列的类型的构建
    typedef struct QNode
    {
    int data;//数据域
    struct QNode *next;//指针域
    }QNode,*QueuePtr;
    typedef struct
    {
    QueuePtr front;//队头指针
    QueuePtr rear;//队尾指针
    }LinkQueue;
    //创建队列函数
    Status InitQueue(LinkQueue &Q)//创建空的队列
    {
    Q.front=Q.rear=(struct QNode *)malloc(sizeof(struct QNode));
    if(!Q.front)
    exit(OVERFLOW);
    Q.front->next=NULL;//将队头指针的指针域置空
    return OK;
    }
    //队列插入函数
    Status EnQueue(LinkQueue &Q,int e)//插入函数
    {
    QueuePtr p;//申请一个结点
    p=(struct QNode *)malloc(sizeof(struct QNode));//动态申请一个结点
    if(!p)
    exit(OVERFLOW);//存储分配失败
    p->data=e;
    p->next=NULL;//将结点的指针域赋值为空
    Q.rear->next=p;//将结点p链接到队列尾部
    Q.rear=p;//将尾指针直线结点p
    return OK;
    }
    //判断队列是否为空
    Status QueueEmpty(LinkQueue Q)//判断队列是否为空
    {
    if(Q.front==Q.rear)
    return ERROR;
    else
    return OK;
    }
    //队列的删除函数
    Status DeQueue(LinkQueue &Q,int &e)//删除队列的头元素
    {
    QueuePtr p;//定义一个结点
    if(Q.front==Q.rear)
    return ERROR;
    p=Q.front->next;//将队列头赋值给p
    e=p->data;
    Q.front->next=p->next;//直接将队列头指针指向p的后继
    if(Q.rear==p)
    Q.rear=Q.front;//队列头尾重合,队列为空
    free(p);//释放空间p
    return OK;
    }
    //顶点的位置
    Status LocateVex(MGraph &G,char e)
    {
    int i;//循环变量
    for(i=0;i<G.vexnum;i++)
    if(G.vexs[i]==e)
    return i;
    return OK;
    }
    //寻找第一个后继元素
    Status FirstAdjVex(MGraph &G,int i)
    {
    int j=0;//标志变量
    int k;//循环变量
    if (G.kind==1||G.kind==3)//网
    j=INFINITY;
    for(k=0;k<G.vexnum;k++)
    if(G.arcs[i][k].adj!=j)
    return k;
    return -1;
    }
    //寻找后继元素
    Status NextAdjVex(MGraph &G,int i,int k)
    {
    int j=0;//标志变量
    int x;//循环变量
    if (G.kind==1||G.kind==3)//网
    j=INFINITY;
    for(x=k+1;x<G.vexnum;x++)
    if(G.arcs[i][x].adj!=j)
    return x;
    return -1;
    }
    //深度优先遍历(递归算法)
    Status DFSM(MGraph G,int i)
    {
    int j;//循环变量
    if(G.flag!=1)//判断图是否存在
    return ERROR;
    printf("%2c",G.vexs[i]);
    visited[i]=true;//将访问过的标记为1
    for(j=0;j<G.vexnum;j++)
    if(G.arcs[i][j].adj==1&&visited[j]==false)
    DFSM(G,j);//新出发点
    return OK;
    }
    //广度优先遍历
    Status BFS(MGraph &G,int i)
    {
    int u,w;//循环变量
    LinkQueue Q;//定义队列
    if(G.flag!=1)
    return ERROR;
    InitQueue(Q);//置空的辅助队列
    printf("%2c",G.vexs[i]);
    visited[i]=true;//将标志变量改变为true
    EnQueue(Q,i);//将i入队列
    while(QueueEmpty(Q)!=ERROR)
    {
    DeQueue(Q,u);//出队列并置为u
    for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))
    {
    if(visited[w]==false)
    {
    printf("%2c",G.vexs[w]);
    visited[w]=true;
    EnQueue(Q,w);//入队列
    }
    }
    }
    return OK;
    }
    //顶点向量
    Status Out_Vexs(MGraph G)
    {
    int i;//循环变量
    if(G.flag!=1)
    return ERROR;
    printf(" 顶点向量为:");
    printf("[");
    for(i=0;i<G.vexnum;i++)
    printf("%c,",G.vexs[i]);
    printf("] ");
    return OK;
    }
    //邻接矩阵
    Status Out_arcs(MGraph &G)
    {
    int i,j;//循环变量
    if(G.flag!=1)
    return ERROR;
    printf(" 该图的邻接矩阵为: ");
    printf(" ");
    for(i=0;i<G.vexnum;i++)//横排输出顶点
    printf("%c ",G.vexs[i]);
    printf(" ");
    for(i=0;i<G.vexnum;i++)//输出邻接矩阵
    {
    printf("%c ",G.vexs[i]);
    for(j=0;j<G.vexnum;j++)
    {
    if(G.arcs[i][j].adj==INFINITY)
    printf("∞");
    else
    printf("%d ",G.arcs[i][j]);
    }
    printf(" ");
    }
    return OK;
    }
    //创建有向图的函数
    Status CreateDG(MGraph &G)
    {
    int i,j,k;//循环变量
    char v1,v2;//存储输入的顶点的字符
    //采用邻接矩阵表示,构造有向图 G
    printf(" 有向图的顶点数:");
    scanf("%d",&G.vexnum);
    printf(" 有向图的边数:");
    scanf("%d",&G.arcnum);
    getchar();//吸收字符
    for(i=0;i<G.vexnum;i++)
    {
    printf(" 第%d个顶点为: ",i+1);
    scanf("%c",&G.vexs[i]);
    getchar();//吸收回车符
    }
    for(i=0;i<G.vexnum;++i)//初始化邻接矩阵
    for(j=0;j<G.vexnum;++j)
    G.arcs[i][j].adj=0;
    for(k=0;k<G.arcnum;++k)//构造邻接矩阵
    {
    printf(" 第%d条边: ",k+1);
    printf("第一个顶点:");scanf("%c",&v1);getchar();
    printf("第二个顶点:");scanf("%c",&v2);getchar();
    i=LocateVex(G,v1);
    j=LocateVex(G,v2);//确定v1和v2在G中的位置
    G.arcs[i][j].adj=1;//将有关系标记为1
    }
    G.flag=1;//标志变量赋值为1
    return OK;
    }
    //创建有向网的函数
    Status CreateDN(MGraph &G)
    {
    int i,j,k,w;//循环变量
    char v1,v2;//存储输入的顶点的字符
    //采用邻接矩阵表示,构造有向网 G
    printf(" 有向网的顶点数:");
    scanf("%d",&G.vexnum);
    printf(" 有向网的边数:");
    scanf("%d",&G.arcnum);
    getchar();//吸收字符
    for(i=0;i<G.vexnum;i++)
    {
    printf(" 第%d个顶点为: ",i+1);
    scanf("%c",&G.vexs[i]);
    getchar();//吸收回车符
    }
    for(i=0;i<G.vexnum;++i)//初始化邻接矩阵
    for(j=0;j<G.vexnum;++j)
    G.arcs[i][j].adj=INFINITY;
    for(k=0;k<G.arcnum;++k)//构造邻接矩阵
    {
    printf(" 第%d条边: ",k+1);
    printf("第一个顶点:");scanf("%c",&v1);getchar();
    printf("第二个顶点:");scanf("%c",&v2);getchar();
    printf("对应的权值:");scanf("%d",&w);getchar();
    i=LocateVex(G,v1);
    j=LocateVex(G,v2);//确定v1和v2在G中的位置
    G.arcs[i][j].adj=w;//将有关系标记为w
    }
    G.flag=1;//标志变量赋值为1
    return OK;
    }
    //创建无向图的函数
    Status CreateAG(MGraph &G)
    {
    int i,j,k;//循环变量
    char v1,v2;//存储输入的顶点的字符
    //采用邻接矩阵表示,构造无向图 G
    printf(" 无向图的顶点数:");
    scanf("%d",&G.vexnum);
    printf(" 无向图的边数:");
    scanf("%d",&G.arcnum);
    getchar();//吸收字符
    for(i=0;i<G.vexnum;i++)
    {
    printf(" 第%d个顶点为: ",i+1);
    scanf("%c",&G.vexs[i]);
    getchar();//吸收回车符
    }
    for(i=0;i<G.vexnum;++i)//初始化邻接矩阵
    for(j=0;j<G.vexnum;++j)
    G.arcs[i][j].adj=0;
    for(k=0;k<G.arcnum;++k)//构造邻接矩阵
    {
    printf(" 第%d条边: ",k+1);
    printf("第一个顶点:");scanf("%c",&v1);getchar();
    printf("第二个顶点:");scanf("%c",&v2);getchar();
    i=LocateVex(G,v1);
    j=LocateVex(G,v2);//确定v1和v2在G中的位置
    G.arcs[i][j].adj=1;//将有关系标记为1
    G.arcs[j][i].adj=G.arcs[i][j].adj;//无向图的对称顶点
    }
    G.flag=1;//标志变量赋值为1
    return OK;
    }
    //创建无向网的函数
    Status CreateAN(MGraph &G)
    {
    int i,j,k,w;//循环变量
    char v1,v2;//存储输入的顶点的字符
    //采用邻接矩阵表示,构造无向网 G
    printf(" 无向网的顶点数:");
    scanf("%d",&G.vexnum);
    printf(" 无向网的边数:");
    scanf("%d",&G.arcnum);
    getchar();//吸收字符
    for(i=0;i<G.vexnum;i++)
    {
    printf(" 第%d个顶点为: ",i+1);
    scanf("%c",&G.vexs[i]);
    getchar();//吸收回车符
    }
    for(i=0;i<G.vexnum;++i)//初始化邻接矩阵
    for(j=0;j<G.vexnum;++j)
    G.arcs[i][j].adj=INFINITY;
    for(k=0;k<G.arcnum;++k)//构造邻接矩阵
    {
    printf(" 第%d条边: ",k+1);
    printf("第一个顶点:");scanf("%c",&v1);getchar();
    printf("第二个顶点:");scanf("%c",&v2);getchar();
    printf("对应的权值:");scanf("%d",&w);getchar();
    i=LocateVex(G,v1);
    j=LocateVex(G,v2);//确定v1和v2在G中的位置
    G.arcs[i][j].adj=w;//将有关系标记为w
    G.arcs[j][i].adj=G.arcs[i][j].adj;//无向网的对称顶点
    }
    G.flag=1;//标志变量赋值为1
    return OK;
    }
    //操作有向图的函数
    Status UseDG(MGraph &G)
    {
    int j;//循环变量
    int x;//存储用户的操作选项
    int i;//存储用户输入的开始的顶点
    system("cls");//清屏函数
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    printf("☆ ☆ ");
    printf("☆ 有向图的相关操作算法 ☆ ");
    printf("☆ ☆ ");
    printf("☆ <1> 有向图的构建 <2> 有向图的深度遍历(递归) ☆ ");
    printf("☆ ☆ ");
    printf("☆ <3> 有向图的广度遍历 <4> 顶点向量 ☆ ");
    printf("☆ ☆ ");
    printf("☆ <3> 邻接矩阵 ☆ ");
    printf("☆ ☆ ");
    printf("☆ ☆ ");
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    printf(" 请输入你要进行操作的序号:");
    scanf("%d",&x);
    while(x!=88)
    {
    switch(x)
    {
    case 1:
    if(CreateDG(G)!=ERROR)
    printf(" 有向图构建成功! ");
    break;
    case 2:
    for(j=0;j<G.vexnum;j++)//标志数组的初始化
    visited[j]=false;
    printf(" 请输入你要开始深度遍历的顶点在顶点向量中的位置:");
    scanf("%d",&i);
    if(DFSM(G,i-1)==ERROR)
    printf(" 该有向图不存在,操作失败! ");
    for(j=0;j<G.vexnum;j++)
    if(visited[j]==false)
    DFSM(G,j);
    printf(" ");
    break;
    case 3:
    for(j=0;j<G.vexnum;j++)//标志数组的初始化
    visited[j]=false;
    printf(" 请输入你要开始广度遍历的顶点在顶点向量中的位置:");
    scanf("%d",&i);
    if(BFS(G,i-1)==ERROR)
    printf(" 该有向图不存在,操作失败! ");
    for(j=0;j<G.vexnum;j++)
    if(visited[j]==false)
    BFS(G,j);
    printf(" ");
    break;
    case 4:
    if(Out_Vexs(G)==ERROR)
    printf(" 该有向图不存在,操作失败! ");
    break;
    case 5:
    if(Out_arcs(G)==ERROR)
    printf(" 该有向图不存在,操作失败! ");
    break;
    default:
    printf(" 你的操作有误,请重新输入。 ");
    UseDG(G);//调用此函数
    }
    printf(" 请输入你要进行操作的序号:");
    scanf("%d",&x);
    }
    return OK;
    }
    //操作有向网的函数
    Status UseDN(MGraph &G)
    {
    int j;//循环变量
    int x;//存储用户的操作选项
    int i;//存储用户输入的开始的顶点
    system("cls");//清屏函数
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    printf("☆ ☆ ");
    printf("☆ 有向网的相关操作算法 ☆ ");
    printf("☆ ☆ ");
    printf("☆ <1> 有向网的构建 <2> 有向网的深度遍历(递归) ☆ ");
    printf("☆ ☆ ");
    printf("☆ <3> 有向网的广度遍历 <4> 顶点向量 ☆ ");
    printf("☆ ☆ ");
    printf("☆ <3> 邻接矩阵 ☆ ");
    printf("☆ ☆ ");
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    printf(" 请输入你要进行操作的序号:");
    scanf("%d",&x);
    while(x!=88)
    {
    switch(x)
    {
    case 1:
    if(CreateDN(G)!=ERROR)
    printf(" 有向网构建成功! ");
    break;
    case 2:
    printf(" 请输入你要开始深度遍历的顶点在顶点向量中的位置:");
    scanf("%d",&i);
    if(DFSM(G,i-1)==ERROR)
    printf(" 该有向图不存在,操作失败! ");
    for(j=0;j<G.vexnum;j++)
    if(visited[j]==false)
    DFSM(G,j);
    printf(" ");
    break;
    case 3:
    for(j=0;j<G.vexnum;j++)//标志数组的初始化
    visited[j]=false;
    printf(" 请输入你要开始广度遍历的顶点在顶点向量中的位置:");
    scanf("%d",&i);
    if(BFS(G,i-1)==ERROR)
    printf(" 该有向网不存在,操作失败! ");
    for(j=0;j<G.vexnum;j++)
    if(visited[j]==false)
    BFS(G,j);
    printf(" ");
    break;
    case 4:
    if(Out_Vexs(G)==ERROR)
    printf(" 该有向网不存在,操作失败! ");
    break;
    case 5:
    if(Out_arcs(G)==ERROR)
    printf(" 该有向网不存在,操作失败! ");
    break;
    default:
    printf(" 你的操作有误,请重新输入。 ");
    UseDN(G);//调用此函数
    }
    printf(" 请输入你要进行操作的序号:");
    scanf("%d",&x);
    }
    return OK;
    }
    //操作无向图的函数
    Status UseAG(MGraph &G)
    {
    int j;//循环变量
    int x;//存储用户的操作选项
    int i;//存储用户输入的开始的顶点
    system("cls");//清屏函数
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    printf("☆ ☆ ");
    printf("☆ 无向图的相关操作算法 ☆ ");
    printf("☆ ☆ ");
    printf("☆ <1> 无向图的构建 <2> 无向图的深度遍历(递归) ☆ ");
    printf("☆ ☆ ");
    printf("☆ <3> 无向图的广度遍历 <4> 顶点向量 ☆ ");
    printf("☆ ☆ ");
    printf("☆ <3> 邻接矩阵 ☆ ");
    printf("☆ ☆ ");
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    printf(" 请输入你要进行操作的序号:");
    scanf("%d",&x);
    while(x!=88)
    {
    switch(x)
    {
    case 1:
    if(CreateAG(G)!=ERROR)
    printf(" 无向图构建成功! ");
    break;
    case 2:
    for(j=0;j<G.vexnum;j++)//标志数组的初始化
    visited[j]=false;
    printf(" 请输入你要开始深度遍历的顶点在顶点向量中的位置:");
    scanf("%d",&i);
    if(DFSM(G,i-1)==ERROR)
    printf(" 该无向图不存在,操作失败! ");
    for(j=0;j<G.vexnum;j++)
    if(visited[j]==false)
    DFSM(G,j);
    printf(" ");
    break;
    case 3:
    for(j=0;j<G.vexnum;j++)//标志数组的初始化
    visited[j]=false;
    printf(" 请输入你要开始广度遍历的顶点在顶点向量中的位置:");
    scanf("%d",&i);
    if(BFS(G,i-1)==ERROR)
    printf(" 该无向图不存在,操作失败! ");
    for(j=0;j<G.vexnum;j++)
    if(visited[j]==false)
    BFS(G,j);
    printf(" ");
    break;
    case 4:
    if(Out_Vexs(G)==ERROR)
    printf(" 该无向图不存在,操作失败! ");
    break;
    case 5:
    if(Out_arcs(G)==ERROR)
    printf(" 该无向图不存在,操作失败! ");
    break;
    default:
    printf(" 你的操作有误,请重新输入。 ");
    UseAG(G);//调用此函数
    }
    printf(" 请输入你要进行操作的序号:");
    scanf("%d",&x);
    }
    return OK;
    }
    //操作无向网的函数
    Status UseAN(MGraph &G)
    {
    int j;//循环变量
    int x;//存储用户的操作选项
    int i;//存储用户输入的开始的顶点
    system("cls");//清屏函数
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    printf("☆ ☆ ");
    printf("☆ 无向网的相关操作算法 ☆ ");
    printf("☆ ☆ ");
    printf("☆ <1> 无向网的构建 <2> 无向网的深度遍历(递归) ☆ ");
    printf("☆ ☆ ");
    printf("☆ <3> 无向网的广度遍历 <4> 顶点向量 ☆ ");
    printf("☆ ☆ ");
    printf("☆ <3> 邻接矩阵 ☆ ");
    printf("☆ ☆ ");
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    printf(" 请输入你要进行操作的序号:");
    scanf("%d",&x);
    while(x!=88)
    {
    switch(x)
    {
    case 1:
    if(CreateAN(G)!=ERROR)
    printf(" 无向网构建成功! ");
    break;
    case 2:
    printf(" 请输入你要开始深度遍历的顶点在顶点向量中的位置:");
    scanf("%d",&i);
    if(DFSM(G,i-1)==ERROR)
    printf(" 该无向网不存在,操作失败! ");
    for(j=0;j<G.vexnum;j++)
    if(visited[j]==false)
    DFSM(G,j);
    printf(" ");
    break;
    case 3:
    for(j=0;j<G.vexnum;j++)//标志数组的初始化
    visited[j]=false;
    printf(" 请输入你要开始广度遍历的顶点在顶点向量中的位置:");
    scanf("%d",&i);
    if(BFS(G,i-1)==ERROR)
    printf(" 该无向网不存在,操作失败! ");
    for(j=0;j<G.vexnum;j++)
    if(visited[j]==false)
    BFS(G,j);
    printf(" ");
    break;
    case 4:
    if(Out_Vexs(G)==ERROR)
    printf(" 该无向网不存在,操作失败! ");
    break;
    case 5:
    if(Out_arcs(G)==ERROR)
    printf(" 该无向网不存在,操作失败! ");
    break;
    default:
    printf(" 你的操作有误,请重新输入。 ");
    UseAN(G);//调用此函数
    }
    printf(" 请输入你要进行操作的序号:");
    scanf("%d",&x);
    }
    return OK;
    }
    //选择构图函数
    Status CreateGraph(MGraph &G)
    {
    //采用数据(邻接矩阵)表示法,构造图G
    printf("请输入你要构建的图的标号:");
    scanf("%d",&G.kind);
    switch(G.kind)
    {
    case 0:return UseDG(G);//构造有向图 G
    case 1:return UseDN(G);//构造有向网 G
    case 2:return UseAG(G);//构造无向图 G
    case 3:return UseAN(G);//构造无向网 G
    default:printf("您的输入有误,请重新输入。");CreateGraph(G);
    }
    return OK;
    }
    //主菜单函数
    Status OperateMenu()
    {
    system("color fc");
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    Sleep(300);
    system("color f1");
    printf("☆ 图的相关操作算法 ☆ ");
    Sleep(300);
    system("color f5");
    printf("☆ <0> 有向图的构建(DG) <1> 有向网的构建(DN) ☆ ");
    Sleep(300);
    system("color f6");
    printf("☆ <2> 无向图的构建(AG) <3> 无向网的构建(AN) ☆ ");
    Sleep(300);
    system("color fc");
    printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ");
    return OK;
    }
    int main()
    {
    MGraph G;//定义图
    HWND hwnd=GetForegroundWindow();//移动输出框的位置以及改变输出框的大小
    MoveWindow(hwnd,100,100,800,400,1);
    OperateMenu();//调用菜单函数
    CreateGraph(G);//调用选择图的函数
    return 0;
    }

    北音执念i
  • 相关阅读:
    利用API对OWLS描述的服务进行操作 转贴
    转arcgis server部署 自己安装的体会
    最后一次的温柔
    JUDDI安装完整版 (转帖W3CHINA)
    jUDDI安装总结
    Protege中安装owls editor、graphviz插件
    改完了开题报告 舒口气
    服务组合的QoS信息
    owls editor
    一、性能测试术语
  • 原文地址:https://www.cnblogs.com/beiyin/p/7905090.html
Copyright © 2011-2022 走看看