基於鄰接表建圖的幾種方法


 最近做圖的題比較多,除了克魯斯卡爾和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;                         // 鄰接表結構體

 

其實有種簡潔且高效的表示形式:

 

 

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++;

 

上面這段代碼中,邊的結構體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...
}

 

其實,對於哈希表這類的存儲結構(鏈表法解決沖突),與圖的鄰接表類似,也可以用類似的表示方法:

 

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..
}

 

轉載自:http://yzmduncan.iteye.com/blog/883903


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM