java用十字链表实现无向图_实验四:图的实现与应用
20162317袁逸灝 實驗四:圖的實現與應用
實驗內容
用
鄰接矩陣
十字鏈表
實現無向圖中的
添加結點
刪除結點
添加邊
刪除邊
size()
isEmpty()
廣度優先迭代器
深度優先迭代器
方法
實驗要求
實驗1:用鄰接矩陣實現無向圖(邊和頂點都要保存),實現在包含添加和刪除結點的方法,添加和刪除邊的方法,size(),isEmpty(),廣度優先迭代器,深度優先迭代器
給出偽代碼,產品代碼,測試代碼(不少于5條測試)
上方提交代碼鏈接
附件提交測試截圖
實驗2:用十字鏈表實現無向圖(邊和頂點都要保存),實現在包含添加和刪除結點的方法,添加和刪除邊的方法,size(),isEmpty(),廣度優先迭代器,深度優先迭代器
給出偽代碼,產品代碼,測試代碼(不少于5條測試)
上方提交代碼鏈接
附件提交測試截圖
實驗3:實現PP19.9
給出偽代碼,產品代碼,測試代碼(不少于5條測試)
上方提交代碼鏈接
附件提交測試截圖
實驗過程
實驗1
鄰接矩陣是存儲圖的一種方式,它通過一個矩陣來表示哪些點之間有聯系。主要有兩種表達方式。
方式1:用0和1來表示
在矩陣種,1代表相連接,0代表不相連。
方式2:用權值來表示
當兩點相連的時候,矩陣的位置為權值;若兩點不為鄰接點,矩陣的位置為無窮大。
鄰接矩陣的特點:
無向圖的鄰接矩陣對稱,可壓縮存儲;
無向圖中頂點 vi 的度是鄰接矩陣中第 i 行 1 的個數。
有向圖鄰接矩陣不一定對稱;
有向圖中頂點 vi 的出度是鄰接矩陣中第 i 行 1 的個數。 頂點 vi 的入度是鄰接矩陣中第 i 列 1 的個數。
鄰接矩陣的實現:
初步實現
需要一個邊的類,類中要有三個變量,兩個是頂點變量,一個是邊的權重變量。
要實現保存點的功能,鑒于后面有添加點的方法,因此最好實例化一個List來保存點,這樣可以使長度不受限制。
實現保存邊的功能,鑒于該實驗的要求是使用鄰接矩陣來實現圖的儲存。因此,在保存邊這一方面,需要用一個二維數組來保存,該數組大小為頂點集合的大小。
考慮到后面可能會使用到權值,因此需要一個大小和邊的大小相同的二維數組來保存權值。
方法實現
添加頂點---addVex(T vex)
考慮到List可以動態擴容,而數組不可以。因此要考慮到將數組擴容的辦法。所以需要兩個列表,一個用來暫時承載保存邊的二維數組的數據,一個暫時承載保存權值的二維數組的數據。當添加頂點的時候,先將二維數組中的數據放到對應的點中,通過重新實例化一個二維數組來實現擴容,然后再將數據返還給數組。
遍歷頂點數組,看是否有重復的頂點存在與頂點列表中。若有,返回異常語句(下圖);若沒有,則將頂點加入至頂點集合中。
刪除頂點---removeVex(T vex)
刪除也涉及頂點列表長度的變化,因此對于邊的二維數組和權值二維數組,也需要使用相同的方法進行擴容。
遍歷數組,看是否存在該點,若不存在,返回異常語句(下圖);若存在,將其從點的集合中移除。
添加邊---addEdge(Edge edge)
因為邊類中規定添加的參數有三個,其中兩個是被該邊連接的端點1和端點2。要遍歷頂點數組,查看這兩個頂點是否都存在。若不存在,返回異常語句(下圖);則將這兩個頂點在二維數組中的對應下標位置中的數據從0變為1。
關于存放權值的二維數組,在對應的位置也要更新為對應的權值數據。在橫坐標與縱坐標相等時,即自己等于自己的時候,權值要為0。對于沒有連接的兩個點,要設定的一個較大的數值來表示兩點不相連。(我這里用到的是10000)
刪除邊---removeEdge(Edge edge)
首先要查看目標邊的兩個頂點是否存在于頂點中,不存在就要返回異常語句。若存在,再看目標邊是否存在,若不存在,返回異常語句(下圖)。若存在,將目標邊兩個端點位于邊數組的對應位置的數據要變為0。權值表中對應的位置要變為最大值。
邊/點的數量---Vex/EdgeSize()
對于定點的的大小,直接返回頂點集合的大小即可。
對于邊數量,需要遍歷數組,看哪些位置是1的,然后記錄1的個數,并將這些個數返回
判斷是否為空---isEmpty()
這里主要需要判斷的是一個頂點集合是否為空,因為頂點集合為空,其他邊也不存在。
廣度優先迭代器---BoradTraverse(T StartVex)
初步實現:
隊列實例化
迭代器實例化
訪問數組實例化
主要實現:
將開始遍歷點放進隊列,并標記為已訪問,由于實例化的訪問數組長度和頂點集合的大小一致,所以找到對應點的下標,再在訪問數組中變為true即可。然后將點的連接點輸進隊列中,并將該點從隊列中彈出至迭代器中,然后循環做這步驟。最后迭代器中放的就是廣度優先遍歷的結果。
深度優先迭代器---depthTraverse(T StartVex)
初步實現:
因為深度優先遍歷需要用到遞歸的方法,所以遞歸出來的點的順序需要放在一個方法外的位置中,最后再把列表給打印出來。因此需要實例化一個存放頂點迭代順序的迭代器。
訪問數組實例化
主要實現:
輸入目標點
傳入迭代器中
標記為已訪問
找鄰接點
遞歸方法
代碼連接:
實驗2:
十字鏈表也是存儲圖的一種形式,其結構比較復雜。對于每一個頂點都會有一個入弧和出弧,入弧是指指向這個點的邊,出弧指的是從這個點出的邊。
拿這幅圖做例子,頂點F的入弧是A-F出弧;出弧是F-G。
對于每條邊,它有四個要素,
弧尾:這條邊出發的起始點
弧頭:這條邊指向的終點
同弧頭:弧頭相同的其他邊。若無,則為空
同弧尾:弧尾相同的其他邊。若無,則為空
實現十字鏈表存儲圖:
初步實現:
創建一個邊的類,其中設置的變量有:邊的權值,弧尾,弧頭,同弧尾的邊以及同弧頭的邊。并且要設定好構造方法,實例化邊的時候要輸入:權值、弧尾、弧頭。
創建一個頂點的類,其中設置的變量有:入弧,出弧,數據。設定好構造方法,實例化頂點的時候要輸入數據。
用頂點類創建一個頂點的集合來存放頂點
用邊類來創建一個邊的集合來存放邊
方法實現:
添加頂點---addVex(Vex vex)
不像之前的鄰接矩陣,這次的邊是直接用一個列表來保存的,所以不需要對邊的集合進行重組。同時,點的添加也沒那么麻煩,只要直接添加進點的集合中就可以了。
刪除頂點---removeVex(Vex vex)
除了直接在點的集合中進行刪除,還要將涉及該點的邊全部進行刪除。
添加邊---addEdge(Edgeedge)
首先是直接將邊添加進邊的集合中。
然后獲得該邊的弧頭和弧尾
看弧頭弧或弧尾是否已有入弧或出弧。
若弧尾沒有出弧,這條邊會成為這個弧尾的出弧。如果該弧尾存在出弧,則尋找該弧尾出弧的同弧尾,直到最后一個同弧尾,這條邊成為該弧尾出弧的新的最后的同弧尾。
若弧頭沒有入弧,這條邊會成為這個弧頭的入弧。如果該弧頭存在入弧,則尋找該弧頭出弧的同弧頭,直到最后一個同弧頭,這條邊成為該弧頭入弧的新的最后的同弧頭。
刪除邊---removeEdge(Edgeedge)
因為保存邊的是一個列表,所以比較容易刪去目標邊。用列表的remove功能可以實現。
頂點/邊的數量---vex/edgeSize()
因為保存邊和頂點的都是一個列表,所以比較容易得到頂點和邊的數量。用列表的size方法可以實現
是否為空---isEmpty()
因為保存頂點的是一個列表,所以比較容易得到圖是否為空,用列表的isEmpty()方法可以實現。
廣度優先遍歷
實例化隊列
實例化迭代器
實例化訪問數組
輸入起始遍歷頂點
將起始遍歷頂點放入隊列中,并將其標記為已訪問。
通過出弧入弧以及出弧的同弧頭以及入弧的同弧尾來獲取起始點的鄰接點,將其入隊,并用相同的方法去訪問鄰接點的鄰接點,然后入隊。將已訪問的點標記直到訪問的點的數量等于頂點集合的長度
將隊列中的元素放進迭代器中并打印出來
深度優先遍歷
實例化列表來保存深度遍歷的頂點順序
實例化訪問數組
對起始遍歷點看它有沒有出弧,有的話對出弧所對應的鄰接點進行方法遞歸。檢查完出弧后看有沒有同弧尾,有的話對同弧尾對應的鄰接點進行方法遞歸。同時要對訪問過的點標記為已訪問。遍歷過程中對這些訪問的點要放進保存頂點順序的列表中。
將列表打印
代碼鏈接
實驗3:
要解決最短路徑可以使用一個方法:Dijkstra算法
把圖中頂點集合V分成兩組,第一組為已求出最短路徑的頂點集合(用S表示,初始時S中只有一個源點,以后每求得一條最短路徑 ,就將加入到集合S中,直到全部頂點都加入到S中,算法就結束了),第二組為其余未確定最短路徑的頂點集合(用U表示),按最短路徑長度的遞增次序依次把第二組的頂點加入S中。在加入的過程中,總保持從源點v到S中各頂點的最短路徑長度不大于從源點v到U中任何頂點的最短路徑長度。此外,每個頂點對應一個距離,S中的頂點的距離就是從v到此頂點的最短路徑長度,U中的頂點的距離,是從v到此頂點只包括S中的頂點為中間頂點的當前最短路徑長度。
實現方法
最短路徑
傳入一個帶權值的二元數組,以及起始點
創建一個訪問數組,并將起始點在訪問數組的對應位置標記為已訪問
以起始點在二元數組中的下標作為行
然后遍歷該行,尋找最小的權值,并記錄對應列下標i
當遇到不是鄰接點的時候,遍歷鄰接點,看哪個鄰接點離目標點近
將最小路徑的值放入數組中
將對應頂點標記為已訪問直到所有點都是已訪問
打印數組
不相通點
查看開始點與哪個點的權值為10000,這兩點不相通。
實驗知識點
鄰接矩陣存儲圖
十字鏈存儲圖
最短路徑的算法——Dijkstra算法
總結
以上是生活随笔為你收集整理的java用十字链表实现无向图_实验四:图的实现与应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓手机游戏修改器(安卓手游修改器)
- 下一篇: java程会释放锁join_关于join