数据结构 - 图
来源:互联网 发布:安卓蓝牙调试助手 源码 编辑:程序博客网 时间:2024/06/04 19:50
邻接矩阵我觉得是非常明了的一种图的表示方法,当然了,其缺点就是,在图的点数多而连接线少的时候,比较浪费资源。
我的邻接矩阵简单代码如下:
int main()
{
cout << "Hello world!" << endl;
int Block[5][5] = \
{
0, 1, 1, 1, 0, \
1, 0, 1, 1, 0, \
1, 1, 0, 0, 1, \
1, 1, 0, 0, 1, \
0, 0, 1, 1, 0 \
};
Graph tmpGph(Block);
tmpGph.DeepSearch();
tmpGph.ResetVisit();
cout << endl;
tmpGph.BFS();
//New Job!!!
// GraphList tmpGphLst;
// int nLineNumbers = 0;
// int nItem, Point;
// cout << "How Many Lines Inside?" << endl;
// cin >> nLineNumbers;
// while(nLineNumbers --)
// {
// cout << "Input Line Point A, B" << endl;
// cin >> nItem >> Point;
// tmpGphLst.AddToListByOrder(nItem, Point);
// }
// tmpGphLst.BFS();
// cout << endl;
return 0;
}
因为遍历的是无向图,所以我做的是一个对称邻接矩阵,其对应的图是这样的:(其中的箭头你就当他不存在吧,无向图哦)
我发现我在写博文题同时,还能提高我的visio绘图能力~不过现在实在不怎么样。一点点练吧。
这样从1点开始进行深度优先遍历,我们很容易就能得出其遍历结果:
1 2 3 5 4
这个结果相信不用我多说吧,具体可以看代码及其运行结果:
int Graph::DeepSearch(int Point)
{
p_nVisitList[Point] = 1;
cout << Point << ends;
for(int i = 0;i < 5;++ i)
{
if(1 == pBlock[Point][i] && 0 == p_nVisitList[i])
{
DeepSearch(i);
}
}
}
就是这样一段简单的代码~其中在函数生命中Point的参数默认为0,其运行结果如下:
其中逐个加1,就对应上了1 2 3 5 4了。
就这么简单。深度优先遍历使用的方法是针对当前的这个点的邻接点进行查找,只要找到了一个未访问的节点,就对这个节点采用同样的方式进行遍历。所以深度优先遍历使用递归是很好的方式,我的那个代码只有13行~
而邻接矩阵的广度优先遍历则是逐层访问,比较适合邻接表来做。邻接矩阵的广度优先遍历方法如下:
void Graph::BFS()
{
p_nVisitList[4] = 1;
cout << 4 << ends;
queue<int> DL;
DL.push(4);
while(!DL.empty())
{
int val = DL.front();
DL.pop();
for(int i = 0;i < 5;++ i)
{
if(1 == pBlock[val][i] && p_nVisitList[i] == 0)
{
cout << i << ends;
p_nVisitList[i] = 1;
DL.push(i);
}
}
}
}
运行结果:
还是一样的图,运行结果就是第二行的结果。你可以自己算一下对不对(BFS遍历的起始点为4,注意下)。
邻接表的广度优先遍历
我觉得,因为邻接表的较为特殊的存储形式,使得其较为适合以广度优先的方式进行遍历。但是需要注意的是,邻接矩阵和邻接表这两种图的存储形式,都能够使用深度优先遍历和广度优先遍历的。
广度优先遍历的思想是逐层访问,每当当前节点的全部相邻节点都被访问完成之后,再访问下一层节点。
我在用邻接表表示的图的类中,专门制作了一个方法用于添加点和点关系的函数。通过这个函数,来实现图的创建。
看下这个类的代码:
class ListNode
{
public:
int val;
int weight;
ListNode * next;
public:
ListNode();
};
ListNode::ListNode():val(0), weight(0), next(NULL)
{
;
}
class GraphList
{
public:
GraphList();
~GraphList();
void AddToListByOrder(int nitem, int Point);
void BFS(int n = 0);//这个广度优先遍历的代码太好写了
private:
int visit[5];
ListNode * Next[5];
};
上面的代码中包含了两个类,一个是邻接表的节点类,另外一个是邻接表本身。代码还是很简单的,而且因为邻接表的特性,使得分层遍历十分方便,看主函数代码结构:
GraphList tmpGphLst;
int nLineNumbers = 0;
int nItem, Point;
cout << "How Many Lines Inside?" << endl;
cin >> nLineNumbers;
while(nLineNumbers --)
{
cout << "Input Line Point A, B" << endl;
cin >> nItem >> Point;
tmpGphLst.AddToListByOrder(nItem, Point);
}
tmpGphLst.BFS();
cout << endl;
在看演示效果:
因为链表采用的是前插法,所以你会看到第二层的遍历结果是3 2 1,反过来的。
很容易发现,在使用邻接表来表示的时候进行广度优先遍历很方便。
图论,我就写这些啦~
最后附上本次的全部代码:
#include <iostream>
#include <queue>
using namespace std;
class Graph
{
private:
//访问控制
int p_nVisitList[5];
int (* pBlock)[5];
public:
Graph(int (*pParam)[5]);
~Graph();
//深度优先遍历
int DeepSearch(int Point = 0);
void BFS();
void ResetVisit();
};
class ListNode
{
public:
int val;
int weight;
ListNode * next;
public:
ListNode();
};
ListNode::ListNode():val(0), weight(0), next(NULL)
{
;
}
class GraphList
{
public:
GraphList();
~GraphList();
void AddToListByOrder(int nitem, int Point);
void BFS(int n = 0);//这个广度优先遍历的代码太好写了
private:
int visit[5];
ListNode * Next[5];
};
void GraphList::AddToListByOrder(int nitem, int Point)//前插法,代码好写
{
if(nitem >= 0 && nitem < 5 && Point >= 0 && Point < 5)
{
ListNode * pnewnode = new ListNode;
if(pnewnode == NULL)
return;
pnewnode->val = Point;
pnewnode->next = Next[nitem];
Next[nitem] = pnewnode;
}
}
void GraphList::BFS(int n)
{
for(int i = 0;i < 5;++ i)
{
if(visit[i] == 0)
{
cout << i << ends;
visit[i] = 1;
}
ListNode * pLNTmp = Next[i];
while(pLNTmp != NULL)
{
if(0 == visit[pLNTmp->val])
{
cout << pLNTmp->val << ends;
visit[pLNTmp->val] = 1;
}
pLNTmp = pLNTmp -> next;
}
}
}
GraphList::GraphList()
{
for(int i = 0;i < 5;++ i)
{
visit[i] = 0;
Next[i] = NULL;
}
}
GraphList::~GraphList()
{
for(int i = 0;i < 5;++ i)
{
ListNode * ptmpLN;
while(Next[i] != NULL)
{
ptmpLN = Next[i]->next;
delete Next[i];
Next[i] = ptmpLN;
}
}
}
void Graph::ResetVisit()
{
for(int i = 0;i < 5;++ i)
{
p_nVisitList[i] = 0;
}
}
Graph::Graph(int (*pParam)[5])
{
for(int i = 0;i < 5;++ i)
p_nVisitList[i] = 0;
pBlock = pParam;
}
Graph::~Graph()
{
;//nothing!
}
int Graph::DeepSearch(int Point)
{
p_nVisitList[Point] = 1;
cout << Point << ends;
for(int i = 0;i < 5;++ i)
{
if(1 == pBlock[Point][i] && 0 == p_nVisitList[i])
{
DeepSearch(i);
}
}
return 0;
}
void Graph::BFS()
{
p_nVisitList[4] = 1;
cout << 4 << ends;
queue<int> DL;
DL.push(4);
while(!DL.empty())
{
int val = DL.front();
DL.pop();
for(int i = 0;i < 5;++ i)
{
if(1 == pBlock[val][i] && p_nVisitList[i] == 0)
{
cout << i << ends;
p_nVisitList[i] = 1;
DL.push(i);
}
}
}
}
int main()
{
cout << "Hello world!" << endl;
int Block[5][5] = \
{
0, 1, 1, 1, 0, \
1, 0, 1, 1, 0, \
1, 1, 0, 0, 1, \
1, 1, 0, 0, 1, \
0, 0, 1, 1, 0 \
};
Graph tmpGph(Block);
tmpGph.DeepSearch();
tmpGph.ResetVisit();
cout << endl;
tmpGph.BFS();
//New Job!!!
GraphList tmpGphLst;
int nLineNumbers = 0;
int nItem, Point;
cout << "How Many Lines Inside?" << endl;
cin >> nLineNumbers;
while(nLineNumbers --)
{
cout << "Input Line Point A, B" << endl;
cin >> nItem >> Point;
tmpGphLst.AddToListByOrder(nItem, Point);
}
tmpGphLst.BFS();
cout << endl;
return 0;
}
- 数据结构---图
- 数据结构-图
- 数据结构:图
- 数据结构--图
- 数据结构----------------【图】 .
- 数据结构--图
- 【数据结构】图
- 数据结构--图
- 数据结构-图
- 数据结构 - 图
- 数据结构:图
- 数据结构-图
- 【数据结构】【图】
- 数据结构 图
- 数据结构 图
- 数据结构-图
- 数据结构 图
- 数据结构:图
- 和为s的连续正数序列
- centos安装jdk环境yum
- 部分手机RadioButton作为Tab键不居中问题
- quick-cocos2d-x基于源码加密打包功能的更新
- JAVA 二叉树遍历
- 数据结构 - 图
- 翻转单词顺序
- 黑马程序员java之反射
- Android ADT 中的项目迁移到 Android Studio出现编码乱码问题
- Hadoop 案例4----平均成绩
- 黑马程序员——总集篇
- mysql安装后配置
- ToggleButton,Switch,RatingBar的使用
- php fgets函数读取多余的空格解决