1. 程式人生 > >圖----資料結構圖論總結(四)

圖----資料結構圖論總結(四)

文章都是摘錄的網路中比較好的程式碼,因為圖的四種儲存方式中有兩種方式(鄰接矩陣和連線表)普通書上都有以此建立圖的程式碼,所以在此不在累贅列出

*******************************************************************************

建立無向圖的鄰接多重表

題目:編寫一個演算法由依次輸入的頂點數目,邊的數目,各頂點的資訊和各條邊的資訊建立無向圖的鄰接多重表。

一.   需求分析

  這裡需要兩個主要字函式,一個是建立圖,另一個是列印圖。

二.   概要設計

首先是建立兩個結點,一個是邊結點,另一個是頂點結點,分別為struct Edge,struct Node,然後建立圖,Create_ML_Graph(int Vertex1,NextEdge New),緊接著是列印Print_ML_Graph(struct Node *Head)。

三.   詳細設計

#include <stdlib.h>

#include <stdio.h>

#define VertexNum  6

struct Edge

{int Marked;

 int Vertex1;

 int Vertex2;

 struct Edge *Edge1;

 struct Edge *Edge2;

};

 typedef struct Edge *NextEdge;

 struct Node

{int Vertex;

 struct Edge *Next;

};

 typedef struct Node *Graph;

 struct Node Head[VertexNum];

 void Create_ML_Graph(int Vertex1,NextEdge New)

{NextEdge Pointer;

 NextEdge Previous;

 Previous=NULL;

 Pointer=Head[Vertex1].Next;

 while(Pointer!=NULL)

{Previous=Pointer;

 if (Pointer->Vertex1==Vertex1)

 Pointer=Pointer->Edge1;

 else  Pointer=Pointer->Edge2;

 }

 if(Previous==NULL)

 Head[Vertex1].Next=New;

 else if(Previous->Vertex1==Vertex1)

 Previous->Edge1=New;

 else Previous->Edge2=New;

 }

 void Print_ML_Graph(struct Node *Head)

{NextEdge Pointer;

 Pointer=Head->Next;

 while(    Pointer!=NULL)

{printf("(%d,%d)",Pointer->Vertex1,Pointer->Vertex2);

 if(Head->Vertex==Pointer->Vertex1)

 Pointer=Pointer->Edge1;

 else if(Head->Vertex==Pointer->Vertex2)

 Pointer=Pointer->Edge2;

 }

 printf("/n");

}

void main()

{int Source;

 int Destinition;

 NextEdge New;

 int i;

 for(i=0;i<VertexNum;i++)

 {Head[i].Vertex=i;

  Head[i].Next=NULL;}

  while(1)

 {printf("Please input the Edge's source:");

 scanf("%d",&Source);

 if(Source==-1) break;

 printf("Please input the Edge's Destinition:");

 scanf("%d",&Destinition);

 if(Source>=VertexNum||Destinition>=VertexNum)

 printf("@[email protected]:out of range!!/n");

 else

 { New=(NextEdge) malloc(sizeof(struct Edge));

  if(New!=NULL)

 {New->Vertex1=Source;

  New->Vertex2=Destinition;

  New->Edge1=NULL;

  New->Edge2=NULL;

  Create_ML_Graph(Source,New);}

  }

 }

 printf("##Graph##/n");

 for(i=0;i<VertexNum;i++)

 {printf("Vertex[%d]:",i);

  Print_ML_Graph(&Head[i]);

  }

 }

四.   除錯分析

  這個題在除錯時,除了常規的變數的定義和指標等錯誤外,主要是指標的值傳不過去,導致列印的時候輸入的圖打印不出來,檢查的時候看各指標是不是傳過去了(用單步執行)。

五.   使用者使用說明

  執行程式時,首先是讓你選擇這時你輸入1回車,這時讓你輸入頭結點數,你可以輸入1或2等(但不能大於6,這裡設的最大值是6),緊接著讓你輸入尾結點,你照樣輸入(不能大於6),這樣反覆輸入幾次也就是幾條邊後回車,就可以看結果。

六.   測試結果

  依次輸入1,2,1,3,2,4,回車

可以看到 <1,2><1,3><2,4>

*************************************************************

有向圖的十字連結串列儲存結構

/**
說明:有向圖的十字連結串列儲存結構,同時編寫了以下函式
        1:建立十字連結串列的函式
        2:輸出有向圖包括頂點和弧
        3:計算頂點的入度和出度
        4:深度優先遍歷有向圖
*/
#include <stdio.h>
#include <malloc.h>
#define OK 1
#define MAX 100

typedef char ElemType ;

typedef struct arcNode{                 //定義有向圖的弧結點
    int tailvex, headvex;                    //弧尾和弧頭在圖中的位置
    struct arcNode *hlink,*tlink;
}ArcNode;

typedef struct vexNode{                    //定義頂點結點
    ElemType data;
    ArcNode *firstin,*firstout;
}VexNode;

typedef struct olgraph{                    //定義有向圖的十字連結串列
    VexNode xlist[MAX];
    int vexnum,arcnum;
}OLGraph;

ArcNode *ptr[MAX];                                        //定義訪問圖的輔助向量
int visited[MAX];                                            //定義頂點訪問標誌

int locateVex(OLGraph *g, ElemType a)
{    int s;
    for(s=0;s<g->vexnum;s++)
        if(g->xlist[s].data==a)        return s;
    return -1;                                        //未找到則返回-1
}

void create(OLGraph *G)
{    int i,j,k;
    ElemType v1,v2,v,vv;
    ArcNode *p;
    printf("/n/n/n/n*********** begin of creating *******************");
    printf("/ninput number of vnum,arcnum:");
    scanf("%d,%d",&G->vexnum,&G->arcnum);
    printf("/ninput data of vex:/n");
    for(i=0;i<G->vexnum;i++)
    {    scanf("%*c%c",&v);                //輸入圖中頂點
        G->xlist.data=v;
        G->xlist.firstin=NULL;        //初始化以頂點為弧頭和弧尾的連結串列
        G->xlist.firstout=NULL;
    }
    printf("/n/ninput data of edge(v1v2)/n");
    for(k=0;k<G->arcnum;k++)            //輸入圖中的弧
    { scanf("%*c%c%c",&v1,&v2);
        i=locateVex(G,v1);
        j=locateVex(G,v2);
        p=(ArcNode *)malloc(sizeof(ArcNode));
        p->tailvex=i;p->headvex=j;

        p->hlink=G->xlist[j].firstin;
        p->tlink=G->xlist.firstout;
        G->xlist[j].firstin=G->xlist.firstout=p;
    }
    printf("*********** end of creating *******************");
    //return G;
}

void printGraph(OLGraph *g)
{    ArcNode *p;
    int i;
    printf("/n/nthe edges are:");
    for(i=0; i<g->vexnum; i++)            //輸出圖中的弧
    { p=g->xlist.firstout; printf("/n  %c:",g->xlist.data);
        while(p!=NULL)
        { printf("    %c----->%c",g->xlist.data, g->xlist[p->headvex].data);
            p=p->tlink;
        }
    }
}

int outNumNode(ArcNode *p)                //計算弧尾相同連結串列的結點數
{    int n=0;
    while (p!=NULL) { n++; p=p->tlink; }
    return n;
}

int inNumNode(ArcNode *p)                    //計算弧頭相同連結串列的結點數
{    int n=0;
    while (p!=NULL) { n++; p=p->hlink; }
    return n;
}

int outDegree(OLGraph *g, ElemType a)//計算某結點的出度
{    int i, outNumber=0;
    outNumber=outNumNode(g->xlist[locateVex(g,a)].firstout);
    return outNumber;
}

int inDegree(OLGraph *g, ElemType a)//計算某結點的入度
{    int i, inNumber=0;
    inNumber=inNumNode(g->xlist[locateVex(g,a)].firstin);
    return inNumber;
}

void printDegree(OLGraph *g)                //輸出結點的度數
{    int i;
    printf("/n/nthe outDegree of vexs are:");
    for(i=0; i<g->vexnum; i++)
    {    printf("/n  %c: %d",g->xlist.data, outDegree(g,g->xlist.data));    }

    printf("/n/nthe inDegree of vexs are:");
    for(i=0; i<g->vexnum; i++)
    {    printf("/n  %c: %d",g->xlist.data, inDegree(g,g->xlist.data));    }
}

void dfs(OLGraph *g, int indexV)                //以某頂點出發深度優先遍歷圖
{ int w;
    printf("%4c", g->xlist[indexV].data);
    visited[indexV]=1;                             // 訪問此結點,並設定標誌
    while (ptr[indexV]!=NULL)
    {    w= ptr[indexV]->headvex;          //取結點的鄰接頂點w
        if( visited[w]==0 ) dfs(g, w);
        ptr[indexV]=ptr[indexV]->tlink;                      // 記住頂點v 的鄰接頂點位置,
    }                                        //  該鄰接點在w之後
}

void depthFirst(OLGraph *g)                            //深度優先遍歷圖
{ int i;
    for (i=0; i<g->vexnum; i++)
    {    ptr=g->xlist.firstout;                //每個頂點連結串列的第一個結點的地址
        visited=0;                          //給每個結點一個未訪問標記
    }
    printf("/n/nthe traverse of depthFirst are:");
    for(i=0; i<g->vexnum; i++)                                    //呼叫以頂點vi為出發點的深度優先遍歷圖G的演算法
        if (visited == 0) dfs(g,i);
    printf("/nthe end of traverse");
}

void main()
{ OLGraph g;
    create(&g);
    printGraph(&g);
    printDegree(&g);
    depthFirst(&g);
}

相關推薦

----資料結構總結()

文章都是摘錄的網路中比較好的程式碼,因為圖的四種儲存方式中有兩種方式(鄰接矩陣和連線表)普通書上都有以此建立圖的程式碼,所以在此不在累贅列出 *******************************************************************

資料結構——(java)

一.基本概念 1、頂點(vertex) 表示某個事物或物件。由於圖的術語沒有標準化,因此,稱頂點為點、節點、結點、端點等都是可以的。 2、邊(edge) 通俗點理解就是兩個點相連組合成一條邊,表示事物與事物之間的關係。需要注意的是邊表示的是頂點之間的邏輯關係,粗細長短都無所謂的。包括

資料結構--

目錄 一、圖的基本知識 二、圖的儲存結構 (1)鄰接矩陣 (2)鄰接表 三、圖的遍歷方式 (1)DFS(Deep First Search 深度優先搜尋) (2)BFS(Breadth First Search 寬度優先搜尋&廣度優先搜尋)

資料結構--知識點總結

一、基本術語 圖(graph):圖是由頂點的有窮非空集合和頂點之間邊的集合組成,通常表示為:G(V,E),其中,G表示一個圖,V是圖G中的頂點的集合,E是圖G中邊的集合。 頂點(Vertex):圖中的資料元素。線性表中我們把資料元素叫元素,樹中將資料元素叫結點。 邊:頂點之間的邏輯關係用邊來表示,邊集可

資料結構 中求單源最短路徑實現 純程式碼

如下有向圖 求出單源起點A到所有其他節點的最短路徑 完整程式碼: #include <stdio.h> #include <memory.h> //圖論的迪傑斯特拉演算法 #define FINITY 200 #define M 20 //單源點頂點到其他

資料結構------知識點總結

轉自:https://blog.csdn.net/Ontheroad_/article/details/72739380圖的儲存結構1.鄰接矩陣:兩個陣列,一個數組儲存“頂點集”,一個數組儲存“邊集”。無向圖中:有向圖中:2.鄰接表:陣列與連結串列相結合的儲存方法。對於帶權值

資料結構學習筆記(之鄰接表實現深度優先遍歷

一下是使用鄰接表儲存表示,實現圖的深度優先遍歷的示例。 用於遍歷的有向圖如下: #include<iostream> #define MaxVertexNum 6 using namespace std; //抽象資料型別 typedef c

演算法資料結構 | 基礎演算法——拓撲排序

今天是演算法和資料結構專題的第32篇文章,我們來聊聊拓撲排序的問題。 拓撲排序是圖論當中一個非常簡單也非常常用的演算法,它有很多的功能。它可以用來檢測有向圖當中是否存在環,也可以用來解決存在依賴的排程問題。下面我們就來看看這個演算法的廬山真面目吧。 演算法場景 拓撲排序是英文音譯,它的英文原文是Topol

資料結構 的深度優先遍歷 C

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

大話資料結構--的最小生成樹-java實現

普利姆(Prim)演算法 最小生成樹 * A * / | \ * B- -F- -E * \ / \ / * C -- D * A B C D E F * 0 1 2 3 4 5 * * A-B 6 A-

大話資料結構--的遍歷-java實現

圖的遍歷分為深度優先遍歷和廣度優先遍歷 總結下圖的遍歷: 深度優先遍歷 就像一棵樹的前序遍歷 A B C D E F G H A 1 1 B 1 1 1 C 1 1 1

資料結構——(2)——的儲存和表示方式.md

圖的儲存方式 在實踐中,圖最常見的策略是: 將每個節點的連線儲存在鄰接列表中。 將整個圖形的連線儲存在鄰接矩陣中。 用鄰接連結串列來表示圖之間的關係 在圖中表示連線的最簡單方法是在每個節點的資料結構中儲存與其連線的節點的列表。該結構稱為鄰接列表。 例如

資料結構——(3)——深度優先搜尋演算法(DFS)思想

圖的遍歷 圖由頂點及其邊組成,圖的遍歷主要分為兩種: 遍歷所有頂點 遍歷所有邊 我們只討論第一種情況,即不重複的列出所有的頂點,主要有兩種策略:深度優先搜尋(DFS),廣度優先搜尋(BFS) 為了使深度和廣度優先搜尋的實現演算法的機制更容易理解,假設提

資料結構——(1)——的簡單介紹

圖的簡介 我們先回顧一下之前介紹的樹的概念,在樹的定義中,每個節點只能有一個父類,並且樹中不能出現有環形。但是你可曾想過,當一棵樹沒有任何規則的時候,會發生什麼嗎? 現在,我們給圖(graph)下一個定義: 圖,是一種用節點和邊來表示相互關係的數學模型。(A graph is a

資料結構——(7)——最短路徑與Dijkstra's Algorithm

帶權圖 在圖中,給每一條路徑帶上一定的權重,這樣的圖我們稱為帶權圖。如下圖所示: 我們現在來回顧一下BFS跟DFS的基本思想: 深度優先搜尋:繼續沿著路徑搜尋,直到我們需要回溯,但這種方式不保證最短路徑。 廣度優先搜尋:檢視包含距離1的鄰居,然後是距離2的鄰

資料結構——(6)——深入分析BFS演算法

DFS的不足和BFS演算法 雖然我們知道根據DFS演算法我們可以找到所有的,由起始節點到目標節點的所有路徑,但並不代表那條路是最短的或者是最佳的。就像我們上篇文章所說的一樣,對於同一幅圖,非遞迴演算法找到的路徑就明顯比遞迴演算法找的要短。 回顧我們之前提到的BFS的基本思想:從起始頂

資料結構——(5)——深入分析DFS演算法

對DFS的過程分析 在前面的文章中我們提到了這樣的一幅圖: 我們知道,在DFS中,我們採用的是遞迴的方式進行實現的,並且給每一個遍歷過的點都做上了標記,目的是為了防止程式進入死迴圈。(為什麼樹可以不需要呢?因為樹沒有環) 利用之前專欄提到的遞迴模式,我們可以寫出下面的虛擬碼:

資料結構——(4)——廣度優先搜尋(BFS)演算法思想

廣度優先搜尋 儘管深度優先搜尋具有許多重要用途,但該策略也具有不適合某些應用程式的缺點。 深度優先方法的最大問題在於它從其中一個鄰居出發,在它返回該節點或者是訪問其他鄰居之前,它必須訪問完從出發節點開始的整個路徑。 如果我們嘗試在一個大的圖中發現兩個節點之間的最短路徑,則使用深度優先

資料結構——(9)——拓撲排序與DFS

DAG圖與AOV網 一個無環的有向圖稱為有向無環圖(DAG)。圖的頂點可以表示要執行的任務,並且邊可以表示一個任務必須在另一個之前執行的約束; 在這個應用程式中,拓撲排序只是任務的有效序列。 當且僅當圖形沒有有向迴圈時,即如果它是有向無環圖(DAG),則可以進行拓撲排序。 任何DAG

資料結構——(8)——最小生成樹(MST)

問題的提出 如下圖,假設這裡有一系列的房屋,問如何鋪設電線,可以使得連線所有房屋的電線的總成本最低?這是20世紀20年代早期研究最小生長樹的最初動機。 (捷克數學家OtakarBorůvka完成的工作)。 最短路徑樹與最小生成樹(MST) 上次,我們看到了Dijkstra演