對於稀疏圖來說,M要遠遠小於N2。
先上數據。例如以下。
1
2
3
4
5
6
|
4 5
1 4 9
4 3 8
1 2 5
2 4 6
1 3 7
|
n表示頂點個數(頂點編號為1~n),m表示邊的條數。接下來m行表示,每行有3個數x y z。表示頂點x到頂點y的邊的權值為z。下圖就是一種使用鏈表來實現鄰接表的方法。
這里我將為大家介紹另一種使用數組來實現的鄰接表,這是一種在實際應用中很easy實現的方法。這樣的方法為每一個頂點i(i從1~n)也都保存了一個類似“鏈表”的東西。里面保存的是從頂點i出發的全部的邊,詳細例如以下。
比方第一條邊“1 4 9”的編號就是1,“1 3 7”這條邊的編號是5。
同一時候為這條邊賦予一個編號,由於這條邊是最先讀入的,存儲在u、v和w數組下標為1的單元格中,因此編號就是1。這條邊的起始點是1號頂點。因此將first[1]的值設為1。
這條邊的起始頂點是4號頂點,因此將first[4]的值設為2。另外這條“編號為2的邊”是我們發現以4號頂點為起始點的第一條邊,所以將next[2]的值設為-1。
next[i]存儲的是“編號為i的邊”的“前一條邊”的編號。
另外這條“編號為4的邊”是我們發現以2號頂點為起始點的第一條邊。所以將next[4]的值設為-1。
由於在為每一個頂點插入邊的時候都直接插入“鏈表”的首部而不是尾部。只是這並不會產生不論什么問題。這正是這樣的方法的其妙之處。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
int
n,m,i;
//u、v和w的數組大小要依據實際情況來設置,要比m的最大值要大1
int
u[6],v[6],w[6];
//first和next的數組大小要依據實際情況來設置,要比n的最大值要大1
int
first[5],next[5];
scanf
(
"%d %d"
,&n,&m);
//初始化first數組下標1~n的值為-1,表示1~n頂點臨時都沒有邊
for
(i=1;i<=n;i++)
first[i]=-1;
for
(i=1;i<=m;i++)
{
scanf
(
"%d %d %d"
,&u[i],&v[i],&w[i]);
//讀入每一條邊
//以下兩句是關鍵啦
next[i]=first[u[i]];
first[u[i]]=i;
}
|
請看下圖:
1
2
3
4
5
6
|
k=first[1];
// 1號頂點當中的一條邊的編號(事實上也是最后讀入的邊)
while
(k!=-1)
//其余的邊都能夠在next數組中依次找到
{
printf
(
"%d %d %d\n"
,u[k],v[k],w[k]);
k=next[k];
}
|
1
2
3
4
5
6
7
8
9
|
for
(i=1;i<=n;i++)
{
k=first[i];
while
(k!=-1)
{
printf
(
"%d %d %d\n"
,u[k],v[k],w[k]);
k=next[k];
}
}
|
因此稀疏圖選用鄰接表來存儲要比鄰接矩陣來存儲要好非常多。