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

数据结构 - 图

2015-09-05 13:54 337 查看
郝斌版《数据结构》学习笔记时间:2015.08.31-2015.09.05转载自:http://www.cnblogs.com/matrix-r/作者:Matrix_R图的存储结构有简单的两种:1邻接矩阵法2临界表法邻接矩阵我觉得是非常明了的一种图的表示方法,当然了,其缺点就是,在图的点数多而连接线少的时候,比较浪费资源。我的邻接矩阵简单代码如下:
intmain()
{
cout<<"Helloworld!"<<endl;
intBlock[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\
};
GraphtmpGph(Block);
tmpGph.DeepSearch();
tmpGph.ResetVisit();
cout<<endl;
tmpGph.BFS();
//NewJob!!!
//GraphListtmpGphLst;
//intnLineNumbers=0;
//intnItem,Point;
//cout<<"HowManyLinesInside?"<<endl;
//cin>>nLineNumbers;
//while(nLineNumbers--)
//{
//cout<<"InputLinePointA,B"<<endl;
//cin>>nItem>>Point;
//tmpGphLst.AddToListByOrder(nItem,Point);
//}
//tmpGphLst.BFS();
//cout<<endl;
return0;
}
因为遍历的是无向图,所以我做的是一个对称邻接矩阵,其对应的图是这样的:(其中的箭头你就当他不存在吧,无向图哦)  我发现我在写博文题同时,还能提高我的visio绘图能力~不过现在实在不怎么样。一点点练吧。这样从1点开始进行深度优先遍历,我们很容易就能得出其遍历结果:  12354  这个结果相信不用我多说吧,具体可以看代码及其运行结果:
intGraph::DeepSearch(intPoint)
{
p_nVisitList[Point]=1;
cout<<Point<<ends;
for(inti=0;i<5;++i)
{
if(1==pBlock[Point][i]&&0==p_nVisitList[i])
{
DeepSearch(i);
}
}
}
就是这样一段简单的代码~其中在函数生命中Point的参数默认为0,其运行结果如下:其中逐个加1,就对应上了12354了。就这么简单。深度优先遍历使用的方法是针对当前的这个点的邻接点进行查找,只要找到了一个未访问的节点,就对这个节点采用同样的方式进行遍历。所以深度优先遍历使用递归是很好的方式,我的那个代码只有13行~而邻接矩阵的广度优先遍历则是逐层访问,比较适合邻接表来做。邻接矩阵的广度优先遍历方法如下:
voidGraph::BFS()
{
p_nVisitList[4]=1;
cout<<4<<ends;
queue<int>DL;
DL.push(4);
while(!DL.empty())
{
intval=DL.front();
DL.pop();
for(inti=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,注意下)。邻接表的广度优先遍历我觉得,因为邻接表的较为特殊的存储形式,使得其较为适合以广度优先的方式进行遍历。但是需要注意的是,邻接矩阵和邻接表这两种图的存储形式,都能够使用深度优先遍历和广度优先遍历的。广度优先遍历的思想是逐层访问,每当当前节点的全部相邻节点都被访问完成之后,再访问下一层节点。我在用邻接表表示的图的类中,专门制作了一个方法用于添加点和点关系的函数。通过这个函数,来实现图的创建。看下这个类的代码:
classListNode
{
public:
intval;
intweight;
ListNode*next;
public:
ListNode();
};
ListNode::ListNode():val(0),weight(0),next(NULL)
{
;
}
classGraphList
{
public:
GraphList();
~GraphList();
voidAddToListByOrder(intnitem,intPoint);
voidBFS(intn=0);//这个广度优先遍历的代码太好写了
private:
intvisit[5];
ListNode*Next[5];
};
上面的代码中包含了两个类,一个是邻接表的节点类,另外一个是邻接表本身。代码还是很简单的,而且因为邻接表的特性,使得分层遍历十分方便,看主函数代码结构:
GraphListtmpGphLst;
intnLineNumbers=0;
intnItem,Point;
cout<<"HowManyLinesInside?"<<endl;
cin>>nLineNumbers;
while(nLineNumbers--)
{
cout<<"InputLinePointA,B"<<endl;
cin>>nItem>>Point;
tmpGphLst.AddToListByOrder(nItem,Point);
}
tmpGphLst.BFS();
cout<<endl;
在看演示效果:因为链表采用的是前插法,所以你会看到第二层的遍历结果是321,反过来的。很容易发现,在使用邻接表来表示的时候进行广度优先遍历很方便。图论,我就写这些啦~最后附上本次的全部代码:
#include<iostream>
#include<queue>
usingnamespacestd;
classGraph
{
private:
//访问控制
intp_nVisitList[5];
int(*pBlock)[5];
public:
Graph(int(*pParam)[5]);
~Graph();
//深度优先遍历
intDeepSearch(intPoint=0);
voidBFS();
voidResetVisit();
};
classListNode
{
public:
intval;
intweight;
ListNode*next;
public:
ListNode();
};
ListNode::ListNode():val(0),weight(0),next(NULL)
{
;
}
classGraphList
{
public:
GraphList();
~GraphList();
voidAddToListByOrder(intnitem,intPoint);
voidBFS(intn=0);//这个广度优先遍历的代码太好写了
private:
intvisit[5];
ListNode*Next[5];
};
voidGraphList::AddToListByOrder(intnitem,intPoint)//前插法,代码好写
{
if(nitem>=0&&nitem<5&&Point>=0&&Point<5)
{
ListNode*pnewnode=newListNode;
if(pnewnode==NULL)
return;
pnewnode->val=Point;
pnewnode->next=Next[nitem];
Next[nitem]=pnewnode;
}
}
voidGraphList::BFS(intn)
{
for(inti=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(inti=0;i<5;++i)
{
visit[i]=0;
Next[i]=NULL;
}
}
GraphList::~GraphList()
{
for(inti=0;i<5;++i)
{
ListNode*ptmpLN;
while(Next[i]!=NULL)
{
ptmpLN=Next[i]->next;
deleteNext[i];
Next[i]=ptmpLN;
}
}
}
voidGraph::ResetVisit()
{
for(inti=0;i<5;++i)
{
p_nVisitList[i]=0;
}
}
Graph::Graph(int(*pParam)[5])
{
for(inti=0;i<5;++i)
p_nVisitList[i]=0;
pBlock=pParam;
}
Graph::~Graph()
{
;//nothing!
}
intGraph::DeepSearch(intPoint)
{
p_nVisitList[Point]=1;
cout<<Point<<ends;
for(inti=0;i<5;++i)
{
if(1==pBlock[Point][i]&&0==p_nVisitList[i])
{
DeepSearch(i);
}
}
return0;
}
voidGraph::BFS()
{
p_nVisitList[4]=1;
cout<<4<<ends;
queue<int>DL;
DL.push(4);
while(!DL.empty())
{
intval=DL.front();
DL.pop();
for(inti=0;i<5;++i)
{
if(1==pBlock[val][i]&&p_nVisitList[i]==0)
{
cout<<i<<ends;
p_nVisitList[i]=1;
DL.push(i);
}
}
}
}
intmain()
{
cout<<"Helloworld!"<<endl;
intBlock[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\
};
GraphtmpGph(Block);
tmpGph.DeepSearch();
tmpGph.ResetVisit();
cout<<endl;
tmpGph.BFS();
//NewJob!!!
GraphListtmpGphLst;
intnLineNumbers=0;
intnItem,Point;
cout<<"HowManyLinesInside?"<<endl;
cin>>nLineNumbers;
while(nLineNumbers--)
{
cout<<"InputLinePointA,B"<<endl;
cin>>nItem>>Point;
tmpGphLst.AddToListByOrder(nItem,Point);
}
tmpGphLst.BFS();
cout<<endl;
return0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: