最近做圖的題比較多,除了克魯斯卡爾和floyd,像廣搜,普里姆,Bellman-Ford,迪傑斯特拉,SPFA,拓撲排序等等,都用到圖的鄰接表形式。
數據結構書上表示鄰接表比較復雜,一般形式如下:
typedef
struct Node
{
int dest; // 鄰接邊的弧頭結點序號
int weight; // 權值信息
struct Node *next; // 指向下一條鄰接邊
}Edge; // 單鏈表結點的結構體
typedef struct
{
DataType data; // 結點的一些數據,比如名字
int sorce; // 鄰接邊的弧尾結點序號
Edge *adj; // 鄰接邊頭指針
}AdjHeight; // 數組的數據元素類型的結構體
typedef struct
{
AdjHeight a[MaxVertices]; // 鄰接表數組
int numOfVerts; // 結點個數
int numOfEdges; // 邊個數
}AdjGraph; // 鄰接表結構體
{
int dest; // 鄰接邊的弧頭結點序號
int weight; // 權值信息
struct Node *next; // 指向下一條鄰接邊
}Edge; // 單鏈表結點的結構體
typedef struct
{
DataType data; // 結點的一些數據,比如名字
int sorce; // 鄰接邊的弧尾結點序號
Edge *adj; // 鄰接邊頭指針
}AdjHeight; // 數組的數據元素類型的結構體
typedef struct
{
AdjHeight a[MaxVertices]; // 鄰接表數組
int numOfVerts; // 結點個數
int numOfEdges; // 邊個數
}AdjGraph; // 鄰接表結構體
其實有種簡潔且高效的表示形式:
typedef
struct
{
int to;
int w;
int next;
}Edge;
Edge e[MAX];
int pre[MAX];
// 初始化
memset(pre,- 1, sizeof(pre));
// 輸入
scanf( " %d %d %d ",& from,&to,&w1);
e[i].to = to; e[i].w = w1; e[i].next = pre[ from]; pre[ from] = i;
i++;
{
int to;
int w;
int next;
}Edge;
Edge e[MAX];
int pre[MAX];
// 初始化
memset(pre,- 1, sizeof(pre));
// 輸入
scanf( " %d %d %d ",& from,&to,&w1);
e[i].to = to; e[i].w = w1; e[i].next = pre[ from]; pre[ from] = i;
i++;
上面這段代碼中,邊的結構體Edge由三個元素組成:弧頭結點序號,邊權值,下一條邊的序號。e[i]指的是第i條邊。pre[i]記錄的是從當前輸入的情況來看,序號為i的弧尾結點發出的第一條邊的序號是pre[i]。
這樣,在操作某個結點發出的邊時,可以像這么做:
/*
now為弧尾結點序號,i為now所發出的邊序號,adj為弧頭結點序號,w為now-->adj這條邊的權值
*/
for(i = pre[now]; i != - 1; i = edge[i].next)
{
int adj = edge[i].to;
int w = edge[i].w;
// do something...
}
for(i = pre[now]; i != - 1; i = edge[i].next)
{
int adj = edge[i].to;
int w = edge[i].w;
// do something...
}
其實,對於哈希表這類的存儲結構(鏈表法解決沖突),與圖的鄰接表類似,也可以用類似的表示方法:
typedef
struct
{
char e[ 11]; // value
char f[ 11]; // key
int next; // 下一個結果(hash沖突)
}Entry;
Entry entry[M];
int hashIndex[M]; // 哈希值為M的結果集的第一個在entry中的序號。
// 輸入:對key進行hash,
sscanf(str, " %s %s ",entry[i].e,entry[i].f);
int hash = ELFHash(entry[i].f);
entry[i].next = hashIndex[hash];
hashIndex[hash] = i;
i++;
// 使用:
for( int k = hashIndex[hash]; k; k = entry[k].next)
{
// do something..
}
{
char e[ 11]; // value
char f[ 11]; // key
int next; // 下一個結果(hash沖突)
}Entry;
Entry entry[M];
int hashIndex[M]; // 哈希值為M的結果集的第一個在entry中的序號。
// 輸入:對key進行hash,
sscanf(str, " %s %s ",entry[i].e,entry[i].f);
int hash = ELFHash(entry[i].f);
entry[i].next = hashIndex[hash];
hashIndex[hash] = i;
i++;
// 使用:
for( int k = hashIndex[hash]; k; k = entry[k].next)
{
// do something..
}