无向有权图的建立(邻接链表法) 广度优先搜索 深度优先搜素

/**图的邻接表存储方式*/

#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<queue>

#define TRUE    1
#define FALSE   0
#define OK      1
#define ERROR   0

using namespace std;

#define MAX_VERTEX_NUM  100


#define MAXSIZE 100

typedef string VertexType;
typedef int    Status;
typedef int Element;

//队列的结点结构
typedef struct QNode{
    Element data;
    struct QNode * next;
}QNode;

//队列的链表结构
typedef struct{
    QNode * queue_front;  //队头指针
    QNode * queue_rear;   //队尾指针
}LinkQueue;


//链队的初始化
Status InitQueue(LinkQueue & Q)
{
    Q.queue_front=Q.queue_rear=(QNode *)malloc(sizeof(QNode));
    Q.queue_front->next=NULL;
    return OK;
}

//入队操作
Status EnQueue(LinkQueue & Q,Element e)
{
    QNode * p;
    p=(QNode*)malloc(sizeof(QNode));
    p->data=e;
    p->next=NULL;
    Q.queue_rear->next=p;
    Q.queue_rear=p;
    return OK;
}

//出队操作
Status Dequeue(LinkQueue & Q,Element & e)
{
    if(Q.queue_front==Q.queue_rear) return ERROR;
    QNode * p;
    p=Q.queue_front->next;      //p指向队头元素
    e=p->data;                  //e保存队头元素的值
    Q.queue_front->next=p->next;//修改头指针
    //注意的是:在链队出队操作时,如果最后一个元素被删除,队尾指针也丢失了,需要对队尾指针重新赋值
    if(Q.queue_rear==p)     Q.queue_rear=Q.queue_front;
    return e;
}

//遍历队列
Status QueueTraverse(LinkQueue Q)
{
    QNode * p;
    p=Q.queue_front->next;
    while(p)
    {
        cout<<(p->data)<<" ";
        p=p->next;
    }
    return OK;
}

//获取队头的元素
Status get_QueueHead(LinkQueue Q,Element & e)
{
    if(Q.queue_front==Q.queue_rear)
    {
        return ERROR;
    }
    else
    {
        e=Q.queue_front->next->data;
        return OK;
    }
}

/**判断队列是否为空*/
Status IsEmpty(LinkQueue Q)
{
    if(Q.queue_front==Q.queue_rear)
        return TRUE;
    else
        return FALSE;
}









queue<int>q;

bool visited[MAX_VERTEX_NUM]={0};
bool visited1[MAX_VERTEX_NUM]={0};

typedef struct Arcnode                  //弧
{
    /**该弧所指向的顶点的位置*/
    int adjvex;
    /**与边有关的信息(权值)*/
    int info;
    /**下一条以当前顶点为出度的弧*/
    struct Arcnode * nextarc;
}/**弧*/Arcnode;


typedef struct VNode                    //点
{
    /**结点名字*/
    VertexType data;
    /**指向第一条依附于该顶点的出边*/
    Arcnode * firstarc;
}/**点*/VNode,/**AdjList表示邻接表类型,点的集合*/AdjList[MAX_VERTEX_NUM];

typedef struct                          //图
{
    /**点的邻接表的数组*/
    AdjList vertices;
    /**图的当前顶点数*/
    int vexnum;
    /**图的当前边数*/
    int arcnum;
}/**图*/ALGraph;


/**加边*/
void ArcAdd(ALGraph &G,int v1,int v2,int w)     //加边
{
    Arcnode *p,*q;                              //Arcnode是弧

    p = new Arcnode;                            //新建立一个结点p
    p->adjvex=v2;                               //p边指向顶点位置为v2的那个顶点
    p->info=w;                                  //这条边的权重为w
    p->nextarc=NULL;                            //?
    q=G.vertices[v1].firstarc;                  //位置为v1这个点的第一条出边为q
    if(q==NULL)
    {
        G.vertices[v1].firstarc=p;  //若第一条依附v2顶点的弧还没有存在,则新加入的边作为第一条依附的弧

    }
    else                            //否则顺着链表向后查找
    {
        while(q->nextarc!=NULL)
            q=q->nextarc;
        q->nextarc=p;
    }

}

/**获取每个结点对应的存储位置标号*/
int LocateVex(ALGraph G,string name)
{
    for(int i=0;i<G.vexnum;i++)
    {
        if(name==G.vertices[i].data)
        {
            return i;
        }
    }
    return -1;
}

/**建立带权无向图*/
Status CreateUDN_2(ALGraph & G)
{
    cout<<"建立带权无向图,请依次输入总结点数,总边数:";
    cin>>G.vexnum>>G.arcnum;
    cout<<"请为从1至n个结点命名:"<<endl;
    for(int i=0;i<G.vexnum;i++)
    {
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc=NULL;
    }
    string v1,v2;
    int w;
    cout<<"请输入"<<G.arcnum<<"组相互依附的两结点与边权"<<endl;
    for(int k=0;k<G.arcnum;k++)
    {
        cin>>v1>>v2>>w;
        int i=LocateVex(G,v1);
        int j=LocateVex(G,v2);
        ArcAdd(G,i,j,w);             //无向边
        ArcAdd(G,j,i,w);             //无向边
    }
    return OK;

}

/**第一个邻接点
*@return 返回值是v的第一个邻接点顶点的位置;若没有邻结点则返回为"空"
*/
int FirstAdjVex(ALGraph G,int v)
{
    if(G.vertices[v].firstarc)          //如果说对于点v,存在该点的一条出边
    {
        return G.vertices[v].firstarc->adjvex;      //返回v顶点的一条出边指向的那个顶点的位置
    }
    else
    {
        return -1;
    }
}

/**相对与某一点的下一个邻接点
*@return 返回值是v的(相对于w的)下一个邻接点;如果w是v的最后一个邻接点,则返回值为"空"
*/
int NextAdjVex(ALGraph G,int v,int w)
{
    Arcnode * p =G.vertices[v].firstarc;            //边p是顶点v的第一条出边
    while(p->adjvex!=w&&p->nextarc!=NULL)
    {
        p=p->nextarc;
    }
    if(p->nextarc==NULL)
    {
        return -1;
    }
    return p->nextarc->adjvex;
}

/**打印邻接表*/
void PrintGraph(ALGraph G)
{
    cout<<"图的创建完成,该图的邻接表表示如下:"<<endl;
    cout<<"括号内表示边的权重——括号前面两个顶点组成边的权重,若权重为0表示没有权重"<<endl;
    Arcnode *p;                             //一条弧p
    for(int i=0;i<G.vexnum;i++)
    {
        if(G.vertices[i].firstarc==NULL)
        {
            cout<<i<<":  "<<G.vertices[i].data<<"-->NULL"<<endl;
        }
        else
        {
            p=G.vertices[i].firstarc;
            cout<<i<<":  "<<G.vertices[i].data<<"-->";
            while(p->nextarc!=NULL)
            {
                cout<<p->adjvex<<"("<<p->info<<")"<<"-->";
                p=p->nextarc;
            }
            cout<<p->adjvex<<"("<<p->info<<")"<<"-->NULL"<<endl;
        }
    }
}

/**深度优先搜索*/
void DFS(ALGraph G,int v)
{
    int w = 0;
    Arcnode * p = NULL;
    cout<<v;
    visited[v]=1;
    p=G.vertices[v].firstarc;
    while(p!=NULL)
    {
        w=p->adjvex;
        if(!visited[w])
        {
            DFS(G,w);
        }
        p=p->nextarc;
    }

}

/**广度优先搜索(使用标准库queue)*/
/*
void BFS(ALGraph G,int v)
{
    cout<<v;
    visited1[v]=1;
    q.push(v);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        Arcnode * p;
        p=G.vertices[u].firstarc;
        while(p!=NULL)
        {
            if(!visited1[p->adjvex]){
                cout<<p->adjvex;
                visited1[p->adjvex]=1;
                q.push(p->adjvex);
            }
            p=p->nextarc;
        }
    }
}
*/

/**广度优先搜索(自己写的队列)*/
void BFS1(ALGraph G,int v)
{
    LinkQueue queue1;
    InitQueue(queue1);
    cout<<v;
    visited1[v]=1;
    EnQueue(queue1,v);
    while(!IsEmpty(queue1))
    {
        int u=0;
        //u = get_QueueHead(queue1,u);
        //Dequeue(queue1,u);
        u=Dequeue(queue1,u);
        Arcnode * p ;
        p=G.vertices[u].firstarc;
        while(p!=NULL)
        {
            if(!visited1[p->adjvex])
            {
                cout<<p->adjvex;
                visited1[p->adjvex]=1;
                EnQueue(queue1,p->adjvex);
            }
            p=p->nextarc;
        }
    }
}

int main()
{
    ALGraph G;
    CreateUDN_2(G);
    PrintGraph(G);
    cout<<"深度优先搜素遍历如下:"<<endl;
    DFS(G,0);
    cout<<"广度优先搜素遍历如下:"<<endl;
    BFS1(G,0);
    return 0;
}

注释还没写完,要考试了,唉…

参考两位大佬的资料,然后广度优先没用STL,用的自己之前写的链队
https://blog.csdn.net/kuronekonano/article/details/78657592 作者:kuronekonano
https://blog.csdn.net/Krismile_/article/details/84774256 作者:Krismile_

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值