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

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

問題定義

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

書上的解法

書中對(duì)這個(gè)問題的分析是很清楚的,我嘗試用自己的方式簡(jiǎn)短覆述。

計(jì)算一個(gè)二叉樹的最大距離有兩個(gè)情況:

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

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

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

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

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

int?nMaxLen?=?0;

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

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

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

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

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

	//?計(jì)算左子樹最長(zhǎng)節(jié)點(diǎn)距離
	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;
	}

	//?計(jì)算右子樹最長(zhǎng)節(jié)點(diǎn)距離
	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;
	}

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

這段代碼有幾個(gè)缺點(diǎn):

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

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

#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;
}

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

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

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

測(cè)試代碼

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

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)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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