链式前向星
链式前向星可以说是简化版的邻接表,在做算法题的时候可以很容易的使用
她的存储结构分为两个部分,一个是边表结点,一个是顶点表结点(和邻接表非常类似)
//链式前向星的存储结构
struct edge{
int to; //指向那个顶点
int next; //同起点的下一条边的编号
int weight; //该边的权重
} edges[MAXSIZE];
边表结点中有3个域,to是这个结点指向的那个结点值,next与该边同结点的下一条边的编号(实际上就是edges的下标)
weight是这条边的权重。
edges是一个数组,她的下标就是边的编号,也就是说我们是给边编好号的,一般从0开始编号。
int head[MAXSIZE];
顶点表结点,如果这个顶点在图中的话,那么head值就不为-1而为其第一条边的编号(当然,也就是构造图的时候以该顶点为起点的最后构造的边的编号,这个有点绕)。
加边操作
//加边操作
void addEdge(int st, int ed, int we){
edges[sumE].to = ed;
edges[sumE].weight = we;
edges[sumE].next = head[st];
head[st] = sumE++;
}
加边操作也很简单,to就是边的结束结点,weight就是权重,next为head[st],然后head[st]指向该节点,以便下一条链接或者直接作为遍历时候的第一条边。
遍历操作
链式前向星的遍历操作和书上的伪代码非常像
for(int i=head[v]; i!=-1; i=edges[i].next);
当i==-1的时候就代表已经把从v节点其实的边所对应的结点都遍历完了。
完整代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define MAXSIZE 100
//链式前向星的存储结构
struct edge{
int to; //指向那个顶点
int next; //同起点的下一条边的编号
int weight; //该边的权重
} edges[MAXSIZE];
int head[MAXSIZE];
//将head数组初始化为-1
void InitHead(){
memset(head, -1, sizeof(head));
}
int sumE = 0; //边的不编号,从0开始
//加边操作
void addEdge(int st, int ed, int we){
edges[sumE].to = ed;
edges[sumE].weight = we;
edges[sumE].next = head[st];
head[st] = sumE++;
}
//遍历链式前向星结构
void Traverse(){
for(int i=0; i<MAXSIZE; i++){
if(head[i] != -1){
printf("head[%d]:", i);
for(int j=head[i]; j!=-1; j=edges[j].next){
printf("%d ", edges[j].to);
}
printf("\n");
}
}
}
int visited[MAXSIZE];
//深度优先遍历搜索
void DFS(int);
void DFSTraverse(){
//初始化访问数组
for(int i=0; i<MAXSIZE; i++){
visited[i] = 0;
}
for(int i=0; i<MAXSIZE; i++){
if(head[i] != -1 && visited[i] == 0){
DFS(i);
}
}
}
void DFS(int n){
if(visited[n] == 0){
printf(" %d ", n);
}
visited[n] = 1; //表示访问过了
for(int i=head[n]; i!=-1; i=edges[i].next){
if(!visited[edges[i].to]){
DFS(edges[i].to);
}
}
}
//广度优先搜索
void BFS(int);
void BFSTraverse(){
//初始化访问数组
for(int i=0; i<MAXSIZE; i++){
visited[i] = 0;
}
for(int i=0; i<MAXSIZE; i++){
if(head[i] != -1 && visited[i] == 0){
BFS(i);
}
}
}
void BFS(int n){
queue<int> q;
q.push(n);
if(visited[n] == 0)
printf(" %d ", n);
visited[n] = 1;
while(!q.empty()){
int v = q.front();
q.pop();
for(int i=head[v]; i!=-1; i=edges[i].next){
if(!visited[edges[i].to]){
printf(" %d ", edges[i].to);
visited[edges[i].to] = 1;
q.push(edges[i].to);
}
}
}
}
int main(){
InitHead();
//存图
addEdge(1, 2, 1);
addEdge(1, 3, 1);
addEdge(1, 4, 1);
addEdge(2, 4, 1);
addEdge(2, 5, 1);
//反向再存一遍
addEdge(2, 1, 1);
addEdge(3, 1, 1);
addEdge(4, 1, 1);
addEdge(4, 2, 1);
addEdge(5, 2, 1);
Traverse();
printf("DFS: ");
DFSTraverse();
printf("\nBFS: ");
BFSTraverse();
return 0;
}
测试用的图以及最后的结果