更多数据结构代码实现请关注我的专栏数据结构
或者进入2021-10-16【严蔚敏数据结构代码实现合集】【c语言学习必备】学习
邻接表与邻接矩阵实现功能类似,详情见邻接矩阵
邻接表数据结构声明
//边表节点结构,一个adjvex用来存储邻接点的位置,一个next指针用来指向下一个节点
typedef struct EdgeNode
{
int adjvex;
struct EdgeNode * next;
} EdgeNode;
//顶点表节点结构,一个data用来存储数据,一个firstedge是用来指向边表的第一个节点
typedef struct
{
string data;
EdgeNode * firstedge;
} AdjList;
//里面的adjList[15]表示我给顶点表开了15的单位大小,然后numVertex,numEdge是一个图的顶点数和边数
typedef struct
{
AdjList adjList[15];
int numVertex,numEdge;
} GraphAdjList;
创建邻接表
//这个函数是这样的,它会遍历图的顶点,然后返回一个位置(其实也就是它所在的下标)
int local(GraphAdjList G,string val)
{
for(int i=0; i<G.numVertex; i++)
{
if(G.adjList[i].data==val)
return i;
}
return -1;
}
//比如v2的位置是在2 这个可以看上面的顶点表图
void CreateGraph(GraphAdjList & G)
{
int i,j,k;
string v1,v2;
EdgeNode * e,* p,*q;
cout<<"请输入顶点数和边数,并以空格隔开:"<<endl;
cin>>G.numVertex>>G.numEdge;
cout<<"请输入顶点的信息:"<<endl;
for(i=0; i<(G.numVertex); i++)
{
cout<<"第"<<i+1<<"个顶点:"<<endl;
cin>>G.adjList[i].data;
G.adjList[i].firstedge=NULL;
}
for(k=0; k<(G.numEdge); k++)
{
cout<<"请输入边(Vi,Vj)上的顶点信息:"<<endl;
cin>>v1>>v2;
i=local(G,v1);
j=local(G,v2);
if(G.adjList[i].firstedge==NULL)
{
e= new EdgeNode;
e->adjvex=j;
e->next=NULL;
G.adjList[i].firstedge=e;
}
else
{
p=G.adjList[i].firstedge;
while(p->next!=NULL)
{
p=p->next;
}
e = new EdgeNode;
e->adjvex=j;
e->next=NULL;
p->next=e;
}
if(G.adjList[j].firstedge==NULL)
{
e= new EdgeNode;
e->adjvex=i;
e->next=NULL;
G.adjList[j].firstedge=e;
}
else
{
p=G.adjList[j].firstedge;
while(p->next!=NULL)
{
p=p->next;
}
e = new EdgeNode;
e->adjvex=i;
e->next=NULL;
p->next=e;
}
}
}
打印邻接表
void Prin(GraphAdjList G)
{
cout<<"所建立的邻接表如以下所示:"<<endl;
for(int i=0; i<G.numVertex; i++)
{
cout<<G.adjList[i].data; //先输出顶点信息
EdgeNode * e = G.adjList[i].firstedge;
while(e) //然后就开始遍历输出每个边表所存储的邻接点的下标
{
cout<<"-->"<<e->adjvex;
e=e->next;
}
cout<<endl;
}
}
状态数组
bool DFSvisited[50]; //用于深搜的标记数组
bool BFSvisited[50]; //用于广搜的标记数组
深度优先搜索
void DFS(GraphAdjList G,int i)
{
EdgeNode * p;
DFSvisited[i]=true;
cout<<G.adjList[i].data<<" ";
p=G.adjList[i].firstedge;
while(p)
{
if(!DFSvisited[p->adjvex])
DFS(G,p->adjvex);
p=p->next;
}
}
void DFSTraverse(GraphAdjList G)
{
for(int i=0; i<G.numVertex; i++)
DFSvisited[i]=false;
for(int i=0; i<G.numVertex; i++)
{
if(!DFSvisited[i])
DFS(G,i);
}
}
广度优先搜索
作者比较懒 就没有用自己实现的队列进行存储操作,感兴趣的同学可以看看我写的2021-9-28【数据结构/严蔚敏】【循环队列】
把相应STL中queue的操作替换掉就可以了。
void BFSTraverse(GraphAdjList G)
{
EdgeNode * p;
queue<int>q;
for(int i=0; i<G.numVertex; i++)
BFSvisited[i]=false;
for(int i=0; i<G.numVertex; i++)
{
if(!BFSvisited[i])
{
BFSvisited[i]=true;
cout<<G.adjList[i].data<<" ";
q.push(i);
while(!q.empty())
{
int count =q.front();
q.pop();
p=G.adjList[count].firstedge;
while(p)
{
if(!BFSvisited[p->adjvex])
{
BFSvisited[p->adjvex]=true;
cout<<G.adjList[p->adjvex].data<<" ";
q.push(p->adjvex);
}
p=p->next;
}
}
}
}
}
完整代码
#include<bits/stdc++.h>
using namespace std;
//边表节点结构,一个adjvex用来存储邻接点的位置,一个next指针用来指向下一个节点
typedef struct EdgeNode
{
int adjvex;
struct EdgeNode * next;
} EdgeNode;
//顶点表节点结构,一个data用来存储数据,一个firstedge是用来指向边表的第一个节点
typedef struct
{
string data;
EdgeNode * firstedge;
} AdjList;
//里面的adjList[15]表示我给顶点表开了15的单位大小,然后numVertex,numEdge是一个图的顶点数和边数
typedef struct
{
AdjList adjList[15];
int numVertex,numEdge;
} GraphAdjList;
//这个函数是这样的,它会遍历图的顶点,然后返回一个位置(其实也就是它所在的下标)
int local(GraphAdjList G,string val)
{
for(int i=0; i<G.numVertex; i++)
{
if(G.adjList[i].data==val)
return i;
}
return -1;
}
//比如v2的位置是在2 这个可以看上面的顶点表图
void CreateGraph(GraphAdjList & G)
{
int i,j,k;
string v1,v2;
EdgeNode * e,* p,*q;
cout<<"请输入顶点数和边数,并以空格隔开:"<<endl;
cin>>G.numVertex>>G.numEdge;
cout<<"请输入顶点的信息:"<<endl;
for(i=0; i<(G.numVertex); i++)
{
//cout<<"第"<<i+1<<"个顶点:"<<endl;
cin>>G.adjList[i].data;
G.adjList[i].firstedge=NULL;
}
for(k=0; k<(G.numEdge); k++)
{
//cout<<"请输入边(Vi,Vj)上的顶点信息:"<<endl;
cin>>v1>>v2;
i=local(G,v1);
j=local(G,v2);
if(G.adjList[i].firstedge==NULL)
{
e= new EdgeNode;
e->adjvex=j;
e->next=NULL;
G.adjList[i].firstedge=e;
}
else
{
p=G.adjList[i].firstedge;
while(p->next!=NULL)
{
p=p->next;
}
e = new EdgeNode;
e->adjvex=j;
e->next=NULL;
p->next=e;
}
if(G.adjList[j].firstedge==NULL)
{
e= new EdgeNode;
e->adjvex=i;
e->next=NULL;
G.adjList[j].firstedge=e;
}
else
{
p=G.adjList[j].firstedge;
while(p->next!=NULL)
{
p=p->next;
}
e = new EdgeNode;
e->adjvex=i;
e->next=NULL;
p->next=e;
}
}
}
void Prin(GraphAdjList G)
{
cout<<"所建立的邻接表如以下所示:"<<endl;
for(int i=0; i<G.numVertex; i++)
{
cout<<G.adjList[i].data; //先输出顶点信息
EdgeNode * e = G.adjList[i].firstedge;
while(e) //然后就开始遍历输出每个边表所存储的邻接点的下标
{
cout<<"-->"<<e->adjvex;
e=e->next;
}
cout<<endl;
}
}
bool DFSvisited[50]; //用于深搜的标记数组
bool BFSvisited[50]; //用于广搜的标记数组
void DFS(GraphAdjList G,int i)
{
EdgeNode * p;
DFSvisited[i]=true;
cout<<G.adjList[i].data<<" ";
p=G.adjList[i].firstedge;
while(p)
{
if(!DFSvisited[p->adjvex])
DFS(G,p->adjvex);
p=p->next;
}
}
void DFSTraverse(GraphAdjList G)
{
for(int i=0; i<G.numVertex; i++)
DFSvisited[i]=false;
for(int i=0; i<G.numVertex; i++)
{
if(!DFSvisited[i])
DFS(G,i);
}
}
void BFSTraverse(GraphAdjList G)
{
EdgeNode * p;
queue<int>q;
for(int i=0; i<G.numVertex; i++)
BFSvisited[i]=false;
for(int i=0; i<G.numVertex; i++)
{
if(!BFSvisited[i])
{
BFSvisited[i]=true;
cout<<G.adjList[i].data<<" ";
q.push(i);
while(!q.empty())
{
int count =q.front();
q.pop();
p=G.adjList[count].firstedge;
while(p)
{
if(!BFSvisited[p->adjvex])
{
BFSvisited[p->adjvex]=true;
cout<<G.adjList[p->adjvex].data<<" ";
q.push(p->adjvex);
}
p=p->next;
}
}
}
}
}
int main(){
GraphAdjList G;
CreateGraph(G);
Prin(G);
cout << "BFS:" << endl;
BFSTraverse(G);
cout << endl;
cout << "DFS:" << endl;
DFSTraverse(G);
return 0;
}
测试样例
请输入顶点数和边数,并以空格隔开:
8 9
请输入顶点的信息:
1 2 3 4 5 6 7 8
1 2
1 3
2 4
2 5
4 8
5 8
3 6
3 7
6 7