當(dāng)前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀]昨天花了一個晚上為《編程之美》,在豆瓣寫了一篇書評《遲來的書評和感想──給喜愛編程的朋友》。書評就不轉(zhuǎn)載到這里了,取而代之,在這里介紹書里其中一條問題的另一個解法。這個解法比較簡短易讀及降低了空間復(fù)雜

昨天花了一個晚上為《編程之美》,在豆瓣寫了一篇書評《遲來的書評和感想──給喜愛編程的朋友》。書評就不轉(zhuǎn)載到這里了,取而代之,在這里介紹書里其中一條問題的另一個解法。這個解法比較簡短易讀及降低了空間復(fù)雜度,或者可以說覺得比較「美」吧。

問題定義

如果我們把二叉樹看成一個圖,父子節(jié)點之間的連線看成是雙向的,我們姑且定義"距離"為兩節(jié)點之間邊的個數(shù)。寫一個程序求一棵二叉樹中相距最遠的兩個節(jié)點之間的距離。

書上的解法

書中對這個問題的分析是很清楚的,我嘗試用自己的方式簡短覆述。

計算一個二叉樹的最大距離有兩個情況:

情況A: 路徑經(jīng)過左子樹的最深節(jié)點,通過根節(jié)點,再到右子樹的最深節(jié)點。情況B: 路徑不穿過根節(jié)點,而是左子樹或右子樹的最大距離路徑,取其大者。

只需要計算這兩個情況的路徑距離,并取其大者,就是該二叉樹的最大距離。

我也想不到更好的分析方法。

但接著,原文的實現(xiàn)就不如上面的清楚 (源碼可從這里下載):

//?數(shù)據(jù)結(jié)構(gòu)定義
struct?NODE
{
	NODE*?pLeft;???????	//?左子樹
	NODE*?pRight;??????	//?右子樹
	int?nMaxLeft;??????	//?左子樹中的最長距離
	int?nMaxRight;?????	//?右子樹中的最長距離
	char?chValue;????	//?該節(jié)點的值
};

int?nMaxLen?=?0;

//?尋找樹中最長的兩段距離
void?FindMaxLen(NODE*?pRoot)
{
	//?遍歷到葉子節(jié)點,返回
	if(pRoot?==?NULL)
	{
		return;
	}

	//?如果左子樹為空,那么該節(jié)點的左邊最長距離為0
	if(pRoot?->?pLeft?==?NULL)
	{
		pRoot?->?nMaxLeft?=?0;?
	}

	//?如果右子樹為空,那么該節(jié)點的右邊最長距離為0
	if(pRoot?->?pRight?==?NULL)
	{
		pRoot?->?nMaxRight?=?0;
	}

	//?如果左子樹不為空,遞歸尋找左子樹最長距離
	if(pRoot?->?pLeft?!=?NULL)
	{
		FindMaxLen(pRoot?->?pLeft);
	}

	//?如果右子樹不為空,遞歸尋找右子樹最長距離
	if(pRoot?->?pRight?!=?NULL)
	{
		FindMaxLen(pRoot?->?pRight);
	}

	//?計算左子樹最長節(jié)點距離
	if(pRoot?->?pLeft?!=?NULL)
	{
		int?nTempMax?=?0;
		if(pRoot?->?pLeft?->?nMaxLeft?>?pRoot?->?pLeft?->?nMaxRight)
		{
			nTempMax?=?pRoot?->?pLeft?->?nMaxLeft;
		}
		else
		{
			nTempMax?=?pRoot?->?pLeft?->?nMaxRight;
		}
		pRoot?->?nMaxLeft?=?nTempMax?+?1;
	}

	//?計算右子樹最長節(jié)點距離
	if(pRoot?->?pRight?!=?NULL)
	{
		int?nTempMax?=?0;
		if(pRoot?->?pRight?->?nMaxLeft?>?pRoot?->?pRight?->?nMaxRight)
		{
			nTempMax?=?pRoot?->?pRight?->?nMaxLeft;
		}
		else
		{
			nTempMax?=?pRoot?->?pRight?->?nMaxRight;
		}
		pRoot?->?nMaxRight?=?nTempMax?+?1;
	}

	//?更新最長距離
	if(pRoot?->?nMaxLeft?+?pRoot?->?nMaxRight?>?nMaxLen)
	{
		nMaxLen?=?pRoot?->?nMaxLeft?+?pRoot?->?nMaxRight;
	}
}

這段代碼有幾個缺點:

算法加入了侵入式(intrusive)的資料nMaxLeft, nMaxRight使用了全局變量 nMaxLen。每次使用要額外初始化。而且就算是不同的獨立資料,也不能在多個線程使用這個函數(shù)邏輯比較復(fù)雜,也有許多 NULL 相關(guān)的條件測試。我的嘗試

我認為這個問題的核心是,情況A?及 B 需要不同的信息: A 需要子樹的最大深度,B 需要子樹的最大距離。只要函數(shù)能在一個節(jié)點同時計算及傳回這兩個信息,代碼就可以很簡單:

#includeusing?namespace?std;

struct?NODE
{
	NODE?*pLeft;
	NODE?*pRight;
};

struct?RESULT
{
	int?nMaxDistance;
	int?nMaxDepth;
};

RESULT?GetMaximumDistance(NODE*?root)
{
	if?(!root)
	{
		RESULT?empty?=?{?0,?-1?};	//?trick:?nMaxDepth?is?-1?and?then?caller?will?plus?1?to?balance?it?as?zero.
		return?empty;
	}

	RESULT?lhs?=?GetMaximumDistance(root->pLeft);
	RESULT?rhs?=?GetMaximumDistance(root->pRight);

	RESULT?result;
	result.nMaxDepth?=?max(lhs.nMaxDepth?+?1,?rhs.nMaxDepth?+?1);
	result.nMaxDistance?=?max(max(lhs.nMaxDistance,?rhs.nMaxDistance),?lhs.nMaxDepth?+?rhs.nMaxDepth?+?2);
	return?result;
}

計算 result 的代碼很清楚;nMaxDepth 就是左子樹和右子樹的深度加1;nMaxDistance 則取 A 和 B 情況的最大值。

為了減少 NULL 的條件測試,進入函數(shù)時,如果節(jié)點為 NULL,會傳回一個 empty 變量。比較奇怪的是 empty.nMaxDepth = -1,目的是讓調(diào)用方 +1 后,把當(dāng)前的不存在的 (NULL) 子樹當(dāng)成最大深度為 0。

除了提高了可讀性,這個解法的另一個優(yōu)點是減少了 O(節(jié)點數(shù)目) 大小的侵入式資料,而改為使用 O(樹的最大深度) 大小的??臻g。這個設(shè)計使函數(shù)完全沒有副作用(side effect)。

測試代碼

以下也提供測試代碼給讀者參考 (頁數(shù)是根據(jù)第7次印刷,節(jié)點是由上至下、左至右編號):

void?Link(NODE*?nodes,?int?parent,?int?left,?int?right)
{
	if?(left?!=?-1)
		nodes[parent].pLeft?=?&nodes[left];?

	if?(right?!=?-1)
		nodes[parent].pRight?=?&nodes[right];
}

void?main()
{
	//?P.?241?Graph?3-12
	NODE?test1[9]?=?{?0?};
	Link(test1,?0,?1,?2);
	Link(test1,?1,?3,?4);
	Link(test1,?2,?5,?6);
	Link(test1,?3,?7,?-1);
	Link(test1,?5,?-1,?8);
	cout?<<?"test1:?"?<<?GetMaximumDistance(&test1[0]).nMaxDistance?<<?endl;

	//?P.?242?Graph?3-13?left
	NODE?test2[4]?=?{?0?};
	Link(test2,?0,?1,?2);
	Link(test2,?1,?3,?-1);
	cout?<<?"test2:?"?<<?GetMaximumDistance(&test2[0]).nMaxDistance?<<?endl;

	//?P.?242?Graph?3-13?right
	NODE?test3[9]?=?{?0?};
	Link(test3,?0,?-1,?1);
	Link(test3,?1,?2,?3);
	Link(test3,?2,?4,?-1);
	Link(test3,?3,?5,?6);
	Link(test3,?4,?7,?-1);
	Link(test3,?5,?-1,?8);
	cout?<<?"test3:?"?<<?GetMaximumDistance(&test3[0]).nMaxDistance?<<?endl;

	//?P.?242?Graph?3-14
	//?Same?as?Graph?3-2,?not?test

	//?P.?243?Graph?3-15
	NODE?test4[9]?=?{?0?};
	Link(test4,?0,?1,?2);
	Link(test4,?1,?3,?4);
	Link(test4,?3,?5,?6);
	Link(test4,?5,?7,?-1);
	Link(test4,?6,?-1,?8);
	cout?<<?"test4:?"?<<?GetMaximumDistance(&test4[0]).nMaxDistance?<<?endl;
}
本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉