您的位置:首页 > 理论基础 > 数据结构算法

数据结构学习笔记(七)--图

2016-04-13 22:29 465 查看
图的存储方式一般分为邻接矩阵与邻接链表。矩阵操作简单,但稀疏图时采用链表效率更高。

图的遍历:DFS(用递归实现) BFS(用队列实现,类似于树的层序遍历!)

注意什么时候使用DFS什么时候使用BFS更好?

**如果估计目标顶点离开起始顶点不会太远,那么选择广度优先遍历是比较合适的,因为广度优先是一种由近及远的搜索策略;

如果估计目标顶点与起始顶点没有太大的关系,那么选择深度优先遍历是比较合适的,深度优先是通过邻接点尽快接近较远目标的搜索策略。

所以,大多数题目还是用广度优先为佳,毕竟深度优先是个递归的程序,而广度优先可以写成循环。

适合用深度的,大概就是上面所说的,已经对目标定点的位置有了模糊的印象,并经判断合适。**

解决实际问题时,有必要每次都把图的结构表示成矩阵或链表吗?其实不必。图只是一个抽象概念,方便我抽象实际问题,有时候世界用一个二维数组表示邻接矩阵就可以完全解决问题了。

如练习中的列出连通子集

#include <cstdio>

#define N 15

void ListComponentsWithDFS();
void ListComponentsWithBFS();
void DFS(int V);
void BFS(int V);
void InitVisit(void);

int n;
bool Visited
;
int G

= {0};

int main()
{
int E;

scanf("%d%d", &n, &E);
for (int i = 0; i < E; i++)
{
int a, b;
scanf("%d%d", &a, &b);
G[b][a] = G[a][b] = 1;
}
ListComponentsWithDFS();
InitVisit();
ListComponentsWithBFS();

return 0;
}

void ListComponentsWithDFS()
{
for (int V = 0; V < n; V++)
if (!Visited[V])
{
printf("{ ");
DFS(V);
printf("}\n");
}
}

void ListComponentsWithBFS()
{
for (int V = 0; V < n; V++)
if (!Visited[V])
{
printf("{ ");
BFS(V);
printf("}\n");
}
}

void DFS(int V)
{
Visited[V] = true;
printf("%d ", V);
for (int i = 0; i < n; i++)
{
if (G[V][i] && !Visited[i])
DFS(i);
}
}

void BFS(int V)
{
const int MAX_SIZE = 100;
int Queue[MAX_SIZE];
int first = -1, last = -1;

Queue[++last] = V;      //入队
Visited[V] = true;
while (first < last)    //当队不为空时
{
int F = Queue[++first];     //出队
printf("%d ", F);
for (int i = 0; i < n; i++)
{
if (G[F][i] && !Visited[i])
{
Queue[++last] = i;      //入队
Visited[i] = true;
}
}
}
}

void InitVisit()
{
for (int i = 0; i < N; i++)
Visited[i] = false;
}


习题:拯救007

利用遍历连通子集的思想。

Saving James Bond - Easy Version

/*拯救007*/
/*by zoe*/
#include <cmath>
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iostream>
#define YES 1
#define NO 0
using namespace std;
struct Point {
int num;
int x;
int y;
Point &operator=(Point P) {
num = P.num;
x = P.x;
y = P.y;
return *this;
}
};

Point M[102][102];
Point P[102];
bool visited[102];
int nu;
// int ne;
int D;

bool Jump(Point P, Point V) {
if (sqrt((P.x - V.x) * (P.x - V.x) + (P.y - V.y) * (P.y - V.y)) < D)
return true;
else
return false;
}

bool FirstCanJump(Point P) {
// printf("judge first can jump:%f\n", sqrt(P.x * P.x + P.y * P.y));
if (sqrt(P.x * P.x + P.y * P.y) < D)
return true;
else
return false;
}

bool IsSafe(Point P) {
if (fabs(P.x - 50) < D || fabs(P.y - 50) < D)
return true;
else
return false;
}

int DFS(Point Pv) {
// printf("DFS start!\n");
int answer;
Point V;
visited[Pv.num] = true;
if (IsSafe(Pv))
answer = YES;
else {
// printf("not the end\n");
for (int i = 0; i < nu; i++) {
V = P[i];
if (!visited[V.num] && Jump(Pv, V)) {
answer = DFS(V);
if (answer == YES)
break;
}
}
}
return answer;
}

void Save007(Point Pv) {

int answer;
for (int i = 0; i < nu; i++) {
Pv = P[i];
if (!visited[Pv.num] && FirstCanJump(Pv)) {
// printf("first can jump\n");
answer = DFS(Pv);
if (answer == YES)
break;
}
// Pv = P[i];
}
if (answer == YES)
printf("Yes\n");
else
printf("No\n");
}

int main() {
int i;

// string S;

cin >> nu >> D;
// cout << nu << " " << D << endl;
if (nu <= 0)
printf("No\n");
for (i = 0; i < nu; i++)
P[i].num = i;

for (i = 0; i < nu; i++) {
scanf("%d%d\n", &P[i].x, &P[i].y);
// cout << i << endl;
// cout << i << " " << P[i].x << " " << P[i].y << endl;
}
for (i = 0; i < nu; i++)
visited[i] = 0;

// cout << 0 << " " << P[0].x << " " << P[0].y << endl;

Save007(P[0]);
/*int i, a[6];
for (i = 0; i < 5; i++)
cin >> a[i];
cout << a[4] << endl;*/
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: