主頁 > 軟體設計 > 【資料結構與演算法拓展】最短路徑的方案數統計問題(基于floyd演算法)

【資料結構與演算法拓展】最短路徑的方案數統計問題(基于floyd演算法)

2020-12-16 13:40:49 軟體設計

前言

資料結構,一門資料處理的藝術,精巧的結構在一個又一個演算法下發揮著他們無與倫比的高效和精密之美,在為資訊技術打下堅實地基的同時,也令無數開發者和探索者為之著迷,

也因如此,它作為博主大二上學期最重要的必修課出現了,由于大家對于上學期C++系列博文的支持,我打算將這門課的筆記也寫作系列博文,既用于整理、消化,也用于同各位交流、展示資料結構的美,

此系列文章,將會分成兩條主線,一條“資料結構基礎”,一條“資料結構拓展”,“資料結構基礎”主要以記錄課上內容為主,“拓展”則是以課上內容為基礎的更加高深的資料結構或相關應用知識,

歡迎關注博主,一起交流、學習、進步,往期的文章將會放在文末,


隨著學習的深入,相信各位讀者的野心已經僅滿足于計算出任意兩點間的最短路徑,那么更進一步的,在這一節我們要討論關于最短路徑的計數問題,在計算出任意兩點間的最短路徑長度的基礎上,我們還需要統計出這些最短路徑的方案數,

這個問題,乍一看感覺有些不同尋常,因為不管怎么說,方案數相較于長度來說總還是不好把握的,我們在思考統計方案數的演算法的時候總是容易囿于對起點到終點路徑規劃決策的模擬,

樸素的解決思路多是先在紙上推演從一起點到終點的路徑,一條一條的畫出最短路徑,小規模的時候,找出答案不是難事,但是一旦資料量較大,筆算就會漏洞百出,更何況一旦準備將其付諸于程式,就像是秀才遇到兵,發現根本無從下手,,,,
在這里插入圖片描述
所以解決問題的關鍵就是要跳出樸素的思維方式,用一種新的視角來審視這個問題,不妨先從回顧計算最短路徑長度的演算法開始,

floyd演算法求最短路徑

任意兩點間的最短路徑問題,解決的方案是選擇不停地列舉中間點來對路徑進行“松弛”,讓各點之間不斷挑選更優的路徑從而將距離邊的更短,

如下圖,對于點對14來說,可以經由中間點2,走1->2->4這條更短的路徑,
在這里插入圖片描述

當然,能用來更新最短路徑的中間點也可以不是直接相連的頂點,例如下圖:
在這里插入圖片描述
點對15的最短路徑可能由3更新成為5,不過在此之前,13和35的距離應該分別被2和4更新成為2.

可以看到,在這個問題中,有個關鍵的狀態定義,點對 ( i , j ) (i,j) (i,j)之間的最短路徑長度 d i j d_{ij} dij?

這個定義讓我們只關心點與點之間的路徑長度關系而非具體路徑,

進一步的,根據這個狀態定義,可以找到狀態間轉移方案:經過中間點k的點對ij的最短路徑就是:
d i j = m i n ( d i k + d k j , d i j ) d_{ij}=min(d_{ik}+d_{kj},d_{ij}) dij?=min(dik?+dkj?,dij?)
那么在演算法的初始,將最短路徑長度初始化
d i i = 0 d_{ii}=0 dii?=0
d i j = i n f ( i j 之 間 沒 有 邊 相 連 ) d_{ij}=inf\ (ij之間沒有邊相連) dij?=inf (ij)
d i j = l e n i j ( i j 之 間 有 長 度 為 l e n i j 的 邊 鏈 接 ) d_{ij}=len_{ij}\ (ij之間有長度為len_{ij}的邊鏈接) dij?=lenij? (ijlenij?)

于是這個最短路徑長度的演算法問題就可以解了,步驟如下:

  • 依次列舉所有中間節點k,更新其余點對
  • 列舉非中間節點的點對ij
  • 使用中間節點k對ij之間的最短路徑長度進行松弛

代碼實作如下:

int dis[N][N];//最短路徑陣列,ij最短路徑為dis[i][j]
void floyd(int n){
	for(int k = 1;k <= n;k++){//列舉中間節點
		for(int i = 1;i <= n;i++){//列舉非中間節點的點對
			if(i == k)continue;
			for(int j = i + 1;j <= n;j++){
				if(j == k)continue;
				if(dis[i][j] > dis[i][k] + dis[k][j]){//松弛最短路徑
					dis[i][j] = dis[i][k] + dis[k][j];
					dis[j][i] = dis[i][k] + dis[k][j];
				}
			}
		}
	}
}

兩點間最短路徑方案數

要統計最短路徑的方案數,沒有最短路徑長度肯定是不行的,所以以下的演算法要建立在floyd演算法之上,也就是說,方案數問題要在floyd的程序中順手解決

前面說過,要解決最短路徑的方案數統計問題,我們要跳出樸素的思維方案,借鑒最短路徑長度的建模分析方法,

不知各位是否注意到了上文在分析最短路徑演算法時標記出了三個模塊,他們分別是:
狀 態 、 轉 移 、 初 始 化 狀態、轉移、初始化 這是解決路徑長度問題的關鍵所在,也就是常常提到floyd用到的動態規劃思想

現在我們可以從動態規劃的角度借助這三個模塊依葫蘆畫瓢來分析最短路徑方案數的問題,(當然這里對狀態和轉移的描述未必在學術上嚴謹,主要是便于分析解決問題,)

定狀態

依照最短路徑的狀態 d i j d_{ij} dij?,我們定義:
點 對 ( i , j ) 之 間 的 最 短 路 徑 方 案 數 = c i j 點對(i,j)之間的最短路徑方案數=c_{ij} (i,j)=cij?(c取自count單詞首字母)

有了這個定義,在任意兩點間最短路方案數方面,用一個狀態便可以忽略具體的路徑方案,將方案數量一言以蔽之,

找轉移

定義了狀態之后,我們迫切的想知道在使用中間點k松弛點對ij時,最短路徑的方案數狀態會如何轉移,

首先一點,路徑的計算應該滿足乘法原理,即:
點 對 ( i , j ) 經 過 點 k 的 最 短 路 徑 方 案 數 = c i k × c j k 點對(i,j)經過點k的最短路徑方案數=c_{ik}\times c_{jk} (i,j)k=cik?×cjk?
舉個例子,如下圖:
在這里插入圖片描述

對于中間節點4,點對17之間的最短路徑方案數為 2 × 2 = 4 2\times2=4 2×2=4(14方案數為2,47方案數為2)

乘法原理這里很好理解,就不再贅述了,下面的問題就是在進行floyd演算法程序中,計算出來的方案數要怎么進行轉移,這個問題要拆成三種情況來討論:

  1. 當經過k不能使得i到j已知路徑更短,即 d i j < d i k + d k j d_{ij} < d_{ik}+d_{kj} dij?<dik?+dkj?,此次松弛無效,不改變方案數 c i j c_{ij} cij?
  2. 當經過k的最短路徑長度等于已知路徑長度,即 d i j = d i k + d k j d_{ij} = d_{ik}+d_{kj} dij?=dik?+dkj?,i到j的方案應該加上從k走的方案數,即 c i j = c i j + c i k × c k j c_{ij}=c_{ij}+c_{ik}\times c_{kj} cij?=cij?+cik?×ckj?
  3. 當經過k的最短路徑長度小于已知路徑長度,即 d i j > d i k + d k j d_{ij} > d_{ik}+d_{kj} dij?>dik?+dkj?,i到j之前的方案應該作廢而只算從k走的方案數,即 c i j = c i k × c k j c_{ij}=c_{ik}\times c_{kj} cij?=cik?×ckj?

于是,狀態轉移的問題也就解決了

初始化

方案數的初始化方法就是給每個有邊的點對之間只能通過這條邊到達,方案數置1,否則不能到達,置0

實作

有了上面的鋪墊,下面就可以大刀闊斧的開始計算最短路徑的方案數了,

步驟如下:

  • 初始化方案數矩陣
  • 執行floyd演算法,在松弛程序中同時轉移方案數
    1. 當經過k不能使得i到j已知路徑更短,即 d i j < d i k + d k j d_{ij} < d_{ik}+d_{kj} dij?<dik?+dkj?,此次松弛無效,不改變方案數 c i j c_{ij} cij?
    1. 當經過k的最短路徑長度等于已知路徑長度,即 d i j = d i k + d k j d_{ij} = d_{ik}+d_{kj} dij?=dik?+dkj?,i到j的方案應該加上從k走的方案數,即 c i j = c i j + c i k × c k j c_{ij}=c_{ij}+c_{ik}\times c_{kj} cij?=cij?+cik?×ckj?
    1. 當經過k的最短路徑長度小于已知路徑長度,即 d i j > d i k + d k j d_{ij} > d_{ik}+d_{kj} dij?>dik?+dkj?,i到j之前的方案應該作廢而只算從k走的方案數,即 c i j = c i k × c k j c_{ij}=c_{ik}\times c_{kj} cij?=cik?×ckj?

實作起來也不難,改動一下上文的代碼:

int dis[N][N];//最短路徑長度矩陣
int cnt[N][N];//最短路徑計數矩陣
void floyd(int n){
	for(int k = 1;k <= n;k++){//列舉中間節點
		for(int i = 1;i <= n;i++){//列舉非中間節點點對
			if(i == k)continue;
			for(int j = i + 1;j <= n;j++){
				if(j == k)continue;
				if(dis[i][j] == dis[i][k] + dis[k][j]){//當經過中間點最短距離相等,方案數相加
					cnt[i][j] += cnt[i][k] * cnt[k][j];
					cnt[j][i] += cnt[i][k] * cnt[k][j];
				}else if(dis[i][j] > dis[i][k] + dis[k][j]){//當經過中間點最短距離更小,之前方案數歸零,計經過k的方案數
					dis[i][j] = dis[i][k] + dis[k][j];
					dis[j][i] = dis[i][k] + dis[k][j];
					cnt[i][j] = cnt[i][k] * cnt[k][j];
					cnt[j][i] = cnt[i][k] * cnt[k][j];
				}
			}
		}
	}
}

讓我們來擬定一個需求,測驗這個場景:

給定n個頂點和m條邊,求出任意兩點間的最短路徑長度和方案數

#include<iostream>
using namespace std;
int dis[105][105];
int cnt[105][105];
const int inf = 1 << 29;

void floyd(int n){
	for(int k = 1;k <= n;k++){//列舉中間節點
		for(int i = 1;i <= n;i++){//列舉非中間節點點對
			if(i == k)continue;
			for(int j = i + 1;j <= n;j++){
				if(j == k)continue;
				if(dis[i][j] == dis[i][k] + dis[k][j]){//當經過中間點最短距離相等,方案數相加
					cnt[i][j] += cnt[i][k] * cnt[k][j];
					cnt[j][i] += cnt[i][k] * cnt[k][j];
				}else if(dis[i][j] > dis[i][k] + dis[k][j]){//當經過中間點最短距離更小,之前方案數歸零,計經過k的方案數
					dis[i][j] = dis[i][k] + dis[k][j];
					dis[j][i] = dis[i][k] + dis[k][j];
					cnt[i][j] = cnt[i][k] * cnt[k][j];
					cnt[j][i] = cnt[i][k] * cnt[k][j];
				}
			}
		}
	}
}

int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	
	for(int i = 1;i <= n;i++){//初始化距離和計數矩陣
		for(int j = 1;j <= n;j++){
			dis[i][j] = inf;
			cnt[i][j] = 0;
		}
		dis[i][i] = 0;
	}
	
	for(int i = 0,x,y,l;i < m;i++){//讀入m條邊
		scanf("%d%d%d",&x,&y,&l);
		dis[x][y] = l;
		dis[y][x] = l;
		cnt[x][y] = 1;
		cnt[y][x] = 1;
	}
	
	floyd(n);//floyd演算法計算長度和計數
	
	/*列印長度資訊和計數資訊*/
	printf("最短路徑長度矩陣:\n");
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			printf("%-3d",dis[i][j] == inf ? -1 : dis[i][j]);
		}
		printf("\n");
	}
	printf("最短路徑計數矩陣:\n");
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			printf("%-3d",cnt[i][j]);
		}
		printf("\n");
	}
} 

進行一個測驗樣例:
在這里插入圖片描述

經過指定頂點的最短路徑數

好的,現在經過改進過的floyd演算法,我們可以統計出任意兩點間的最短路徑數量了,那么接下來我們還想知道另一個問題:如何統計兩點間經過指定中間頂點的最短路徑方案數

其實有了前面的鋪墊,這個問題就變得很簡單,我們模仿上面的套路,不妨先給個狀態定義:
點 對 ( i , j ) 之 間 經 過 中 間 頂 點 k 的 最 短 路 徑 方 案 數 = c i j k 點對(i,j)之間經過中間頂點k的最短路徑方案數=c_{ij}^k (i,j)k=cijk?

那么狀態的轉移如下:

  • 當ij之間存在經過k的最短路徑,有 d i j = d i k + d k j d_{ij} =d_{ik}+d_{kj} dij?=dik?+dkj?,方案數 c i j k = c i k × c k j c_{ij}^k=c_{ik}\times c_{kj} cijk?=cik?×ckj?(還記的上文的乘法原理嗎?)
  • 當ij之間不存在經過k的最短路徑,即 d i j < d i k + d k j d_{ij} <d_{ik}+d_{kj} dij?<dik?+dkj?,方案數 c i j k = 0 c_{ij}^k=0 cijk?=0

于是乎這個問題就解決了~


往期博客

  • 【資料結構基礎】資料結構基礎概念
  • 【資料結構基礎】線性資料結構——線性表概念 及 陣列的封裝
  • 【資料結構基礎】線性資料結構——三種鏈表的總結及封裝
  • 【資料結構基礎】線性資料結構——堆疊和佇列的總結及封裝(C和java)
  • 【演算法與資料結構基礎】模式匹配問題與KMP演算法
  • 【資料結構與演算法基礎】二叉樹與其遍歷序列的互化 附代碼實作(C和java)
  • 【資料結構與演算法拓展】 單調佇列原理及代碼實作
  • 【資料結構基礎】圖的存盤結構
  • 【資料結構與演算法基礎】并查集原理、封裝實作及例題決議(C和java)
  • 【資料結構與演算法拓展】二叉堆原理、實作與例題(C和java)
  • 【資料結構與演算法基礎】哈夫曼樹與哈夫曼編碼(C++)
  • 【資料結構與演算法基礎】最短路徑問題
  • 【資料結構與演算法基礎】堆排序原理及實作
  • 【資料結構與演算法基礎】最小生成樹演算法原理及實作
  • 【資料結構基礎】圖的遍歷方法與應用
  • 【資料結構基礎】矩陣的存盤結構,陣列,三元組表及十字鏈表
  • 【資料結構與演算法基礎】拓撲排序與AOV網路
  • 【資料結構與演算法基礎】AOE網路與關鍵路徑
  • 【資料結構與演算法基礎】樹與二叉樹的互化

參考資料:

  • 《資料結構》(劉大有,楊博等編著)
  • 《演算法導論》(托馬斯·科爾曼等編著)
  • 《圖解資料結構——使用Java》(胡昭民著)
  • OI WiKi

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/235535.html

標籤:其他

上一篇:第三屆泰迪杯技能賽賽后分享總結

下一篇:C++高并發網路架構與實作——第五篇

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more