數據結構之圖

數據結構之線性表
數據結構之鏈表
數據結構之串
數據結構之圖
數據結構之排序算法

一、基本概念

在這裏插入圖片描述
圖是由頂點的有窮非空集合和頂點之間的集合組成,通常表示爲:G(V,E),其中G表示一個圖,V表示圖中邊的集合。
連通圖:圖中任意兩點都能連通。
帶權值的圖稱之爲網。
樹:沒有環路的連通圖。
生成樹:由n-1條邊將n個頂點連接成的連通圖。
最小生成樹:最小權值的生成樹稱爲最小生成樹。

二、圖的存儲結構

順序存儲:

  1. 鄰接矩陣
    在這裏插入圖片描述

鏈式存儲:

  1. 鄰接表
    在這裏插入圖片描述
  2. 十字鏈表
    在這裏插入圖片描述
    漫畫圖結構

三、算法

遍歷:從圖中某一頂點出發,依次訪問圖中其餘頂點,且每個頂點僅被訪問一次。

深度優先遍歷(DFS)

DFS原理:從圖中某個頂點出發,先訪問此頂點,再依次訪問它的每個未被訪問過的鄰接點,重複上述操作,直到所有頂點都被訪問。
DFS本質上就是樹的先序遍歷,需要增加一個訪問數組標記當前結點是否被訪問過,核心算法就是遞歸。

  1. 鄰接矩陣深度遍歷算法
void DFS(MGraph* G, int i){//深度遞歸遍歷
	visited[i] = true;
	printf("%c\n", G->vexter[i]);
	for(int j = 0; j < G-->num_vertex; j++){
		if(G->arc[i][j] == 1 && !visit[j]){	
			DFS(G, j);		
		}
	}
}

void DFSTraverse(MGraph* G){//深度優先遍歷
	int i = 0;
	for(i = 0; i < G->num_vertex; i++){
		visited[i] = false; //初始化訪問數組
	}
	for( i = 0; i < G->num_vertex; i++){ 
		if(!visited[i]){
			DFS(G, i); //非連通圖設計,連通圖只執行一次
		}
	}
}

時間複雜度爲O(n2)

  1. 鄰接表深度遍歷算法
void DFS(MGraph* G, int i){
	EdgeNode* p;
	visted[i] = true;
	printf("%d\n", G->adjl[i].data);
	p = G->firstedge;
	while(p){
		if(!visited[p->adjvex]){
			DFS(G, p-adjvex);
		}			
		p = p->next;
	}
}

void DFSTraversal(MGraph* G){
	for(int i = 0; i < G->num_vertex; i++){
		vidited[i] = false;
	}
	for(int i = 0; i < G->num_vertex; i++){
		if(!visited[i]){
			DFS(G, i);
		}
	}
}

時間複雜度爲O(n + e)

廣度優先遍歷(BFS)

時間複雜度和DFS相同

  1. 鄰接矩陣廣度優先遍歷
void BFSTraverse(GL* G) {
	int i = 0, j = 0;
	Queue Q;
	InitQueue(Q);
	for (i = 0; i < G->num_vertex; i++) {
		visited[i] = false;
	}
	for (i = 0; i < G->num_vertex; i++) {
		if (!visited[i]) {
			visited[i] = true;
			printf("%c\n", G->vexs[i]);
			Enqueue(Q, i);
			while (!Empty(Q)) {
				Dequeue(Q, &i);
				for (int j = 0; j < G->num_vertexs; j++) {
					if ((G->arc[i][j] == 1) && (!visited[j])) {
						visited[j] = true;
						printf("%c\n", G->vexs[j]);
						Enqueue(Q, j);
					}
				}
			}
		} 		
	}	
}

  1. 鄰接表廣度優先遍歷
int BFSTraverse(GL* G) {
	EdgeNode* p = NULL;
	int i = 0;
	Queue Q;
	InitQueue(Q);
	for (i = 0; i < G->num_vertex; i++) { //訪問數組初始化
		visited[i] = false;
	}
	for (i = 0; i < G->num_vertex; i++) { //訪問所有頂點
		if (!visited[i]) {
			visited[i] = true;
			printf("%c\n", G->vertex.data); //訪問頂點
			EnQueue(Q, i);
			while (!QueueEmpty(Q)) {
				Dequeue(Q, &i);
				p = G->adjList[i].firstedge; //訪問鄰接點
				while (p) {
					if (!visited[p->adjvex]) {
						visited[p->adjvex] = true;
						printf("%c\n", G->adjList[p->adjvex].data);
						EnQueue(Q, p->adjvex);
					}
					p = p->next;
				}
			}
		}
	}
}

最小生成樹算法

  1. Prim算法是走一步看一步的思維方式。從任意一個頂點出發,每次添加最短邊,逐步生成最小生成樹。
    時間複雜度爲O(n2),適合稠密圖算法。
  2. Kruskal算法是全局思維方式。直接從最短邊開始,每次添加最短邊。
    時間複雜度爲O(elbe),適合稀疏圖算法

最短路徑算法

  1. 迪傑斯特拉算法
  2. 弗洛伊德算法

關鍵路徑算法

發佈了84 篇原創文章 · 獲贊 12 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章