数据结构 图型结构及其应用

作业3 图型结构及其应用

作业要求1:

​ 分别实现无向图(或有向图)的邻接矩阵和邻接表存储结构的建立算法,分析和比较各建立算法的时间复杂度以及存储结构的空间占用情况。

void CreatMGraph(MTgraph*G)//邻接矩阵表示,数组表示法
{
    //printf("Adjacency matrix representation, array representation, array representation\n");
    int w;//记录权值
    int i,j;
    FILE* fp=fopen("graph.txt","r");//将图中结点信息保存在文件中
    FILE* fq=fopen("data.txt","r");
    //printf("Please enter the number of nodes:");
    fscanf(fq,"%d ",&G->n);//节点数目
    //printf("Please enter the number of edges:");
    fscanf(fq,"%d ",&G->e);//边的数目
    for(i=0;i<G->n;i++)
    {
        fscanf(fp,"%d ",&(G->v[i]));//读入节点名称
    }
    fclose(fp);
    for(i=0;i<G->n;i++)
    for(j=0;j<G->n;j++)
    G->edge[i][j]=0;
    for(int k=0;k<G->e;k++)
    {
        //printf("Please enter a node of the edge:");
        fscanf(fq,"%d ",&i);//左顶点的位置信息
        //printf("Please enter another node for the edge:");
        fscanf(fq,"%d ",&j);//右顶点的位置信息
        //printf("Please enter the weights:");
        fscanf(fq,"%d ",&w);
        G->edge[i][j]=w;
        G->edge[j][i]=w;
    }
    fclose(fq);
    printf("Build successfully!\n");
}

邻接矩阵建立算法,时间复杂度为o(n),空间占用:n2矩阵,占用大小为n2的sizeof(int)。

void CreateGraph(Adjgraph*G)//邻接表存储结构建立的算法
{
    //printf("Adjacency list storage structure establishment algorithm\n");
    FILE* fp=fopen("graph.txt","r");
    FILE* ft=fopen("data2.txt","r");
    int head,tail,weight;
    //printf("Please enter the number of nodes:");
    fscanf(ft,"%d ",&G->n);//输入顶点个数
    //printf("Please enter the number of edges:");
    fscanf(ft,"%d ",&G->e);//输入边数
    for(int i=0;i<G->n;i++)
    {
        fscanf(fp,"%d ",&(G->vlist[i].v));//输入顶点信息
        G->vlist[i].firstedge=NULL;//将边表设置为空表
    }
    fclose(fp);
    for(int i=0;i<G->e;i++)
    {
        //printf("Please enter a node of the edge:");
        fscanf(ft,"%d ",&head);//输入出边顶点
        //printf("Please enter another node for the edge:");
        fscanf(ft,"%d ",&tail);//输入入边顶点
        //printf("Please enter the weight:");
        fscanf(ft,"%d ",&weight);//输入权重
        EdgeNode* p=NULL;
        if((p=(EdgeNode *)malloc(sizeof(EdgeNode)))==NULL)
        return;
        p->adj=head;//设置边界点
        p->cost=weight;
        p->next=G->vlist[tail].firstedge;//链入第tail号链表的前端
        G->vlist[tail].firstedge=p;
        EdgeNode* q=NULL;
        if((q=(EdgeNode *)malloc(sizeof(EdgeNode)))==NULL)
        return;
        q->adj=tail;
        q->cost=weight;
        q->next=G->vlist[head].firstedge;
        G->vlist[head].firstedge=q;
    }
    fclose(ft);
    printf("Build successfully!\n");
}

邻接表建立算法,时间复杂度为o(n),空间占用:使用静态数组存储结点,使用动态链表存储边,所占的大小为 2x边数x sizeof(EdgeNode)+静态数组n*sizeof(EdgeNode)

作业要求2:

void AMTransfer(MTgraph* G1,const Adjgraph G2)//从邻接表转换为邻接矩阵
{
    int j;
    G1->e=G2.e;//边数传递
    int count=G2.e;//记录边数
    G1->n=G2.n;//结点数传递
    EdgeNode*p=NULL;
    int flag[size][size]={0};
    for(int i=0;i<G2.n;i++)
    {
        p=G2.vlist[i].firstedge;
        while(p!=NULL)
        {
            j=p->adj;
            if(flag[i][j]!=0)  
            {
                p=p->next;
                continue;
            }
            flag[i][j]++;
            flag[j][i]++;
            G1->edge[j][i]=p->cost;
            G1->edge[i][j]=p->cost;
            count--;
            if(count<0) return;
            p=p->next;
        }
    }
}

邻接表转换为邻接矩阵

void MATransfer(Adjgraph* G2,const MTgraph G1)//从邻接矩阵转换为邻接表
{
    G2->e=G1.e;//边数传递
    G2->n=G1.n;//结点数传递
    for(int i=0;i<G1.n;i++)
    for(int j=i;j<G1.n;j++)
    if(G1.edge[i][j]!=0)
    {
        EdgeNode* p=NULL;
        if((p=(EdgeNode *)malloc(sizeof(EdgeNode)))==NULL)
        return;
        p->adj=i;//设置边界点
        p->cost=G1.edge[i][j];
        p->next=G2->vlist[j].firstedge;//链入第tail号链表的前端
        G2->vlist[j].firstedge=p;
        EdgeNode* q=NULL;
        if((q=(EdgeNode *)malloc(sizeof(EdgeNode)))==NULL)
        return;
        q->adj=j;
        q->cost=G1.edge[i][j];
        q->next=G2->vlist[i].firstedge;
        G2->vlist[i].firstedge=q;
    }
}

邻接矩阵转换为邻接表

作业要求3

在上述两种存储结构上,分别实现无向图(或有向图)的深度优先搜索(递归和非递归)和广度优先搜索算法。并以适当的方式存储和展示相应的搜索结果,包括:深度优先或广度优先生成森林(或生成树)、深度优先或广度优先序列和深度优先或广度优先编号。并分析搜索算法的时间复杂度和空间复杂度 。

void DFSTA_X(Adjgraph G,int i,Tree *T)//循环实现邻接表深度优先算法
{
    int temp=0;int flag=0;int t=i;
    int S[size];//设置一个栈(最大为顶点数)
    for(int i=0;i<size;i++)
    S[i]=-1;
    int top=0;//设置栈顶
    Tree*tp=createNew();
    Tree*ST[size];
    for(int i=0;i<size;i++)
    ST[i]=NULL;
    int Top=0;
    ST[Top]=tp;
    S[top]=i;//将该结点进栈
    visit[i]=1;
    T->v=G.vlist[i].v;
    tp=T;
    EdgeNode*p=NULL;
    int first=0;
    printf("%d ",G.vlist[i].v);
    while(top!=-1)
    {
        temp=-1;
        p=G.vlist[t].firstedge;
        while(p!=NULL)
        {
            if(!visit[p->adj])
            {
                temp=p->adj;
                if(flag==1)
                {
                    top++;
                    S[top]=t;
                    tp->rchild=createNew();
                    tp=tp->rchild;
                    tp->v=G.vlist[temp].v;
                }
                break;
            }
            p=p->next;
        }
        if(temp==-1)
        {
            t=S[top];top--;
            tp=ST[Top];Top--;
            flag=1;
        }
        else{
            printf("%d ",G.vlist[temp].v);
            top++;Top++;
            S[top]=temp;
            visit[temp]=1;
            t=temp;
            ST[Top]=tp;
            if(flag!=1)
            {
                tp->lchild=createNew();
                tp=tp->lchild;
                tp->v=G.vlist[temp].v;
            }
            flag=0;
        }
    }
}
void DFSTA(Adjgraph G,int i,Tree *T)//邻接表深度优先算法递归单元
{
    EdgeNode* p;
    visit[i]=1;//对方访问过的节点进行标记
    sub[i]=count++;//进行编号
    p=G.vlist[i].firstedge;//取一个边表的头指针
    printf("%d ",G.vlist[i].v);//访问该节点
    T->v=G.vlist[i].v;
    Tree* tp=createNew();
    int flag=1;
    while(p!=NULL)
    {
        if(!visit[p->adj])
        {
            if(flag==1)
            {
                T->lchild=tp;
                DFSTA(G,p->adj,tp);
                flag=0;
            }
            else
            {
                tp->rchild=createNew();
                tp=tp->rchild;
                DFSTA(G,p->adj,tp);
            }
        }
        p=p->next;
    }
}
void DFSTB_X(MTgraph G,int i,Tree* T)//循环实现邻接矩阵深度优先算法
{
    int temp=0;int flag=0;
    int S[size];//设置一个栈(最大为顶点数)
    for(int i=0;i<size;i++)
    S[i]=-1;
    int top=0;//设置栈顶
    Tree*tp=createNew();
    Tree*ST[size];
    for(int i=0;i<size;i++)
    ST[i]=NULL;
    int Top=0;
    ST[Top]=tp;
    S[top]=i;//将该结点进栈
    visit[i]=1;
    T->v=G.v[i];
    tp=T;
    int m;
    printf("%d ",G.v[i]);
    while(top!=-1)
    {
        for(m=0;m<G.n;m++)
        {
            if(G.edge[i][m]>0&&visit[m]!=1)
            {
                if(flag==1)
                {
                    top++;
                    S[top]=i;
                    tp->rchild=createNew();
                    tp=tp->rchild;
                    tp->v=G.v[m];
                }
                break;
            }
        }
        if(m==G.n)
        {
            flag=1;
            i=S[top];
            S[top]=-1;
            top--;
            tp=ST[Top];Top--;
        }
        else
        {
                printf("%d ",G.v[m]);
                top++;Top++;
                S[top]=m;
                visit[m]=1;
                i=m;
                ST[Top]=tp;
                if(flag!=1)
                {
                    tp->lchild=createNew();
                    tp=tp->lchild;
                    tp->v=G.v[m];
                }
                flag=0;
        }
    }
}
void DFSTB(MTgraph G,int i,Tree*T)//邻接矩阵深度优先算法递归单元
{
    int j;
    printf("%d ",G.v[i]);
    visit[i]=1;
    sub[i]=count++;
    int flag=1;
    T->v=G.v[i];
    Tree*tp=createNew();
    for(j=0;j<G.n;j++)
    {
        if((G.edge[i][j]>0)&&(!visit[j]))
        {
            if(flag==1)
            {
                T->lchild=tp;
                DFSTB(G,j,tp);
                flag=0;
            }
            else
            {
                tp->rchild=createNew();
                tp=tp->rchild;
                DFSTB(G,j,tp);
            }
        }
    }
}
void DFSTAmain(Adjgraph G,Tree* T)//邻接表深度优先算法
{
    int flag=0;
    Tree* tp=createNew();
    for(int j=0;j<G.n;j++)
    visit[j]=0;
    for(int i=0;i<G.n;i++)
    {
        if(!visit[i])
        {
            if(flag==0)
            {
                T->lchild=tp;
                DFSTA(G,i,tp);
                flag=1;
            }
            else
            {
                tp->rchild=createNew();
                tp=tp->rchild;
                DFSTA(G,i,tp);
            }
        }
    }
    printf("\n");
}
void DFSTAmain_X(Adjgraph G,Tree *T)//邻接表深度优先算法(循环)
{
    int flag=0;
    Tree* tp=createNew();
    for(int j=0;j<G.n;j++)
    visit[j]=0;
    for(int i=0;i<G.n;i++)
    {
        if(!visit[i])
        {
            if(flag==0)
            {
                T->lchild=tp;
                DFSTA_X(G,i,tp);
                flag=1;
            }
            else
            {
                while(tp->rchild!=NULL)tp=tp->rchild;
                tp->rchild=createNew();
                tp=tp->rchild;
                DFSTA_X(G,i,tp);
            }
        }
    }
    printf("\n");
}
void DFSTBmain(MTgraph G,Tree* T)//邻接矩阵深度优先算法
{
    int flag=0;
    Tree*tp=createNew();
    for(int j=0;j<G.n;j++)
    visit[j]=0;
    for(int i=0;i<G.n;i++)
    {
        if(!visit[i])
        {
            if(flag==0)
                {
                    T->lchild=tp;
                    DFSTB(G,i,tp);
                    flag=1;
                }
                else
                {
                    tp->rchild=createNew();
                    tp=tp->rchild;
                    DFSTB(G,i,tp);
                }
        }
    }
    printf("\n");
}
void DFSTBmain_X(MTgraph G,Tree*T)//邻接矩阵深度优先算法(递归)
{
    int flag=0;
    Tree*tp=createNew();
    for(int j=0;j<G.n;j++)
    visit[j]=0;
    for(int i=0;i<G.n;i++)
    {
        if(!visit[i])
        {
            if(flag==0)
                {
                    T->lchild=tp;
                    DFSTB_X(G,i,tp);
                    flag=1;
                }
                else
                {
                    while(tp->rchild!=NULL)tp=tp->rchild;
                    tp->rchild=createNew();
                    tp=tp->rchild;
                    DFSTB_X(G,i,tp);
                }
        }
    }
    printf("\n");
}
void BFSTA(Adjgraph G,int i)//邻接表广度优先算法单元
{
    int j;EdgeNode*p=NULL;
    initial(&Q);
    printf("%d ",G.vlist[i].v);
    visit[i]=1;
    inque(i,&Q);
    while(Q.head!=Q.tail)
    {
        j=ouque(&Q);
        p=G.vlist[j].firstedge;
        while(p!=NULL)
        {
            if(!visit[p->adj])
            {
                printf("%d ",G.vlist[p->adj].v);
                visit[p->adj]=1;
                inque(p->adj,&Q);
            }
            p=p->next;
        }
    }
}
void BFSTB(MTgraph G,int i)//邻接矩阵广度优先算法单元
{
    int j,k;queue Q;initial(&Q);
    printf("%d ",G.v[i]);
    visit[i]=1;
    inque(i,&Q);
    while(Q.head!=Q.tail)
    {
        j=ouque(&Q);
        for(k=0;k<G.n;k++)
        {
            if(G.edge[j][k]>0&&(!visit[k]))
            {
                printf("%d ",G.v[k]);
                visit[k]=1;
                inque(k,&Q);
            }
        }
    }
}
void BFSTAmain(Adjgraph G)//邻接表广度优先算法
{
    for(int i =0; i<G.n;i++)
    {
        visit[i]=0;
    }
    for(int i=0;i<G.n;i++)
    {
        if(!visit[i])
        BFSTA(G,i);//从顶点i出发的第一次搜索
    }
    printf("\n");
}
void BFSTBmain(MTgraph G)//邻接矩阵广度优先算法
{
    for(int i =0; i<G.n;i++)
    {
        visit[i]=0;
    }
    for(int i=0;i<G.n;i++)
    {
        if(!visit[i])
        BFSTB(G,i);//从顶点i出发的第一次搜索
    }
    printf("\n");
}

​ 在该过程中实现了生成树,通过遍历生成树会得到与遍历相似的结果。时间复杂度为o(n2)。分别是在递归单元外有n在递归单元内有n的遍历,导致最后为o(n2)的复杂度。没递归一次调用一次栈,栈中的元素最多的时候(即空间复杂度)为n。

作业要求4:

对于无向图,采用“邻接表”存储结构,设计和实现计算每个顶点度的算
法,并分析其时间复杂度。

遍历所有结点的next值,最坏的情况为o(n2)的时间复杂度。

void Dev2(Adjgraph G,DEV* dev2)//邻接表的度计算
{
    EdgeNode*p=NULL;
    for(int i=0;i<G.n;i++)
    {
        dev2->v[i]=G.vlist[i].v;
        p=G.vlist[i].firstedge;
        while(p!=NULL)
        {
            dev2->dev[i]++;
            p=p->next;
        }
    }
}

测试用例

20 15 6 7 3 8 5 9 7 11 12 4 5 13 11 4 2 14 5 9 12 4 9 11 3 6 2 3 9 10 14 13 2 5 1 2 4 0 2 7 4 3 2 19 3 7 5 11

前两个值第一个代表顶点第二个代表边的数量

测试结果如下:

Build successfully!
Build successfully!
please enter your choice:1
1 2 3 4 12 15 6 5 13 9 8 7 10 11 14 16 17 18 19 20
1 2 3 4 12 15 6 5 13 9 8 7 10 11 14 16 17 18 19 20
1 2 3 4 12 15 6 5 13 9 8 7 10 11 14 16 17 18 19 20
1 2 3 4 12 15 6 5 13 9 8 7 10 11 14 16 17 18 19 20
please enter your choice:2
1 5 6 8 7 9 2 3 4 10
1 5 6 8 7 9 2 3 4 10
1 5 6 8 7 9 2 3 4 10
1 5 6 8 7 9 2 3 4 10
please enter your choice:3
1 2 3 4 12 15 5 8 6 13 7 9 10 11 14 16 17 18 19 20
please enter your choice:4
1 5 6 8 9 7 2 3 4 10
please enter your choice:5
点的名称为:1 度为:0
点的名称为:2 度为:0
点的名称为:3 度为:1
点的名称为:4 度为:2
点的名称为:5 度为:3
点的名称为:6 度为:3
点的名称为:7 度为:1
点的名称为:8 度为:2
点的名称为:9 度为:1
点的名称为:10 度为:0
点的名称为:11 度为:0
点的名称为:12 度为:4
点的名称为:13 度为:1
点的名称为:14 度为:0
点的名称为:15 度为:2
点的名称为:16 度为:0
点的名称为:17 度为:0
点的名称为:18 度为:0
点的名称为:19 度为:0
点的名称为:20 度为:0

完整代码请看代码文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值