數據結構之圖的分類和存儲

圖(Graph)G由兩個集合V和E組成,記為:G=(V,E),其中V是頂點的有窮非空集合(其實就是頂點),E是V 中頂點偶對的有窮集合(就是)。V(G)和E(G)通常分別表示圖G的頂點集合以及邊集合,E(G)可以為空集合,但是此時的圖只有頂點,沒有邊。

舉個例子:

一個地圖: 頂點:城市 邊:路 可能只有城市沒有路就是E(G)可以為空集合,圖只有頂點,沒有邊。

多個城市 a b c d e

a 到b的方法(a到其他) :a - b a -c - b a - c - d - b

到a也有很多方法 b-a c-b-a 這樣就形成了網狀結構

1. 圖的分類

  • 有向圖:

邊是有方向的。類似車道的單行道

這意味著每條邊都從一個頂點指向另一個頂點,并且這種指向關系是有序的,有向圖的 那個方向的線條稱為。在有向圖中,如果有一條從頂點A到頂點B的邊,那么我們說A指向B(A是起點,B是終點),但這并不 意味著B也指向A

示例

在這里插入圖片描述

  • 無向圖

邊沒有方向。這意味著每條邊都連接兩個頂點,但不區分起點和終點。在無向圖中,如果兩個頂點由一 條邊連接,那么它們是相鄰的,并且這種相鄰關系是對稱的。

示例

在這里插入圖片描述

  • 網(帶權圖)

如果在圖的每條邊(或者弧)都被賦予一個權重(常用于表示節點之間連接的成本或距離),即為 (帶權圖)

在這里插入圖片描述

頂點的度

表示與頂點相連的邊的數量。

  • 無向圖

在這里插入圖片描述

  • 有向圖

在有向圖中,頂點的度分為入度(In-degree)和出度(Out-degree)。

入度:指向該頂點的邊的數量。

出度:從該頂點出發的邊的數量。
在這里插入圖片描述

  • 路徑

圖的路徑是指由圖中的頂點和邊所構成的序列,其中頂點之間通過邊相連。

兩個頂點之間存在路徑(到達方式),說明它們是連通

路徑可以是有向的或無向 的,這取決于圖的類型。

在這里插入圖片描述

a->c連通 c->a不是因為 這是有向圖c到a沒有路徑到達

若任意兩個頂點之間都是連通的話,則圖是連通圖

在這里插入圖片描述

這就是聯通圖

  • 鄰接點

鄰接點的定義是:如果兩個頂點之間存在一條邊,那么這兩個頂點就互為鄰接點

2 圖的存儲

2.1 鄰接矩陣

矩陣(二維數組)

鄰接矩陣是表示頂點間相鄰關系的矩陣。

對于n個頂點的圖,鄰接矩陣是一個n×n的二維數組(只存儲0 1)。兩個頂點存在直接連接到邊就是1,否則是0,自己到自己一般也是0

在無向圖中,鄰接矩陣是對稱的(對于對角線對稱),而在有向圖中則不一定。

    • 無向圖

在這里插入圖片描述

對應的鄰接矩陣是

12345
101001
210001
300011
400100
511100
  • ?
    • 有向圖

在這里插入圖片描述

對應的鄰接矩陣是

12345
101000
210001
300000
400100
510100

代碼如下:

  • 有向圖:
#include <iostream>
using namespace std;#define MAX_VERTICES 100 // 最大定點數// 初始化鄰接矩陣  int(*p)[MAX_VERTICES]也可以數組指針
void initalizeGraph(int adjMartix[MAX_VERTICES][MAX_VERTICES], int n)
{for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){adjMartix[i][j] = 0; // 初始化為0,表示沒有邊}}
}// 添加有向邊
void addDirectedEdge(int adjMartix[MAX_VERTICES][MAX_VERTICES], int u, int v) // uv是出度也是入度
{// 兩目標直接連接 有向圖adjMartix[u][v] = 1;// // 無向圖// adjMartix[v][u]  = 1;
}
void printGraph(int adjMartix[MAX_VERTICES][MAX_VERTICES], int n)
{for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){printf("%d ", adjMartix[i][j]); // 初始化為0,表示沒有邊}printf("\n");}
}
//  打印圖int main()
{int adjMartix[MAX_VERTICES][MAX_VERTICES]; // 圖// 節點int n = 5;// 初始化圖initalizeGraph(adjMartix, n);// 添加有向邊addDirectedEdge(adjMartix, 0, 1);addDirectedEdge(adjMartix, 1, 0);addDirectedEdge(adjMartix, 1, 4);addDirectedEdge(adjMartix, 4, 0);addDirectedEdge(adjMartix, 4, 2);addDirectedEdge(adjMartix, 3, 2);// 打印有向圖printGraph(adjMartix, n);return 0;
}

無向圖:

#include <iostream>
using namespace std;#define MAX_VERTICES 100 // 最大定點數// 初始化鄰接矩陣  int(*p)[MAX_VERTICES]也可以數組指針
void initalizeGraph(int adjMartix[MAX_VERTICES][MAX_VERTICES], int n)
{for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){adjMartix[i][j] = 0; // 初始化為0,表示沒有邊}}
}// 添加有向邊
void addDirectedEdge(int adjMartix[MAX_VERTICES][MAX_VERTICES], int u, int v) // uv是出度也是入度
{// 兩目標直接連接 有向圖adjMartix[u][v] = 1;// // 無向圖adjMartix[v][u]  = 1;
}
void printGraph(int adjMartix[MAX_VERTICES][MAX_VERTICES], int n)
{for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){printf("%d ", adjMartix[i][j]); // 初始化為0,表示沒有邊}printf("\n");}
}
//  打印圖int main()
{int adjMartix[MAX_VERTICES][MAX_VERTICES]; // 圖// 節點int n = 5;// 初始化圖initalizeGraph(adjMartix, n);// 添加有向邊addDirectedEdge(adjMartix, 0, 1);addDirectedEdge(adjMartix, 0, 4);addDirectedEdge(adjMartix, 1, 4);addDirectedEdge(adjMartix, 5, 3);addDirectedEdge(adjMartix, 3, 4);// 打印有向圖printGraph(adjMartix, n);return 0;
}

優點:
編碼簡單,容易理解。
便于檢查圖中任意兩個頂點之間是否存在邊。
便于計算圖中頂點的度。
缺點:
對于稀疏圖,鄰接矩陣會浪費大量存儲空間,因為矩陣中的大部分元素都是0。
在進行圖的遍歷等操作時,可能需要遍歷整個矩陣,效率較低。

2.2 鄰接表

鄰接表是圖的一種鏈式存儲結構。對于圖中的每個頂點,鄰接表都存儲一個鏈表,該鏈表包含與該頂點相鄰的所有頂點

例如下圖1包含和他相鄰的所有頂點,2和3

可以省略邊:連接關系2-3(隱含表示邊)(下節講,下面的代碼不省略)

1 - 2 - 3

1 - 3

在這里插入圖片描述

代碼如下

#include <iostream>
using namespace std;// 定義邊
typedef struct EdgeNode
{int adjvex;            // 鄰接點 終點struct EdgeNode *next; // 下一條邊 個指針用于連接同一起點的多條邊。這樣,我們就可以通// 過遍歷next指針來訪問從A出發的所有邊。
} EdgeNode;// 定義頂點
typedef struct VertexNode
{int data;            // 起點信息EdgeNode *FirstNode; // 這個指針用于從頂點出發找到其第一條邊 。這樣,我們就可以從任意一// 個頂點開始,通過firstedge找到其所有鄰接點。
} VertexNode;typedef struct Grasp_List
{VertexNode *newNode; // 頂點int numVertices;     // 頂點數int numEdges;        // 邊數
} Grasp_List;// 初始化函數
void InitGraph(Grasp_List *graph, int n)
{graph->newNode = new VertexNode[n](); // 分配內存 ()會進行初始化graph->numVertices = n;                頂點5graph->numEdges = 0;                  // 邊0for (int i = 0; i < n; i++){graph->newNode[i].data = i;            // 初始化每個頂點的數據graph->newNode[i].FirstNode = nullptr; // 初始化第一條邊為空}
}// 向圖中添加邊 u起始頂點 v鄰接點
void AddEdge(Grasp_List *graph, int u, int v)
{// 創建邊EdgeNode *newEdgeNode = (EdgeNode *)malloc(sizeof(EdgeNode)); // 創建新邊節點// 分配失敗if (!newEdgeNode){perror("分配失敗");return;}newEdgeNode->adjvex = v; // 設置鄰接點 也就是終點// 插入 頭插法 把邊直接newEdgeNode->next = graph->newNode[u].FirstNode; // 下一條邊=原來的第一條邊graph->newNode[u].FirstNode = newEdgeNode;       // 更新第一條邊graph->numEdges++;                               // 邊數加1如果是無向圖 還需要再添加一條邊// EdgeNode* newNodeV = (EdgeNode*)malloc(sizeof(EdgeNode)); // 創建新邊節點// if (!newNodeV)//{//     printf("申請內存失敗\n");//     exit(-1);// }// newNodeV->adjvex = u;                     // 設置鄰接點頭插法// newNodeV->next = G->adjList[v].firstedge; // 下一條邊 = 原來的第一條邊// G->adjList[v].firstedge = newNodeV;       // 更新第一條邊
}// 打印鄰接表
void printGraph(Grasp_List *graph)
{if (graph == nullptr){cout << "我是空圖" << endl;return;}printf("Graph with %d vertices and  %d edge:\n", graph->numVertices, graph->numEdges);// 根據定點數遍歷for (int i = 0; i < graph->numVertices; i++){printf("vertices %d: ", graph->newNode[i].data); // 打印頂點// 找到頂點第一條邊EdgeNode *p = graph->newNode[i].FirstNode; // 保存while (p){// 鄰接點printf(" %d", p->adjvex);// 下一條邊p = p->next;}printf("\n");}
}// 釋放圖占用的內存
void freeGraph(Grasp_List *graph)
{if (graph == NULL){return;}// 釋放邊內存for (int i = 0; i < graph->numVertices; i++){EdgeNode *curerent = graph->newNode[i].FirstNode;EdgeNode *tmp = nullptr;while (curerent){tmp = curerent;curerent = curerent->next;free(tmp);tmp = nullptr;}curerent = nullptr;}// 釋放頂點內存delete[] (graph->newNode);graph->newNode = nullptr;// 釋放圖本身的內存delete graph;
}// 主函數實例
int main()
{Grasp_List *G  = new Grasp_List;// 初始化圖InitGraph(G, 5);// 添加邊AddEdge(G, 0, 1);AddEdge(G, 0, 4);AddEdge(G, 1, 2);AddEdge(G, 1, 3);AddEdge(G, 2, 3);// 打印圖printGraph(G);// 釋放圖freeGraph(G);return 0;
}

解釋一個遍創建的過程

AddEdge(G, 0, 1);
  • 這表示在圖 G 中添加一條從頂點 0 到頂點 1 的邊。

  • 具體步驟如下:

    1. 創建一個新邊節點 newEdgeNode,并為其分配內存。
    2. 將新邊的鄰接點設置為 1
    3. 使用頭插法將新邊插入到頂點 0 的邊鏈表中,使新邊成為頂點 0 的第一條邊。
    4. 圖的邊數增加 1
  • 形成鏈表的過程

    在調用 AddEdge(G, 0, 1) 后,頂點 0 和頂點 1 通過一條邊連接起來。具體來說:

    • 頂點 0 的邊鏈表中新增了一個邊節點,其 adjvex 字段為 1
    • 這個邊節點通過 next 指針連接到原來頂點 0 的邊鏈表

優點:
節省存儲空間,特別是對于稀疏圖。
便于添加和刪除邊。
便于進行圖的遍歷等操作。

缺點:
不便于檢查圖中任意兩個頂點之間是否存在邊(需要遍歷兩個頂點的鄰接表)。
在某些情況下,可能需要額外的空間來存儲頂點的信息(如頂點的索引或名稱)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79971.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79971.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79971.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

擴增子分析|微生物生態網絡穩定性評估之魯棒性(Robustness)和易損性(Vulnerability)在R中實現

一、引言 周集中老師團隊于2021年在Nature climate change發表的文章&#xff0c;闡述了網絡穩定性評估的原理算法&#xff0c;并提供了完整的代碼。自此對微生物生態網絡的評估具有更全面的指標&#xff0c;自此網絡穩定性的評估廣受大家歡迎。本系列將介紹網絡穩定性之魯棒性…

setup 函數在 Vue 3 中的作用是什么?什么時候會執行

文章目錄 前言? 一、setup() 函數的作用是什么&#xff1f;? 二、setup() 什么時候執行&#xff1f;? 三、setup() 的參數? 四、setup() 中不能做什么&#xff1f;? 五、常見用法示例? 六、總結&#xff08;適合背誦或面試回答&#xff09; <script setup> 是 **Vu…

JDBC實現--保姆級教程~

本來以為寫過一個使用python與數據庫連接的文章&#xff0c;但是今天突然發現沒有&#xff0c;那就直接寫Java與數據庫連接的吧。當然如果大家有需要可以告訴我&#xff0c;有時間的話也可以寫一個的pymysql的使用的。 數據庫有很多種&#xff0c;接下來我就以MySQL為例來進行講…

Ubuntu18.04搭建samda服務器

一.什么是Samba服務器&#xff1f; Samba服務器是一種基于開源協議實現的網絡共享服務軟件&#xff0c;主要用于在不同操作系統&#xff08;如Windows、Linux、Unix&#xff09;之間實現文件和打印機共享功能。其核心目標是解決跨平臺資源共享的兼容性問題&#xff0c;尤其是在…

《分詞算法大揭秘:BPE、BBPE、WordPiece、ULM常見方法介紹》

分詞算法是自然語言處理&#xff08;NLP&#xff09;中的一個重要預處理步驟&#xff0c;它將文本分割成更小的單元&#xff08;如單詞、子詞或字符&#xff09;。以下是幾種常見的分詞算法&#xff1a;Byte Pair Encoding (BPE)、Byte-level BPE (BBPE)、WordPiece 和 Unigram…

WordPress01 - 后臺常用功能

最近些日子研究Wordpress&#xff0c;做些簡單的筆記。 怎么安裝Wordpress&#xff0c;怎么進的后臺&#xff0c;這些咱就不嘮了哈&#xff0c;網上到處是教程。 目錄 1&#xff0c;Wordpress的后臺 1-1&#xff0c; Posts(投稿) 1-2&#xff0c;Media(媒體) 1-3&#xf…

R8周:RNN實現阿爾茨海默病診斷

&#x1f368; 本文為&#x1f517;365天深度學習訓練營中的學習記錄博客 &#x1f356; 原作者&#xff1a;K同學啊 一、前期準備 1.設置GPU import numpy as np import pandas as pd import torch from torch import nn import torch.nn as nn import torch.nn.functi…

今天python練習題

目錄 一、每日一言 二、練習題 三、效果展示 四、下次題目 五、總結 一、每日一言 不要害怕失敗&#xff0c;失敗可能成為我們前進的動力&#xff01; 二、練習題 有列表lst [[1,2,3],[4,5,6],[7,8,9]],取出其中的元素1/5/9組成新的列表 # 有列表lst [[1,2,3],[4,5,6],[…

機器人強化學習入門學習筆記(二)

基于上一篇的《機器人強化學習入門學習筆記》,在基于 MuJoCo 的仿真強化學習訓練中,除了 PPO(Proximal Policy Optimization)之外,還有多個主流強化學習算法可用于訓練機器人直行或其他復雜動作。 ?? 一、常見強化學習算法對比(可用于 MuJoCo) 算法類型特點適合場景PP…

用 DuckDB 高效分析 JSON 數據:從入門到實戰

解析 JSON 文件進行分析常常充滿挑戰。無論你是在處理 API 響應、日志文件&#xff0c;還是應用數據&#xff0c;如果沒有合適的工具&#xff0c;分析 JSON 都會非常耗時。 借助 DuckDB&#xff0c;你可以直接用 SQL 查詢復雜的 JSON 文件&#xff0c;無需編寫復雜的解析代碼或…

從貼牌到品牌:出海官網如何讓中國制造“貴”起來?

在全球經濟一體化的當下&#xff0c;中美關稅戰如同一記重錘&#xff0c;給國際貿易格局帶來了巨大震蕩。自貿易摩擦爆發以來&#xff0c;雙方多次調整關稅政策&#xff0c;涉及的商品種類不斷增多&#xff0c;稅率持續攀升&#xff0c;眾多中國企業的出口業務遭受重創&#xf…

react-13react中外部css引入以及style內聯樣式(動態className與動態style)

1. 外部css文件 - 普通引入 1.1 創建一個 CSS 文件&#xff0c;MyComponent.css。 /* MyComponent.css */ .my-class {color: red;font-size: 20px; } 1.2 組件中import引入 import React from react; import ./MyComponent.css; // 引入 CSS 文件function MyComponent() {r…

n8n 與智能體構建:開發自動化 AI 作業的基礎平臺

n8n 是一款開源的自動化流程構建平臺&#xff0c;通過其模塊化節點系統&#xff0c;開發者可以快速實現跨平臺的任務編排、數據集成與智能交互。當 n8n 與大型語言模型&#xff08;LLM&#xff09;結合時&#xff0c;就能構建出具備感知、推理、執行能力的 AI 智能體&#xff0…

14.Spring Boot 3.1.5 集成 Spring Security 進行訪問控制

14.Spring Boot 3.1.5 集成 Spring Security 進行訪問控制 Spring Security 是一個強大且高度可定制的認證和訪問控制框架&#xff0c;專為基于 Spring 的應用程序設計。它為基于 Java EE 的企業應用程序提供了全面的安全解決方案&#xff0c;包括 Web 應用程序安全和方法級安…

Linux學習筆記(二):Linux權限管理

文章目錄 一、Linux下用戶的分類1. Linux下用戶分為兩類&#xff1a;2. 這兩類用戶如何進行切換呢&#xff1f;3. 短暫提權 二、何為權限1. 什么是權限2. Linux的文件后綴意義 三、修改權限1. 設置文件的訪問權限——chmod2. 修改文件擁有者——chown3. 修改文件所屬組——chgr…

學習alpha,第2個alpha

alphas (-1 * ts_corr(rank(ts_delta(log(volume), 2)), rank(((close - open) / open)), 6)) 先分析操作符從左到右 ts_corr: Pearson 相關度量兩個變量之間的線性關系。當變量呈正態分布且關系呈線性時&#xff0c;它最有效。 ts_corr(vwap, close, 20)是一個計算時間序列相…

Paddle Serving|部署一個自己的OCR識別服務器

前言 之前使用C部署了自己的OCR識別服務器&#xff0c;Socket網絡傳輸部分是自己寫的&#xff0c;回過頭來一看&#xff0c;自己犯傻了&#xff0c;PaddleOCR本來就有自己的OCR服務器項目&#xff0c;叫PaddleServing&#xff0c;這里記錄一下部署過程。 1 下載依賴環境 1.1 …

React Native【詳解】搭建開發環境,創建項目,啟動項目

下載安裝 node https://nodejs.cn/download/ 查看 npx 版本 npx -v若無 npx 則安裝 npm install -g npx創建項目 npx create-expo-applatestRN_demo 為自定義的項目名稱 下載安裝 Python 2.7 下載安裝 JAVA JDK https://www.oracle.com/java/technologies/downloads/#jdk24-…

NVIDIA Halos:智能汽車革命中的全棧式安全系統

高級輔助駕駛行業正面臨一個尷尬的"安全悖論"——傳感器數量翻倍的同時&#xff0c;事故率曲線卻遲遲不見明顯下降。究其原因&#xff0c;當前行業普遍存在三大技術困局&#xff1a; 碎片化安全方案 傳統方案就像"打補丁"&#xff0c;激光雷達廠商只管點云…

數據資產管理與AI融合:物聯網時代的新征程

一、引言 在當今數字化浪潮席卷全球的時代&#xff0c;數據資產已成為企業和組織的核心競爭力之一。隨著物聯網&#xff08;IoT&#xff09;技術的飛速發展&#xff0c;海量的數據如潮水般涌來&#xff0c;如何高效地管理和利用這些數據資產成為了亟待解決的問題。與此同時&am…