一、首先是图的存储和表示:
1.图的邻接矩阵表示:使用二维数组map[N][N]可表示图,map[u][v]的内容是一个标志。因为c语言中没有bool的类型,只有int的类型,所以在c中当值为1的时候,表示u和v两个点之间有边,当为0的时候表示两个点之间没有边。在c++中用bool表示,当为false的时候表示没有边,当为true的时候表示有边。
2.图的邻接表表示:用c++中的vector,是一个能够存放任意数据类型的动态数组,可以增加和压缩数据。具体函数为:
函数 | 表述 |
c.assign(beg,end) c.assign(n,elem) | 将[beg; end)区间中的数据赋值给c。 将n个elem的拷贝赋值给c。 |
c.at(idx) | 传回索引idx所指的数据,如果idx越界,抛出out_of_range。 |
c.back() | 传回最后一个数据,不检查这个数据是否存在。 |
c.begin() | 传回迭代器重的可一个数据。 |
c.capacity() | 返回容器中数据个数。 |
c.clear() | 移除容器中所有数据。 |
c.empty() | 判断容器是否为空。 |
c.end() | 指向迭代器中的最后一个数据地址。 |
c.erase(pos) c.erase(beg,end) | 删除pos位置的数据,传回下一个数据的位置。 删除[beg,end)区间的数据,传回下一个数据的位置。 |
c.front() | 传回第一个数据。 |
get_allocator | 使用构造函数返回一个拷贝。 |
c.insert(pos,elem) c.insert(pos,n,elem) c.insert(pos,beg,end) | 在pos位置插入一个elem拷贝,传回新数据位置。 在pos位置插入n个elem数据。无返回值。 在pos位置插入在[beg,end)区间的数据。无返回值。 |
c.max_size() | 返回容器中最大数据的数量。 |
c.pop_back() | 删除最后一个数据。 |
c.push_back(elem) | 在尾部加入一个数据。 |
c.rbegin() | 传回一个逆向队列的第一个数据。 |
c.rend() | 传回一个逆向队列的最后一个数据的下一个位置。 |
c.resize(num) | 重新指定队列的长度。 |
c.reserve() | 保留适当的容量。 |
c.size() | 返回容器中实际数据的个数。 |
c1.swap(c2) swap(c1,c2) | 将c1和c2元素互换。 同上操作。 |
vector<Elem> c vector <Elem> c1(c2) vector <Elem> c(n) vector <Elem> c(n, elem) vector <Elem> c(beg,end) c.~ vector <Elem>() | 创建一个空的vector。 复制一个vector。 创建一个vector,含有n个数据,数据均已缺省构造产生。 创建一个含有n个elem拷贝的vector。 创建一个以[beg;end)区间的vector。 销毁所有数据,释放内存。 |
Vector操作
函数 | 描述 |
operator[] | 返回容器中指定位置的一个引用。 |
//用vector方法创建邻接表式的数组
vector<int> v;
v.push_back(1);
v.push_back(1);
v.push_back(13);
v.push_back(14);
for(i = 0;i < v.size();i++)
{
printf("%d",v[i];
}
二、图的遍历
图的遍历分为两种,深度优先(Depth-first-search)和广度优先(Breath-first-search)
1.深度优先(dfs)
dfs是从图中某一个结点出发,依次访问与之相通的没有被访问过的结点,直到图中与之相同的点都被访问到。若还有没有被访问到的点,则另选一个未被访问过的点,继续按照此过程深度遍历图,直到所有的结点都被访问到。
下面是深度优先的代码:
void dfs(int u)
{
printf("%d",u); //从未被访问的结点开始访问,并将其标记为已经被访问过
vis[u] = 1;
for(i= 1; i <= n;i++) //依次深度优先访问与当前顶点邻接的但没有被访问过的点
if(vis[i] == 0 && map[u][i] == 1)
dfs(i);
}
下面是dfs的应用
(1)判断图是否连通,计算连通分量的个数:
若一个图是连通的,有n个顶点,则从图的一个顶点出发进行深度优先遍历,所经过的顶点一定是n个。即对顶点为1-n的图,dfs(1)所访问的结点数一定是n个,用计数器ans作为所访问的次数,若ans为n,则一定是连通图。具体代码如下:
for(int i = 1;i <= n;i++)
if(vis[i] == 0)
{
ans++;
dfs(i);
}
(2)欧拉(回)路问题:
欧拉路:从无向图的一个结点出发走一条道路,每条边恰好经过一次,这样的道路就会称为欧拉路。
欧拉回路:从图中的一个点开始,可以经过图中的每条边并回到最初的位置。
欧拉道路的判断方法:如果一个图是连通的,且该图最多有两个奇点(度数为奇数),则一定存在欧拉道路。
有欧拉回路所必须满足的条件是:
(1)有向图:保证图是连通图,而且每个节点的入度必须等于出度;
(2)无向图:保证图是连通图,且每个节点的度数必须为偶数(不能为0);
所以要判断欧拉回路和欧拉路,统计每个点的度,连通性可以用dfs判断。