目錄
鑰匙要點
找到最短路徑
摘要
數據結構中的圖和樹之間有什麼區別?樹是一種類型,但並非所有圖形都是樹。樹是沒有任何週期的連接圖。它具有帶根節點和子節點的層次結構。樹上的每個節點都有一個獨特的路徑。另一方面,圖可以具有循環,其結構更為複雜。它可以連接或斷開連接,節點之間可以具有多個路徑。列表。鄰接矩陣是大小為v x v的2D數組,其中v是圖中的頂點數。如果頂點I和J之間有邊緣,則第I和J列的交點處的單元格為1,否則為0。鄰接列表是鏈接列表的數組。數組的索引代表一個頂點,其鏈接列表中的每個元素代表與頂點形成邊緣的其他頂點。是數據結構中幾種類型的圖形。一個簡單的圖是一個沒有循環的圖形,在任何兩個頂點之間不超過一個邊緣。多編碼可以在頂點之間具有多個邊緣。完整的圖是一個簡單的圖形,其中每對頂點都通過邊緣連接。加權圖為每個邊緣分配一個權重。有向圖(或Digraph)具有方向的邊緣。邊緣從一個頂點到另一個頂點。
在計算機科學中的許多應用中,都使用了圖表中圖中圖的應用?它們在社交網絡中用於表示人們之間的聯繫。它們用於網絡爬行中訪問網頁並構建搜索索引。它們用於網絡路由算法中,以找到兩個節點之間的最佳路徑。它們在生物學中用於建模和分析生物網絡。它們也用於計算機圖形和物理模擬中。
首頁 後端開發 php教程 PHP主| PHP DEV的數據結構:圖形

PHP主| PHP DEV的數據結構:圖形

Feb 23, 2025 am 08:49 AM

PHP主| PHP DEV的數據結構:圖形

鑰匙要點

    圖是用於建模密鑰/值對之間關係的數學結構,並具有許多真實的應用程序,例如網絡優化,流量路由和社交網絡分析。它們由連接它們的頂點(節點)和邊緣(線)組成,它們可以定向或無方向性,加權或未加權。
  • >
  • >圖形可以通過兩種方式表示:作為鄰接矩陣或鄰接列表。鄰接列表更具空間效率,尤其是對於大多數頂點沒有連接的稀疏圖,而鄰接矩陣則有助於更快地查找。 圖理論的常見應用是在任意兩個節點之間找到最少數量的啤酒花(即最短路徑)。這可以使用廣度優先的搜索來實現,這涉及從指定的根節點從級別穿越圖形級別。此過程需要保持未訪問的節點的隊列。 > Dijkstra的算法被廣泛用於查找圖中任何兩個節點之間的最短或最佳路徑。這涉及檢查從源節點開始的所有可能對頂點之間的每個邊緣,並保持最短的總距離的更新的頂點,直到達到目標節點為止。
在我以前的一篇文章中,我向您介紹了樹數據結構。現在,我想探索一個相關的結構 - 圖。圖具有許多現實世界應用程序,例如網絡優化,流量路由和社交網絡分析。 Google的Pagerank,Facebook的Graph Search以及Amazon和Netflix的建議是圖形驅動應用程序的一些示例。 在本文中,我將探討使用圖形的兩個常見問題 - 啤酒花數量最少和最短路徑問題。 圖是一種數學結構,用於建模鍵/值對之間的關​​系。圖包含一組>頂點(節點)和連接它們的任意數量的 edges(線)。這些邊緣可以指向或無向。導向邊緣只是兩個頂點之間的邊緣,而邊緣A→B不與B→A相同。無方向的邊緣沒有方向或方向;邊緣A-B等於B-A。我們上次了解到的樹結構可以被視為一種無向圖的類型,其中每個頂點通過簡單路徑連接到至少一個其他頂點。 圖形也可以加權或未加權。加權圖或網絡是將重量或成本值分配給其每個邊緣的一個網絡。加權圖通常用於確定最佳路徑,最優勢或兩個點之間的最低“成本”路徑。 GoogleMap的驅動方向是使用加權圖的示例。 最少的啤酒花

圖理論的常見應用是在任意兩個節點之間找到最少的啤酒花。與樹一樣,圖形可以通過以下兩種方式之一進行遍歷:深度優先或廣度優先。我們在上一篇文章中介紹了深度優先的搜索,因此讓我們看一下廣度優先的搜索。 考慮以下圖:

PHP主| PHP DEV的數據結構:圖形 為了簡單起見,讓我們假設該圖是

- 即,任何方向的邊緣是相同的。我們的任務是在任意兩個節點之間找到最少的啤酒花。 在廣度優先的搜索中,我們從根節點(或指定為根的任何節點)開始,然後按級別沿著樹的水平沿我們的方式進行工作。為了做到這一點,我們需要一個隊列來維護未訪問的節點的列表,以便我們可以在每個級別後回溯和處理它們。 一般算法看起來像這樣: 但是,我們怎麼知道哪些節點相鄰,更不用說未訪問的而不首先遍歷圖形呢?這使我們解決瞭如何建模圖數據結構的問題。
1. Create a queue
2. Enqueue the root node and mark it as visited
3. While the queue is not empty do:
  3a. dequeue the current node
  3b. if the current node is the one we're looking for then stop
  3c. else enqueue each unvisited adjacent node and mark as visited
登入後複製
登入後複製
登入後複製
代表圖形

通常有兩種表示圖形的方法:作為鄰接矩陣或鄰接列表。上面的圖表示為鄰接列表,如下所示:

PHP主| PHP DEV的數據結構:圖形該圖表示為矩陣,其中1表示2個頂點之間的邊緣的“發生率”:

PHP主| PHP DEV的數據結構:圖形

鄰接列表更具空間效率,尤其是對於大多數頂點沒有連接的稀疏圖,而鄰接矩陣有助於更快的查找。最終,表示形式的選擇將取決於可能需要哪種類型的圖形操作。 讓我們使用鄰接列表來表示圖表:
1. Create a queue
2. Enqueue the root node and mark it as visited
3. While the queue is not empty do:
  3a. dequeue the current node
  3b. if the current node is the one we're looking for then stop
  3c. else enqueue each unvisited adjacent node and mark as visited
登入後複製
登入後複製
登入後複製
現在,讓我們看看一般廣度優先搜索算法的實現是什麼樣的:
<span><span><?php
</span></span><span><span>$graph = array(
</span></span><span>  <span>'A' => array('B', 'F'),
</span></span><span>  <span>'B' => array('A', 'D', 'E'),
</span></span><span>  <span>'C' => array('F'),
</span></span><span>  <span>'D' => array('B', 'E'),
</span></span><span>  <span>'E' => array('B', 'D', 'F'),
</span></span><span>  <span>'F' => array('A', 'E', 'C'),
</span></span><span><span>);</span></span>
登入後複製
登入後複製
運行以下示例,我們得到:
<span><span><?php
</span></span><span><span>class Graph
</span></span><span><span>{
</span></span><span>  <span>protected $graph;
</span></span><span>  <span>protected $visited = array();
</span></span><span>
</span><span>  <span>public function __construct($graph) {
</span></span><span>    <span>$this->graph = $graph;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>// find least number of hops (edges) between 2 nodes
</span></span><span>  <span>// (vertices)
</span></span><span>  <span>public function breadthFirstSearch($origin, $destination) {
</span></span><span>    <span>// mark all nodes as unvisited
</span></span><span>    <span>foreach ($this->graph as $vertex => $adj) {
</span></span><span>      <span>$this->visited[$vertex] = false;
</span></span><span>    <span>}
</span></span><span>
</span><span>    <span>// create an empty queue
</span></span><span>    <span>$q = new SplQueue();
</span></span><span>
</span><span>    <span>// enqueue the origin vertex and mark as visited
</span></span><span>    <span>$q->enqueue($origin);
</span></span><span>    <span>$this->visited[$origin] = true;
</span></span><span>
</span><span>    <span>// this is used to track the path back from each node
</span></span><span>    <span>$path = array();
</span></span><span>    <span>$path[$origin] = new SplDoublyLinkedList();
</span></span><span>    <span>$path[$origin]->setIteratorMode(
</span></span><span>      <span>SplDoublyLinkedList<span>::</span>IT_MODE_FIFO|SplDoublyLinkedList<span>::</span>IT_MODE_KEEP
</span></span><span>    <span>);
</span></span><span>
</span><span>    <span>$path[$origin]->push($origin);
</span></span><span>
</span><span>    <span>$found = false;
</span></span><span>    <span>// while queue is not empty and destination not found
</span></span><span>    <span>while (!$q->isEmpty() && $q->bottom() != $destination) {
</span></span><span>      <span>$t = $q->dequeue();
</span></span><span>
</span><span>      <span>if (!empty($this->graph[$t])) {
</span></span><span>        <span>// for each adjacent neighbor
</span></span><span>        <span>foreach ($this->graph[$t] as $vertex) {
</span></span><span>          <span>if (!$this->visited[$vertex]) {
</span></span><span>            <span>// if not yet visited, enqueue vertex and mark
</span></span><span>            <span>// as visited
</span></span><span>            <span>$q->enqueue($vertex);
</span></span><span>            <span>$this->visited[$vertex] = true;
</span></span><span>            <span>// add vertex to current path
</span></span><span>            <span>$path[$vertex] = clone $path[$t];
</span></span><span>            <span>$path[$vertex]->push($vertex);
</span></span><span>          <span>}
</span></span><span>        <span>}
</span></span><span>      <span>}
</span></span><span>    <span>}
</span></span><span>
</span><span>    <span>if (isset($path[$destination])) {
</span></span><span>      <span>echo "<span><span>$origin</span> to <span>$destination</span> in "</span>, 
</span></span><span>        <span>count($path[$destination]) - 1,
</span></span><span>        <span>" hopsn";
</span></span><span>      <span>$sep = '';
</span></span><span>      <span>foreach ($path[$destination] as $vertex) {
</span></span><span>        <span>echo $sep, $vertex;
</span></span><span>        <span>$sep = '->';
</span></span><span>      <span>}
</span></span><span>      <span>echo "n";
</span></span><span>    <span>}
</span></span><span>    <span>else {
</span></span><span>      <span>echo "No route from <span><span>$origin</span> to <span>$destinationn</span>"</span>;
</span></span><span>    <span>}
</span></span><span>  <span>}
</span></span><span><span>}</span></span>
登入後複製
登入後複製
如果我們使用堆棧而不是隊列,則遍歷將成為深度優先的搜索。

找到最短路徑

另一個常見的問題是找到任何兩個節點之間的最佳路徑。早些時候,我提到了GoogleMap的行駛方向,以此為例。其他應用程序包括規劃旅行行程,道路交通管理以及火車/公共汽車計劃。 解決此問題的最著名算法之一是由一位29歲的計算機科學家以Edsger W. Dijkstra的名義發明的。總的來說,Dijkstra的解決方案涉及檢查從源節點開始的所有可能的頂點之間的每個邊緣,並保持最短的總距離的更新的頂點,直到達到目標節點,或者無法達到目標節點,任何情況下的情況下。 有幾種方法可以實施該解決方案,實際上,在1959年,使用Minheaps,Priorityqueues和Fibonacci堆的多年以來,都對Dijkstra的原始算法做出了。一些改進的性能,而另一些則旨在解決Dijkstra解決方案中的缺點,因為它僅適用於正加權圖(權重為正值)。 這是一個(正)加權圖的示例:

PHP主| PHP DEV的數據結構:圖形

我們可以將此圖表示為鄰接列表,如下所示:
1. Create a queue
2. Enqueue the root node and mark it as visited
3. While the queue is not empty do:
  3a. dequeue the current node
  3b. if the current node is the one we're looking for then stop
  3c. else enqueue each unvisited adjacent node and mark as visited
登入後複製
登入後複製
登入後複製
這是使用PriorityQueue來維護所有“不優化”頂點的列表的實現:
<span><span><?php
</span></span><span><span>$graph = array(
</span></span><span>  <span>'A' => array('B', 'F'),
</span></span><span>  <span>'B' => array('A', 'D', 'E'),
</span></span><span>  <span>'C' => array('F'),
</span></span><span>  <span>'D' => array('B', 'E'),
</span></span><span>  <span>'E' => array('B', 'D', 'F'),
</span></span><span>  <span>'F' => array('A', 'E', 'C'),
</span></span><span><span>);</span></span>
登入後複製
登入後複製
如您所見,Dijkstra的解決方案只是廣度優先搜索的變體! 運行以下示例會產生以下結果:
<span><span><?php
</span></span><span><span>class Graph
</span></span><span><span>{
</span></span><span>  <span>protected $graph;
</span></span><span>  <span>protected $visited = array();
</span></span><span>
</span><span>  <span>public function __construct($graph) {
</span></span><span>    <span>$this->graph = $graph;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>// find least number of hops (edges) between 2 nodes
</span></span><span>  <span>// (vertices)
</span></span><span>  <span>public function breadthFirstSearch($origin, $destination) {
</span></span><span>    <span>// mark all nodes as unvisited
</span></span><span>    <span>foreach ($this->graph as $vertex => $adj) {
</span></span><span>      <span>$this->visited[$vertex] = false;
</span></span><span>    <span>}
</span></span><span>
</span><span>    <span>// create an empty queue
</span></span><span>    <span>$q = new SplQueue();
</span></span><span>
</span><span>    <span>// enqueue the origin vertex and mark as visited
</span></span><span>    <span>$q->enqueue($origin);
</span></span><span>    <span>$this->visited[$origin] = true;
</span></span><span>
</span><span>    <span>// this is used to track the path back from each node
</span></span><span>    <span>$path = array();
</span></span><span>    <span>$path[$origin] = new SplDoublyLinkedList();
</span></span><span>    <span>$path[$origin]->setIteratorMode(
</span></span><span>      <span>SplDoublyLinkedList<span>::</span>IT_MODE_FIFO|SplDoublyLinkedList<span>::</span>IT_MODE_KEEP
</span></span><span>    <span>);
</span></span><span>
</span><span>    <span>$path[$origin]->push($origin);
</span></span><span>
</span><span>    <span>$found = false;
</span></span><span>    <span>// while queue is not empty and destination not found
</span></span><span>    <span>while (!$q->isEmpty() && $q->bottom() != $destination) {
</span></span><span>      <span>$t = $q->dequeue();
</span></span><span>
</span><span>      <span>if (!empty($this->graph[$t])) {
</span></span><span>        <span>// for each adjacent neighbor
</span></span><span>        <span>foreach ($this->graph[$t] as $vertex) {
</span></span><span>          <span>if (!$this->visited[$vertex]) {
</span></span><span>            <span>// if not yet visited, enqueue vertex and mark
</span></span><span>            <span>// as visited
</span></span><span>            <span>$q->enqueue($vertex);
</span></span><span>            <span>$this->visited[$vertex] = true;
</span></span><span>            <span>// add vertex to current path
</span></span><span>            <span>$path[$vertex] = clone $path[$t];
</span></span><span>            <span>$path[$vertex]->push($vertex);
</span></span><span>          <span>}
</span></span><span>        <span>}
</span></span><span>      <span>}
</span></span><span>    <span>}
</span></span><span>
</span><span>    <span>if (isset($path[$destination])) {
</span></span><span>      <span>echo "<span><span>$origin</span> to <span>$destination</span> in "</span>, 
</span></span><span>        <span>count($path[$destination]) - 1,
</span></span><span>        <span>" hopsn";
</span></span><span>      <span>$sep = '';
</span></span><span>      <span>foreach ($path[$destination] as $vertex) {
</span></span><span>        <span>echo $sep, $vertex;
</span></span><span>        <span>$sep = '->';
</span></span><span>      <span>}
</span></span><span>      <span>echo "n";
</span></span><span>    <span>}
</span></span><span>    <span>else {
</span></span><span>      <span>echo "No route from <span><span>$origin</span> to <span>$destinationn</span>"</span>;
</span></span><span>    <span>}
</span></span><span>  <span>}
</span></span><span><span>}</span></span>
登入後複製
登入後複製

摘要

在本文中,我介紹了圖理論的基礎知識,兩種表示圖形的方法以及圖理論應用中的兩個基本問題。我向您展示瞭如何使用廣度優先的搜索來找到任何兩個節點之間最少的啤酒花,以及如何使用Dijkstra的解決方案來找到任何兩個節點之間的最短路徑。 通過fotolia 圖像 經常詢問數據結構中圖的問題(常見問題解答)

數據結構中的圖和樹之間有什麼區別?樹是一種類型,但並非所有圖形都是樹。樹是沒有任何週期的連接圖。它具有帶根節點和子節點的層次結構。樹上的每個節點都有一個獨特的路徑。另一方面,圖可以具有循環,其結構更為複雜。它可以連接或斷開連接,節點之間可以具有多個路徑。列表。鄰接矩陣是大小為v x v的2D數組,其中v是圖中的頂點數。如果頂點I和J之間有邊緣,則第I和J列的交點處的單元格為1,否則為0。鄰接列表是鏈接列表的數組。數組的索引代表一個頂點,其鏈接列表中的每個元素代表與頂點形成邊緣的其他頂點。是數據結構中幾種類型的圖形。一個簡單的圖是一個沒有循環的圖形,在任何兩個頂點之間不超過一個邊緣。多編碼可以在頂點之間具有多個邊緣。完整的圖是一個簡單的圖形,其中每對頂點都通過邊緣連接。加權圖為每個邊緣分配一個權重。有向圖(或Digraph)具有方向的邊緣。邊緣從一個頂點到另一個頂點。

>

在計算機科學中的許多應用中,都使用了圖表中圖中圖的應用?它們在社交網絡中用於表示人們之間的聯繫。它們用於網絡爬行中訪問網頁並構建搜索索引。它們用於網絡路由算法中,以找到兩個節點之間的最佳路徑。它們在生物學中用於建模和分析生物網絡。它們也用於計算機圖形和物理模擬中。

>圖形遍曆算法是什麼?

>有兩個主要的圖形遍曆算法:Depth-First Search(DFS)和廣度優先搜索(BFS)。 DFS在回溯之前盡可能沿每個分支探索。它使用堆棧數據結構。 BFS探索當前深度的所有頂點,然後才能進入下一個級別。它使用隊列數據結構。

如何在Java中實現圖形? hashmap中的每個鍵都是頂點,其值是一個鏈接列表,包含其連接到的頂點。

>

>什麼是兩部分圖?

二鍵圖是一個圖形,是一個圖形的圖形。被分為兩個不相交的集合,使每個邊緣在一個集合中連接一個頂點與另一組頂點連接。沒有邊界在同一集合中連接頂點。

什麼是子圖?

一個子圖是一個圖形,是另一個圖的一部分。它具有原始圖的某些(或全部)頂點,以及原始圖的某些(或全)邊緣。

>

>圖中的一個週期是什麼?一條從同一頂點開始和結束的路徑,至少具有一個邊。的連續的頂點通過邊緣連接。

以上是PHP主| PHP DEV的數據結構:圖形的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1422
52
Laravel 教程
1316
25
PHP教程
1267
29
C# 教程
1239
24
PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? 說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用? 什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用? Apr 09, 2025 am 12:09 AM

HTTP請求方法包括GET、POST、PUT和DELETE,分別用於獲取、提交、更新和刪除資源。 1.GET方法用於獲取資源,適用於讀取操作。 2.POST方法用於提交數據,常用於創建新資源。 3.PUT方法用於更新資源,適用於完整更新。 4.DELETE方法用於刪除資源,適用於刪除操作。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

解釋self ::,parent ::和static :: in php oop中的區別。 解釋self ::,parent ::和static :: in php oop中的區別。 Apr 09, 2025 am 12:04 AM

在PHPOOP中,self::引用當前類,parent::引用父類,static::用於晚靜態綁定。 1.self::用於靜態方法和常量調用,但不支持晚靜態綁定。 2.parent::用於子類調用父類方法,無法訪問私有方法。 3.static::支持晚靜態綁定,適用於繼承和多態,但可能影響代碼可讀性。

PHP如何安全地上載文件? PHP如何安全地上載文件? Apr 10, 2025 am 09:37 AM

PHP通過$\_FILES變量處理文件上傳,確保安全性的方法包括:1.檢查上傳錯誤,2.驗證文件類型和大小,3.防止文件覆蓋,4.移動文件到永久存儲位置。

PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? Apr 17, 2025 am 12:25 AM

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

See all articles