資料結構之圖的關節點和重連通分量
本著業界良心,我感覺這個連結中關於圖的關節點講得很不錯。什麼是關節點?在某圖中,若刪除頂點V以及V相關的邊後,圖的一個連通分量分割為兩個或兩個以上的連通分量,則稱頂點V為該圖的一 個關節點。
如圖所示,圖中有四個關節點A/B/D和G,如頂點B和它的邊被刪除,圖就會被分為3個連通分量A,C,F,L,M,J;G,H,I,K;D,E.一個沒有關節點的連通圖稱為重連通圖,上圖顯然不是重連通圖
利用深度優先搜尋便可以求的圖的關節點,本由此可判別圖是否重連通。
上圖右邊是從頂點A出發深度優先搜尋遍歷所得的深度優先生成樹。對於樹中任一頂點V而言,其孩子節點為鄰接點。由深度優先生成樹可得出兩類關節點的特性:
(1)若生成樹的根有兩棵或兩棵以上的子樹,則此根頂點必為關節點。因為圖中不存在連線不同子樹頂點的邊,若刪除此節點,則樹便成為森林。
(2)若生成樹中某個非葉子頂點V,其某棵子樹的根和子樹中的其他節點均沒有指向V的祖先的回邊,則V為關節點。因為刪去v,則其子樹和圖的其它部分被分割開來
若對圖Graph=(V,{Edge}) 重新定義遍歷時的訪問函式visited,並引入一個新的函式low,則由一次深度優先遍歷便可求得連通圖中存在的所有關節點。
定義visited[v]為深度優先搜尋遍歷連通圖時訪問頂點v 的次序號;定義:
對於某個頂點v,存在孩子結點w 且low[w]≧visited[v],則該頂點v 必為關節點。因為當w 是v 的孩子結點時,low[w]≧visited[v],表明w 及其子孫均無指向v 的祖先的回邊。由定義可知,visited[v]值即為v 在深度優先生成樹的前序序列的序號,只需將DFS 函式中頭兩個語句改為visited[v0]=++count(在DFSTraverse 中設初值count=1)即可;low[v]可由後序遍歷深度優先生成樹求得,而v
在後序序列中的次序和遍歷時退出DFS 函式的次序相同,由此修改深度優先搜尋遍歷的演算法便可得到求關節點的演算法.
程式碼如下(註釋比較詳細了):
/*
* @description:求關節點,關節點的定義;假如刪除頂點v及相關各邊後,將圖的一個
聯通分量分割成兩個或是兩個以上的聯通分量,則頂點v為圖的關節點
* @more:注意根節點的情況是需要單獨處理的,其關節點成立的條件是:
生成樹的根有兩棵或兩顆以上的子樹
因為圖中不存在連線不同子樹的根節點的邊,這樣在遍歷子樹的過程,
會存在有節點子樹是無法遍歷到的,這樣把根節點刪除後,就會把圖分成
森林
*/
void FindArticul(ALGraph G) {
int i,v;
ArcNode *p;
count = 1;
low[0] = visited[0] = 1; //表示鄰接表上0號頂點為生成樹的根
//標誌其他的節點都沒有訪問
for(i = 1; i < G.vexnum ; i++)
visited[i] = FALSE;
p = G.vertices[0].firstarc;
v = p->adjvex;
DFSArticul(G,v); //從第一個鄰接點開始進行查詢
if(count < G.vexnum ) {
//根節點為關節點,輸出
printf("%d,%d\n",0,G.vertices[0].data);
//繼續往下找
while(p->nextarc) {
p = p->nextarc;
v = p->adjvex;
if(visited[v] == 0)
DFSArticul(G,v);
}
}
}
/*
* @descirption:從第v的節點出發深度優先遍歷圖查詢圖的關節點
* @more:注意visited[]現在不再是單純的訪問標誌(0/1)而是1/vexnum-1,
是通過深度優先搜尋遍歷得到的,且在遍歷的過程的中生成樹中
父親節點的總是並孩子節點先遍歷到
而low[]是類似後序遍歷得到的,也就是說孩子節點是先於父親節點
遍歷到的
*/
void DFSArticul(ALGraph G,int v) {
int min,w;
ArcNode *p;
//v是第count訪問的節點
visited[v] = min = ++count;
//對v的每個鄰接點進行遍歷
for(p = G.vertices[v].firstarc ; p ; p = p->nextarc ) {
//w是v的鄰接點
w = p->adjvex;
//w未曾訪問,是v的孩子
if(visited[w] == 0) {
//返回前求得low[w]
DFSArticul(G,w);
/*如果v的孩子節點的low小,說明其還有祖先節點和孩子節點相連,
這也是為什麼上面要先返回low[w]的原因
*/
if(low[w] < min)
min = low[w];
if(low[w] >= visited[v])
printf("%d,%d\n",v,G.vertices[v].data);
}
//w已經訪問過,w是v0在生成樹上的祖先
else if(visited[w] < min)
min = visited[w];
}
/*
v的節點的low為visited[v]/low[w]/visited[k]中最小的
w是頂點v的在深度優先生成樹上的孩子節點
k是頂點v在深度優先生成樹有回邊連線的祖先節點
*/
low[v] = min;
Order_Low[v] = lowcount++; //用於理解
}
貼個測試程式碼:
/*---------------------------------------------------------------------------
* file:ALGraph.c
* date:10-14-2014
* author:[email protected]
* version:1.0
* description:鄰接表實現圖的基本操作及求圖的關節點
----------------------------------------------------------------------------*/
#include <stdio.h>
#include "findarticul.h"
int main() {
int i;
ALGraph G;
//建立圖
CreateGraph(&G);
//深度優先遍歷圖
DFSTraverse(G,PrintElem);
printf("\n");
//求關節點
FindArticul(G);
printf("i G.vertices[i].data visited[i] low[i] Order_Low\n");
for(i = 0; i < G.vexnum ; i++)
printf("%d %d %d %d %d\n",i,G.vertices[i].data,visited[i],low[i],Order_Low[i]);
return 0;
/*
please enter the kind of graph(DG:0,DN:1,UDG:2,UDN:3):2
please the vexnum and arcnum:13,17
please enter the value of each vertex:1,2,3,4,5,6,7,8,9,10,11,12,13
please enter the heads and tails:
1,2
1,3
1,6
1,12
2,3
2,4
2,7
2,8
2,13
4,5
7,8
7,9
7,11
8,11
10,12
10,13
12,13
>>(可以看到2輸出了兩次,這是因為刪除2會將圖分割成三顆樹)
1 2 3 4 5 7 8 11 9 13 10 12 6
6,7
1,2
3,4
1,2
0,1
i G.vertices[i].data visited[i] low[i] Order_Low
0 1 1 1 0
1 2 5 1 9
2 3 12 1 8
3 4 10 5 7
4 5 11 10 6
5 6 13 1 12
6 7 8 5 3
7 8 6 5 5
8 9 9 8 2
9 10 4 2 1
10 11 7 5 4
11 12 2 1 11
12 13 3 1 10
*/
}
完整的原始碼看:GitHub
相關推薦
資料結構之圖的關節點和重連通分量
本著業界良心,我感覺這個連結中關於圖的關節點講得很不錯。什麼是關節點?在某圖中,若刪除頂點V以及V相關的邊後,圖的一個連通分量分割為兩個或兩個以上的連通分量,則稱頂點V為該圖的一 個關節點。
圖之關節點和重連通分量
一、介紹 關節點問題主要是用線上路架設上,一旦關節點損壞,線路網就斷開了。因此為避免這種情況,需要將網做出重連通圖。關節點更像是把圖分成了兩部分,而這兩部分只通過這個關節點連結。顯然如果這個關節點斷了,這兩個子圖就無法再通訊了。 二、演算法 基於深
圖->連通性->關節點和重連通分量
文字描述 相關定義:假若在刪去頂點v以及和v相關聯的各邊之後,將圖的一個連通分量分割成兩個或兩個以上的連通分量,則稱頂點v為該圖的一個關節點.一個沒有關節點的連通圖稱為重連通圖. 在重連通圖上,任意一對頂點之間至少存在兩條路徑, 則在刪去某個頂點以及依附於該頂點的各邊時也不破壞圖的連通性.若在連通圖上至
資料結構之圖篇(2):圖的基本操作 深度和廣度遍歷
程式碼實現 main.cpp(主函式) #include <iostream> #include "CMap.h" using namespace std; /** 圖的的儲存:鄰接矩陣 圖的遍歷:深度+廣度 A / \
資料結構之圖的深度優先遍歷和廣度優先遍歷
1.圖的簡單介紹 上圖就是一個圖(無線圖),由頂點和連線組成 圖可以分為無向圖和有向圖(這個又有出度、入度的概念)、網,一般來說圖有兩種常用的表示方式,鄰接矩陣(用二維陣列的形式表示)和鄰接表(主要是陣列+連結串列的形式表示),圖常用的遍歷方式有深度優先遍歷(DFS)和廣
資料結構之圖的遍歷和部分性質
無向圖和有向圖 1、無向圖中,任意兩個頂點之間都存在邊的話,就是無向完全圖。 含有n個頂點的無向完全圖有n×(n−1)2條邊。 有向圖中,若任意兩個頂點之間都存在方向互為相反的有向邊,則就是有向完全圖。 含有n個頂點的有向完全圖有n×(
資料結構之圖(鄰接表儲存,DFS和BFS遍歷)
來看下面的一個簡單的圖, 那麼這樣的一個圖,我們應該用什麼儲存結構來儲存它呢?常用的是鄰接矩陣和鄰接表,這裡鄰接矩陣不做講解,如下所有程式碼都是以鄰接表作為儲存結構,所以這裡就只講解下鄰接表。那麼什麼是鄰接表呢?如何構造呢? 鄰接表是一
資料結構之圖的關鍵路徑
title: 資料結構之圖的關鍵路徑 tags: 資料結構與演算法之美 一、AOE和AOV網 1.AOE網 AOE-網:指用邊表示活動的網,是一個帶權的有向無環圖,其中,頂點表示事件弧表示活動,權表示活動持續的時間,通常一個AOE-網可用來估算工程的完成時間。 2.AOV網 指用頂點表示活動
資料結構之圖(帶權圖 迪傑斯特拉演算法)
// 主要思想是: 每次尋找最小的邊 這樣的話從上一個節點 到這個節點的值 是最小的 當找到最小的邊時,把final[v] = true 表示從原點到這個節點的最小值 已經找到了 <!DOCTYPE html> <html> &l
資料結構之圖(鄰接表 稀疏圖)
<!DOCTYPE html> <html> <head> <title>鄰接表</title> <meta charset="utf-8">
資料結構之圖的最小生成樹
我們把構造連通網的最小代價生成樹稱為最小生成樹,找連通網的最小生成樹,經典的有兩種演算法:普里姆演算法(Prim)和克魯斯卡爾演算法(Kruskal)。 普里姆演算法 有如下鄰接矩陣,9個頂點,左側數字為行號,INFINITY為極大值65535,MAXVEX為頂點個數最大值,此處
資料結構之圖的遍歷
圖的遍歷是和樹的遍歷類似,我們希望從圖中某一點出發訪問圖中其餘頂點,且使每一個頂點僅被訪問一次,這一過程就叫做圖的遍歷。 深度優先遍歷 深度優先遍歷,也稱之為深度優先搜尋,簡稱DFS。首先指定一個規則,在沒有碰到重複頂點的情況下,始終向右手邊走,A-B-C-D-E-F,走到F時發
資料結構之圖篇(1):概述
圖的概念 1.有向圖(由節點和方向箭頭構成)無向圖(只有節點,相當於每條連線都是雙向的) 2.出度:頂點的箭頭指出;入度:頂點的箭頭指入; 3.有向圖:弧;無向圖:邊; 5.權值:弧或者邊上的資料 圖的儲存結構 陣列儲存 1.鄰接矩陣(頂點陣列【索引+資料】+鄰接矩
資料結構之圖學習筆記
一、圖的定義: 圖(Graph)是由頂點的有窮非空集合和頂點之間邊的集合組成,通常表示為:G(V,E),其中,G表示一個圖,V表示圖G中頂點的集合,E是圖G中的邊集合。 a.線性表中的資料元素我們稱為元素,樹中資料元素稱為節點,而圖中的
資料結構之圖論之鄰接表
還是插入一段程式碼來解釋鄰接表的建立過程。 //自己建立一個鄰接表 //邊表結點 typedef struct { int adjvex;//該邊的頭結點 int weight;//權值 EdgeNode *next;//該邊尾結點的下一條邊 }EdgeNo
資料結構之圖論之深度搜索之八皇后
//八皇后問題 #include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> using namespace std; int a[100],coun
python資料結構之串——概述和基本演算法
概述: 字串(string)簡稱串,也是一種線性結構。在python中和array差不多,因為py的陣列也可以包括各種字元(在C/Java一類的語法中,陣列必須是同一種資料型別的元素)。線性結構,有限序列,是主要特點。串其中可以包含各種元素,也是計算機主要處理的一類物件。因
資料結構之圖
1.圖的定義 圖(graph)是由一些點(vertex)和這些點之間的連線(edge)所組成的;其中,點通常稱為頂點(vertex),而點到點之間的連線通常稱之為邊或者弧(edge)。通常記為G=(V,E)。 2.圖的分類 圖通常分為有向圖和無向圖,而其表示表示方式
資料結構之圖(圖的基本操作)
由於圖的基本操作的程式碼較多,我放到這一章來寫。圖可以用兩種方法來儲存,但是本人偏愛連結串列的表示方法,所以以下程式碼也都是是基於鄰接連結串列的儲存方式。 1 /* 2 以下儲存結構參考嚴蔚敏版資料結構,不懂的可以翻閱檢視 3 */ 4 const int UNDIGR
資料結構之圖(圖的簡介)
圖的定義: 一個圖G = (V,E)由頂點(vertex)集 V 合邊(edge)集 E 組成。每條邊(v,w)就是一個點對,其中v,w ∈ V。有時也把邊稱作弧。如果點對是有序的,那麼圖就叫做有向圖。頂點 v 和 w 領接邊 (v,w) ∈ E。在一個具有邊(