【數據結構第 6 章 ②】- 用 C 語言實現鄰接矩陣

目錄

一、鄰接矩陣表示法

二、AMGraph.h

三、AMGraph.c

四、Test.c


【數據結構第 6 章 ① 】- 圖的定義和基本術語-CSDN博客

由于圖的結構比較復雜,任意兩個頂點之間都可能存在聯系,因此無法以數據元素在存儲區中的物理位置來表示元素之間的關系,即圖沒有順序存儲結構,但可以借助二維數組來表示元素之間的關系,即鄰接矩陣表示法。另一方面,由于圖的任意兩個頂點間都可能存在關系,因此,用鏈式存儲表示圖是很自然的事,圖的鏈式存儲有多種,有鄰接表、十字鏈表和鄰接多重表,應根據實際需要的不同,選擇不同的存儲結構。


一、鄰接矩陣表示法

鄰接矩陣(Adjacency Matrix)是表示頂點之間相鄰關系的矩陣。設 G(V, E) 是具有 n 個頂點的圖,則 G 的鄰接矩陣是具有如下性質的 n 階方陣

例如,圖一中的 G1 和 G2 的鄰接矩陣如下所示:

若 G 是網,則鄰接矩陣可以定義為:

其中?w_{i, j}?表示邊上的權值;?\infty?表示計算機允許的,大于所有邊上權值的數。例如,下圖所示為一個有向網和它的鄰接矩陣。


二、AMGraph.h

用鄰接矩陣表示法表示圖,除了一個用于存儲鄰接矩陣的二維數組外,還需要用一個一維數組來存儲頂點信息

注意:下面是以無向圖為例的

#pragma once#define DEFAULT_CAPACITY 10typedef char VertexType;  // 假定頂點的數據類型為 char
typedef int EdgeType;  // 假定邊的權值的數據類型為 inttypedef struct AMGraph
{VertexType* vertices;  // 頂點表(vertices 是 vertex 的復數)EdgeType** edges;  // 鄰接矩陣int vSize;  // 當前圖中的頂點數int eSize;  // 當前圖中的邊數int capacity;  // 容量
}AMGraph;// 基本操作
void AMGraphInit(AMGraph* pg);  // 初始化void ShowAdjMatrix(AMGraph* pg);  // 顯示鄰接矩陣int GetVetexPos(AMGraph* pg, VertexType v);  // 獲取頂點的位置void InsertVertex(AMGraph* pg, VertexType v);  // 插入頂點
void InsertEdge(AMGraph* pg, VertexType v1, VertexType v2);  // 插入邊void EraseVertex(AMGraph* pg, VertexType v);  // 刪除頂點
void EraseEdge(AMGraph* pg, VertexType v1, VertexType v2);  // 刪除邊int GetFirstAdjVexPos(AMGraph* pg, VertexType v);  // 獲取 v 的第一個鄰接頂點的位置
int GetNextAdjVexPos(AMGraph* pg, VertexType v, VertexType w);
// 獲取 v 的(相對于 w 的)下一個鄰接頂點的位置void AMGraphDestroy(AMGraph* pg);  // 銷毀


三、AMGraph.c

  1. 初始化

    void AMGraphInit(AMGraph* pg)
    {assert(pg);pg->vSize = pg->eSize = 0;pg->capacity = DEFAULT_CAPACITY;pg->vertices = (VertexType*)malloc(sizeof(VertexType) * pg->capacity);assert(pg->vertices);pg->edges = (EdgeType**)malloc(sizeof(EdgeType*) * pg->capacity);assert(pg->edges);for (int i = 0; i < pg->capacity; ++i){pg->edges[i] = (EdgeType*)malloc(sizeof(EdgeType) * pg->capacity);assert(pg->edges[i]);for (int j = 0; j < pg->capacity; ++j){pg->edges[i][j] = 0;}}
    }
  2. 獲取頂點的位置

    int GetVetexPos(AMGraph* pg, VertexType v)
    {assert(pg);for (int i = 0; i < pg->vSize; ++i){if (pg->vertices[i] == v)return i;}return -1;
    }
  3. 顯示鄰接矩陣

    void ShowAdjMatrix(AMGraph* pg)
    {assert(pg);printf("  ");  // 輸出兩個空格for (int i = 0; i < pg->vSize; ++i){printf("%c ", pg->vertices[i]);}printf("\n");for (int i = 0; i < pg->vSize; ++i){printf("%c ", pg->vertices[i]);for (int j = 0; j < pg->vSize; ++j){printf("%d ", pg->edges[i][j]);}printf("\n");}
    }
  4. 插入頂點

    void InsertVertex(AMGraph* pg, VertexType v)
    {assert(pg);// 考慮是否需要擴容if (pg->vSize == pg->capacity){VertexType* tmp1 = (VertexType*)realloc(pg->vertices, sizeof(VertexType) * 2 * pg->capacity);assert(tmp1);pg->vertices = tmp1;EdgeType** tmp2 = (EdgeType**)realloc(pg->edges, sizeof(EdgeType*) * 2 * pg->capacity);assert(tmp2);pg->edges = tmp2;for (int i = 0; i < pg->capacity; ++i){EdgeType* tmp3 = (EdgeType*)realloc(pg->edges[i], sizeof(EdgeType) * 2 * pg->capacity);assert(tmp3);pg->edges[i] = tmp3;for (int j = pg->capacity; j < 2 * pg->capacity; ++j){pg->edges[i][j] = 0;}}for (int i = pg->capacity; i < 2 * pg->capacity; ++i){pg->edges[i] = (EdgeType*)malloc(sizeof(EdgeType) * 2 * pg->capacity);assert(pg->edges[i]);for (int j = 0; j < 2 * pg->capacity; ++j){pg->edges[i][j] = 0;}}pg->capacity *= 2;}// 插入頂點pg->vertices[pg->vSize++] = v;
    }
  5. 插入邊

    void InsertEdge(AMGraph* pg, VertexType v1, VertexType v2)
    {assert(pg);int pos1 = GetVetexPos(pg, v1);int pos2 = GetVetexPos(pg, v2);if (pos1 == -1 || pos2 == -1)return;if (pg->edges[pos1][pos2] != 0)return;pg->edges[pos1][pos2] = pg->edges[pos2][pos1] = 1;++pg->eSize;
    }
  6. 刪除頂點

    void EraseVertex(AMGraph* pg, VertexType v)
    {assert(pg);int pos = GetVetexPos(pg, v);if (pos == -1)return;// cnt 為和 v 相關聯的邊的數目int cnt = 0;for (int j = 0; j < pg->vSize; ++j){if (pg->edges[pos][j] != 0)++cnt;}pg->vertices[pos] = pg->vertices[pg->vSize - 1];for (int j = 0; j < pg->vSize; ++j){pg->edges[pos][j] = pg->edges[pg->vSize - 1][j];}for (int i = 0; i < pg->vSize; ++i){pg->edges[i][pos] = pg->edges[i][pg->vSize - 1];}--pg->vSize;pg->eSize -= cnt;
    }
    
  7. 刪除邊

    void EraseEdge(AMGraph* pg, VertexType v1, VertexType v2)
    {assert(pg);int pos1 = GetVetexPos(pg, v1);int pos2 = GetVetexPos(pg, v2);if (pos1 == -1 || pos2 == -1)return;if (pg->edges[pos1][pos2] == 0)return;pg->edges[pos1][pos2] = pg->edges[pos2][pos1] = 0;--pg->eSize;
    }
  8. 獲取 v 的第一個鄰接頂點

    int GetFirstAdjVexPos(AMGraph* pg, VertexType v)
    {assert(pg);int pos = GetVetexPos(pg, v);if (pos == -1)return -1;for (int j = 0; j < pg->vSize; ++j){if (pg->edges[pos][j] != 0)return j;}return -1;
    }
  9. 獲取 v 的(相對于 w 的)下一個鄰接頂點

    int GetNextAdjVexPos(AMGraph* pg, VertexType v, VertexType w)
    {assert(pg);int pos1 = GetVetexPos(pg, v);int pos2 = GetVetexPos(pg, w);if (pos1 == -1 || pos2 == -1)return -1;for (int j = pos2 + 1; j < pg->vSize; ++j){if (pg->edges[pos1][j] != 0)return j;}return -1;
    }
  10. 銷毀

    void AMGraphDestroy(AMGraph* pg)
    {assert(pg);free(pg->vertices);pg->vertices = NULL;for (int i = 0; i < pg->capacity; ++i){free(pg->edges[i]);pg->edges[i] = NULL;}free(pg->edges);pg->edges = NULL;pg->vSize = pg->eSize = pg->capacity = 0;
    }


四、Test.c

#include "AMGraph.h"
#include <stdio.h>int main()
{AMGraph g;AMGraphInit(&g); InsertVertex(&g, 'A');InsertVertex(&g, 'B');InsertVertex(&g, 'C');InsertVertex(&g, 'D');InsertVertex(&g, 'E');InsertEdge(&g, 'A', 'B');InsertEdge(&g, 'A', 'D');InsertEdge(&g, 'B', 'C');InsertEdge(&g, 'B', 'E');InsertEdge(&g, 'C', 'D');InsertEdge(&g, 'C', 'E');ShowAdjMatrix(&g);printf("\n");EraseVertex(&g, 'C');ShowAdjMatrix(&g);printf("\n");EraseEdge(&g, 'A', 'B');ShowAdjMatrix(&g);printf("\n");printf("%d\n", GetFirstAdjVexPos(&g, 'A'));  // 3printf("%d\n", GetNextAdjVexPos(&g, 'A', 'D'));  // -1AMGraphDestroy(&g);return 0;
}

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

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

相關文章

SpringCloud網關介紹

一、Gateway簡介 1、官網 上一代zuul 1.X&#xff1a;https://github.com/Netflix/zuul/wiki 當前gateway&#xff1a;https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/ 2、是什么 SpringCloud Gateway是SpringCloud的一個全…

.NET Core 依賴注入 Microsoft.Extensions.DependencyInjection

文章目錄 前言什么是依賴注入C# 使用依賴注入框架介紹 Microsoft.Extensions.DependencyInjectionNuget安裝簡單單例使用打印結果 自動裝配舉例自動裝配測試用例打印結果自動裝配執行順序測試用例有歧義構造函數漸進式構造函數循環依賴 自動裝配結論 手動裝配手動注入別名注入 …

Git:版本控制的藝術與實踐

引言&#xff1a; 在軟件開發領域&#xff0c;版本控制是至關重要的一環。它幫助我們跟蹤代碼的變化、管理團隊協作、回溯歷史記錄以及解決沖突等。而Git作為目前最流行的分布式版本控制系統&#xff0c;已經成為了開發者們的必備工具。本文將深入探討Git的核心概念、常用命令以…

使用Docker安裝Superset并設置Oracle訪問和使用PG作Meta數據庫

一、安裝 Docker 安裝一個linux&#xff0c;可以是Centos或Ubuntu&#xff0c;如果是Centos 7.X&#xff0c;那么要注意先將系統自帶的docker先刪除。下文以Centos7.9為例 #刪除自帶的不完整版本 yum remove docker docker-client docker-client-latest \docker-common docker-…

調用win32 api獲取電腦名字和系統目錄

學習一下幾個函數的功能&#xff0c;和調用方式&#xff1b; void CBasenameView::OnDraw(CDC* pDC) {CBasenameDoc* pDoc GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereCString str1;TCHAR myname1[50], myname2[50], mydirname1[50], myd…

常見的Linux系統版本

在介紹常見的Linux系統版本之前&#xff0c;首先需要區分Linux系統內核與Linux發行套件系統的不同。Linux系統內核指的是一個由Linus Torvalds負責維護&#xff0c;提供硬件抽象層、硬盤及文件系統控制及多任務功能的系統核心程序。而Linux發行套件系統是我們常說的Linux操作系…

【Vue+Python】—— 基于Vue與Python的圖書管理系統

文章目錄 &#x1f356; 前言&#x1f3b6;一、項目描述?二、項目展示&#x1f3c6;三、撒花 &#x1f356; 前言 【VuePython】—— 基于Vue與Python的圖書管理系統 &#x1f3b6;一、項目描述 描述&#xff1a; 本項目為《基于Vue與Python的圖書管理系統》&#xff0c;項目…

Minio保姆級教程

轉載自&#xff1a;www.javaman.cn Minio服務器搭建和整合 1、centos安裝minio 1.1、創建安裝目錄 mkdir -p /home/minio1.2、在線下載minio #進入目錄 cd /home/minio #下載 wget https://dl.minio.io/server/minio/release/linux-amd64/minio1.3、minio配置 1.3.1、添加…

Flutter筆記:滑塊及其實現分析1

Flutter筆記 滑塊分析1 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 郵箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/134900784 本文從設計角度&#…

SQL命令---刪除字段

介紹 使用sql語句刪除表字段。 命令 alter table 表名 drop 字段名;例子 刪除a表中的name字段。 alter table a drop name;下面是執行刪除后的表結構&#xff1a;

微服務實戰系列之通信

前言 掰個指頭數一數&#xff0c;博主的“微服務實戰系列”從無到有&#xff0c;從零走到了十五。如果比作時鐘&#xff0c;剛好走過了一刻度。 當初為什么要做這個系列&#xff0c;博主想了又想&#xff0c;私以為作為當下軟件領域的幾個“hot spot”之一&#xff0c;又乘著…

探秘機器學習核心邏輯:梯度下降的迭代過程 (圖文詳解)

一 需求解函數 f() 和 g()函數分別為求y值和求導數的函數。 目的&#xff1a;求該函數的最小值&#xff1a; 代碼&#xff1a; import numpy as np import matplotlib.pyplot as plt f lambda x : (x - 3.5) ** 2 - 4.5 * x 10 g lambda x : 2 * (x - 3.5) - 4.5x np.l…

架構LAMP

目錄 1.什么是LAMP 2.LAMP組成及作用 3.搭建Apache httpd服務 4.編譯安裝mysqld 服務 5.編譯安裝PHP 解析環境 6.安裝論壇 1.什么是LAMP LAMP架構是目前成熟的企業網站應用模式之一&#xff0c;指的是協同工作的一整套系統和相關軟件&#xff0c;能夠提供動態Web站點服務…

MATLAB算法實戰應用案例精講-【人工智能】漫談自動駕駛

目錄 常用數據集 一、自動駕駛領域數據集 1. KITTI數據集 2.CityScapes數據集 3.BDD100K數據集

go與ioc

在Go開發服務端程序時&#xff0c;使用IoC&#xff08;Inversion of Control&#xff09;機制并不像在Java等語言中那樣普遍。Go語言的設計哲學傾向于簡潔和直接&#xff0c;更注重代碼的可讀性和可維護性。 在Go中&#xff0c;通常會使用依賴注入&#xff08;Dependency Inje…

【Python】視頻剪輯小程序

近期遇到一些錄制的視頻需要剪輯。 手機上剪輯操作很耗時&#xff0c;有幾個G的視頻&#xff0c;花了一天的空余時間去剪輯。電腦上也有格式工廠&#xff0c;有很方便。 可是學了Pthon&#xff0c;又無意中了解到了moviepy這個庫&#xff0c;于是自己寫了個簡單的視頻剪輯程序。…

Windows安裝kafka

壓縮包下載地址&#xff1a;https://www.apache.org/dyn/closer.cgi?path/kafka/3.6.1/kafka_2.13-3.6.1.tgz 啟動kafka步驟 zookeeper-server-start.bat rem 閉命令提示符窗口的命令回顯&#xff0c;這樣在運行腳本時不會顯示腳本的具體命令內容 echo offrem 命令行啟動未…

Proteus仿真--8×8LED點陣屏仿電梯數字滾動顯示

本文介紹基于88LED點陣屏仿電梯數字滾動顯示設計&#xff08;完整仿真源文件及代碼見文末鏈接&#xff09; 仿真圖如下 其中K1-K5的5個按鍵分別代表不同樓層&#xff0c;摁下按鍵后在8X8LED上便會顯示到對應樓層的跳變信息&#xff0c;模擬電梯的運作 仿真運行視頻 Proteus仿…

nodejs多線程,fork和Worker

一、前言 javascript是單線程執行的&#xff0c;如果想要多線程執行&#xff0c;那么相當于再運行一個node,其實不該理解成多線程&#xff0c;更像是多進程。 二、Worker(‘worker_threads’模塊) worker有點類似exec&#xff0c;直接再cmd執行node命令&#xff0c;不同的是兩…

《安富萊嵌入式周報》第328期:自主微型機器人,火星探測器發射前失誤故障分析,微軟推出12周24期免費AI課程,炫酷3D LED點陣設計,MDK5.39發布

周報匯總地址&#xff1a;嵌入式周報 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬漢嵌入式論壇 - Powered by Discuz! 更新一期視頻教程&#xff1a; 【實戰技能】 單步運行源碼分析&#xff0c;一期視頻整明白FreeRTOS內核源碼框架和運行…