Data Structure and Algorithm Fundamentals (Wang Zhuo) (26) Attachment: Breadth-First Traversal Algorithm BFS of Adjacency List (Learning Process Record)

Table of contents

Breadth-first traversal algorithm BFS of adjacency list

First edition:

question:

The frame of the second edition:

Sort out the context:

Version 3: (error)

1:

2: 

Final result: (version with comments)

The entire program version including environment and preconditions:

Wish: Don’t fight internally, time passes inexplicably without knowing what’s going on, it’s really strange

that's all


Breadth-first traversal algorithm BFS of adjacency list

First edition:

void BFS(ALG G, int v)
{
    cout << G.vex[v].data;
    visited[v] = 1;
    SqQueue Q;
    InitQueue(Q);
    auto i=G.vex[v].firstarc;
    while(!QueneEmpty(Q))
    { 
        if(visited[i->adjvex]=0)
            EnQueue(Q, i->adjvex);
        i = i->nextarc;
        BFS(G,i->adjvex);
    }
}

question:

At the beginning, one element must be enqueued first

There is no dequeue operation. At the same time, we noticed that
there is a prerequisite for dequeue, that is, we can only dequeue after all subsequent edge nodes on the link have entered the team.

Recursion cannot be used here, because with recursion he will start to create new queues repeatedly, and he will be endless like this


Then based on these points, we temporarily listed out the

The frame of the second edition:

{
    //i表示头,J表示指向的每个元素
    while (j.next != NULL)
    {
        if(visited[j.邻接])
        {
            入队;
            下一位;
            输出;
        }
        出队;
    }
}

 As a result, there are still many problems:

Not marked "visited" 

 The judgment should be the node itself, not: j.next

And the important thing is: as long as this node is not empty, we will always point to the next one

Regardless of whether the element has been accessed before or not, the operation of finding the next bit every time we loop is the same

Similarly, the number of outputs should be consistent with the number of dequeues

Notice:

I means the head is used for dequeue and output

J means that each element pointed to is used to loop through


So I feel that the writing here is a bit messy. TMD is still very confusing as I feel, so I still have to

Sort out the context:

  1. Enqueue all [unvisited] elements on the link
  2. dequeue vertices
  3. Continue to traverse from the head of the team and repeat the loop steps (that is to say, 1 and 2 are the statements inside the loop body)

Write the third edition according to the context:


Version 3: (error)

Then we went to tinker with it for a long time, but the following problems still occurred:

1:

Note: judgment statement

            if (visited[j->adjvex] == 0)//enqueue [unvisited] element

Should be "==", not "="


2: 

        cout << j->adjvex;

Note: We should use i to output this thing


The problems encountered in the process are mainly the above, because I did not make revisions for every program modification during the learning process, I can only list these pits according to the process, and there may be others, but these pits It should have stepped on enough,


Final result: (version with comments)

int visited[MVNum] = {};    
void BFS(ALG G, int v)
{
    cout << G.vex[v].data;
    visited[v] = 1;
    SqQueue Q;
    InitQueue(Q);
    EnQueue(Q, G.vex[v].firstarc->adjvex);//从第一个顶点开始遍历
    auto i = G.vex[v].firstarc;//指向(代表)链头
    while (!QueneEmpty(Q))//直至队空结束
    {
        auto j = i;//用于指向访问各个元素节点
        while (j != NULL)//当结点为空(链尾,结束了)结束循环
        {
            if (visited[j->adjvex] == 0)//入队【没被访问过的】元素
            {
                EnQueue(Q, j->adjvex);
            }
            j = j->nextarc;//指向下一轮循环
            visited[j->adjvex] = 1;//别忘了
        }
        DeQueue(Q, i->adjvex);//出队队头
        cout << j->adjvex;
        //输出出队的元素,当然这里出队和输出在循环开始时操作也可以
    }
}

The entire program version including environment and preconditions:

#include<iostream>
using namespace std;

typedef int Status;

#define MVNum 100  //最大顶点数
//MAX Vertex Number
typedef char VertexType;  //设顶点类型:字符型

//弧/边的结点结构
typedef int OtherInfo;
struct ArcNode
{
    int adjvex;//Adjacency
    //该边所指向的(相邻)顶点的位置
    struct ArcNode* nextarc;  //指向下一条边的指针
    OtherInfo info;  //和边相关的信息
};

struct VertexNode
    //顶点的结点结构
{
    VertexType data;  //顶点信息
    ArcNode* firstarc;  //指向第一条依附该顶点的边的指针
};

//图的结构定义
struct ALG
{
    //AdjList vertices;  
    VertexNode vex[MVNum];//顶点表
    int vexnum, arcnum;  //顶点数和边数
}; //Adjacency List Graph

#include<stdlib.h>//存放exit
#include<math.h>//OVERFLOW,exit

#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE  -1
//#define OVERFLOW   -2   

typedef char QElemType;
typedef int Status;         //函数调用状态
#define MAXQSIZE 100  //初始大小为100,可按需修改

struct SqQueue//循环队列定义
{
    QElemType* base;//初始化的动态分配存储空间
    int rear;//头指针
    int front;//尾指针
};

Status InitQueue(SqQueue& Q)//初始化
{
    Q.base = new QElemType[MAXQSIZE];
    //Q.base = (QElemType*)malloc(MAXQSIZE * sizeof(QElemType));
    if (!Q.base) exit(OVERFLOW);//存储分配失败
    Q.rear = Q.front = 0;
    return true;
}

Status Queuelength(SqQueue Q)//求长度
{
    return(Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}

QElemType GetHead(SqQueue Q)//取队头元素
{
    if (Q.front != Q.rear)
        //别忘排除空表的情况
        return(Q.base[Q.front]);
}

Status EnQueue(SqQueue& Q, QElemType e)//入队
{
    if ((Q.rear + 1) % MAXQSIZE == Q.front)
        return OVERFLOW;
    Q.base[Q.rear] = e;
    //这里rear只是下标,不是指针,所以只能这样用
    Q.rear = (Q.rear + 1) % MAXQSIZE;
    return true;
}

Status DeQueue(SqQueue& Q, QElemType e)//出队
{
    if (Q.front == Q.rear)
        return NULL;
    e = Q.base[Q.front];
    Q.front = (Q.front + 1) % MAXQSIZE;
    return true;
}

Status QueneEmpty(SqQueue& Q)
{
    if (Q.front == Q.rear)
        return true;
    else
        return false;
}

int visited[MVNum] = {};    
void BFS(ALG G, int v)
{
    cout << G.vex[v].data;
    visited[v] = 1;
    SqQueue Q;
    InitQueue(Q);
    EnQueue(Q, G.vex[v].firstarc->adjvex);//从第一个顶点开始遍历
    auto i = G.vex[v].firstarc;//指向(代表)链头
    while (!QueneEmpty(Q))//直至队空结束
    {
        auto j = i;//用于指向访问各个元素节点
        while (j != NULL)//当结点为空(链尾,结束了)结束循环
        {
            if (visited[j->adjvex] == 0)//入队【没被访问过的】元素
            {
                EnQueue(Q, j->adjvex);
            }
            j = j->nextarc;//指向下一轮循环
            visited[j->adjvex] = 1;//别忘了
        }
        DeQueue(Q, i->adjvex);//出队队头
        cout << j->adjvex;
        //输出出队的元素,当然这里出队和输出在循环开始时操作也可以
    }
}

int main()
{

}

Wish: Don’t fight internally, time passes inexplicably without knowing what’s going on, it’s really strange

that's all

Guess you like

Origin blog.csdn.net/Zz_zzzzzzz__/article/details/130068772