🌹【成住壞空,依緣生滅】
我們常把「美」與「醜」、「外表」與「內在」,看做成「二元對立」的比較組,於是出現「色衰」與「愛弛」、「胸大」與「無腦」的因果關係。接著對「不愛的人」發「好人卡」,然後被心中自以為所愛的人,用壞的態度對待及折磨,竟還誤以為這就是愛的本質。
《心經》中「色不異空,空不異色,色即是空,空即是色」,其中「色」與「空」之所以沒有差別,是因為一切都因緣相生。
在佛法中的「空」,並非完全沒有、不存在;而是因為所有的形貌,都在不斷改變,不會恆久存在。只要能理解「因緣性空」的道理,就不會過度執著於外貌,被人或事情的表象,牽著鼻子走,憑當下一時片面的印象,就給予好或壞的價值判斷,甚至產生貪婪或恐懼的心念。
「花開」與「花落」只是生命型態表現的改變,如同「種子」與「大樹」,雖然形貌差異甚大,但都只是依緣而生,就生命的本質來說,兩者其實是一樣的。
眼見「花開」與「花落」,心生傷春悲秋的感觸,這固然可以是當下很自然由衷升起的浪漫情懷,但不要繼續沉溺於傷春悲秋裡,一旦抓著情緒不放,就是過度了,也執著了,必須要提醒自己,認清楚生命的本質,了解「色」與「空」都是依緣而生,只要接納臣服,就不會耗損不必要的心力,阻擋生命該有的行進。
所以,延續這個教導的推理,我們可以得到以下的啟發:
不要因為形貌的差異,就輕易地忽視種子的力量,也不要過度仰賴大樹的倚靠。正如「美」與「醜」,只不過是我們對外貌變化的相對定義,並不是真正的實相。不要被美麗的事物誘惑,也不要歧視醜陋的外觀。
🌿摘錄自若權《先放手;再放心——我從〔心經〕學到的人生智慧》 博客來:https://bit.ly/3Bxjjrv
🌿每本書內頁都有附贈若權親自設計《心經》手抄稿紙,與若權親筆示範抄寫《心經》
🌿抄寫《心經》同學們,今日(9/19)若要交功課,歡迎放置於此文下方喔。我今天的作業是77/108,你呢?
同時也有1部Youtube影片,追蹤數超過7萬的網紅在地上滾的工程師 Nic,也在其Youtube影片中提到,硬核的知識也許不是每個工程師都能夠在職涯發展中完全運用到,但無論是本科系、轉職、自學成為工程師的朋友,都應該要知道,這些紮實的背景知識提早學習起來,在未來的日子裡,只有好沒有壞。 就透過本影片我的真實經驗分享,告訴你這些我在大學時期看似枯燥乏味的理論,其實就是程式設計內功,而日後沉睡已久的內功卻又...
完全二元樹 在 無待堂 Facebook 的最佳解答
【明星與女巫】
.1 女孩們
這個城市庇護難民。入夜之後由於人工照射過於光猛,連星星都看不見,城市反而成為星星的海洋。在外人眼中,這裡豪華得不像難民營。
這些都是倒影在玻璃屏的倒影,1 分鐘之前,Alice 不小心通過一台 Panasonic CF90 登入了政府網絡,並不小心修改了人口普查紀錄,將自己從「未普查」修改為「已普查」。她是一個業餘上網者,也不是想偷竊政府的甚麼資料,只是想測試一下能否做到。然後她發現並沒想像中的困難,於是找了一個無關痛癢的地方作了修改,就當是一句不顯眼的「到此一遊」。
她懷疑在 C 區像她這樣的人有多少,也許沒有。她比較願意相信自己是特別的,這令她沒有那麼不自在。她瞄瞄電腦中的時間,三個八婆應該差不多已來到。芝芝、Keiko、冬菇頭,這是她同系的同學和朋友。這三個人看中 Alice 的電腦,在 C 區,速度夠快的電腦並不常見。而她們最近迷一個外面的男明星,叫 David,就這樣,所以她們需要夠快的網絡和電腦連接外面的網絡。Alice 千叮萬囑她們不能向其他人透露關於上網的事。
據說是在上世紀的一場大戰,具有VR 彩現能力和短期洗腦能力的高速電腦結構被定義為戰略物資,在戰後的難民營,管有高速運算機亦需要持牌。Alice 一開始認知到犯法,但上網可以看到的東西實在太多,後來她開始認為自己合法擁有它,只不過沒有文書——她對自己這樣辯解。
但具體上,她可以被控無牌管有高速運算機。
一般人根本不知道這種機器屬於戰略物資,C 區大部份人口都是科技文盲,會以為它是其他大戰前的科技產物。她向父親這樣解釋這台機器:這是一台科技文物,它主要的功能是進行類似「貪食蛇」或是「接龍」的小遊戲程式,父親顯然不懂,所以就接受了它搬入房中。她也為這台機器寫了一個反跟蹤程式,她不想別人知道她在上網。
透過仍在地球軌道運行的殘存衛星,這台運算器可以透過一種在 21 世紀初開始流行的技術——全球 Wifi——接收到訊號。
相反,C 區下達消息以實體報刊為主,近年政府也實際出資建立了電視、電台,但那不是她在網絡存庫看到的世界。這個地方誕生,就因為那場因為互聯網而爆發的毀滅性戰爭,所以大家都被灌輸了「上網行為必須嚴格管制」的文化,還有相關的一大堆一般人進入不了的防火牆。
透過斷斷續續的收發,可以讀到不少殘存的網絡檔案庫。聽說大戰後的人開始重建各地網絡,修復以前的資料。關於之前的一切像朦朧的月亮,始終是模糊不清。國際聯盟認為,對 A 區至其餘各區的長期難民人口來說,全面享受互聯網人權的人口少於 5%。這當然是一個約數,很多人也可以用互聯網,這主要是擁有權力的人、金融政府機關、有錢的難民,或者像 Alice 一樣不正當得到工具的。這個消息,並沒有在 C 區報道或廣播過。
芝芝、Keiko、冬菇頭是能夠守秘密的人嗎?她會這樣想。
她們帶著一些外賣和——紅酒——前來,還有一個小箱放她們的睡衣。芝芝一家來到這裡以前,是一個美國人。這真是一個令人懷舊的名字。她放下之後,大動作擁抱她,說著路上許多的不便。然後她望著那台機器,「已經開動了啊?就像上次一樣,很讚。」芝芝說。她們放下行裝之後就開始上網,Alice 第二次讓芝芝操作,她已經在搜索關於 David 要破天荒走入難民營開音樂會的消息。
冬菇頭據她自己說,她一家來自亞洲某個國家,因此她被定義為亞洲人的方式也很方便,她正在抄寫她們讀到的消息——實際上是速寫。據說在難民營的上流社會,人們已經開始使用電子手帳記事,政府對他們開放了某些持有電子運算裝置的權限,甚至「合法上網」。不過要如何得到那個資格,似乎要經過許多官僚程序、實力和意志的較量。有些人得到上網專利之後會用各種方式分銷出去。
有些人得到足夠數據可以下載一本書而痛哭流涕。與大戰前不一樣,這是一個欠缺數據的時代。
Alice 沒有收她們錢,因為她們有莫名其妙的友誼,這都是因為在小學六年班的時候,她們曾經一起在河邊的路上發現一具腐爛中的屍體。雖然這並不是甚麼開心的回憶。
那實際上是一大批浮屍的其中一具,具體的歷史已經不再流傳了,被刪除了,只知道這些都是鄰國戰場飄來的。你只會知道有東西被刪除了,但不會知道是甚麼被刪除了。
她們開始吃飯,芝芝和冬菇頭邊看邊吃,Keiko 問:「妳爸爸是可以的吧?」
Alice 說:「沒問題,我早已跟他說過,你們在樓下沒見到他?」
Keiko 說:「有呀,他在跟一個男人聊天,好像很忙的,所以我才問一下。」
是怎樣的人?
「像妳爸爸那個年紀,但老一點點。」
只有 Steven 會經常拜訪爸爸,Steven 是一個有著老鷹眼神的英國人,他們之間似乎是以鄉誼結緣。從小他就會來拜訪,特別是聖誕節,十幾歲的時候她特別期待 Steven 來,因為他會帶一些貴重的禮物來,有一次是一隻戰前的 casio 手錶。據說是因為爸爸和 Steven 有一些生意合作。她沒有問,正如她主動要交近幾年的房租,爸爸也沒有問。
後來她才知道 Steven 實際也做過警察,但實際年期她也不懂,who cares?她其實從沒有跟他認真聊過天,這一切只是來自童年一些模糊不清又不重要的印象。
晚餐吃完,她們繼續忙碌,Alice 下樓扔垃圾,經過客廳時他們還在。Steven 穿著休閒的 polo shirt和西褲笑著看了看她,說了一些客套的話,她就繼續出門。父親的聲音從她身後傳來,似乎正繼續之前的談話:「Steve,我上一次去鹿鳴堂喝咖啡已經像上個世紀了……」
她去了扔垃圾,又回去房間。芝芝說到正在幫 David 建立一個後授會,而她會是團長。
Alice 一邊喝著酒,打開了陽台的窗,讓微熱的海風吹進來。她不懂他,她看過照片,是一個好看的男人,27 歲左右的歐亞混血兒,175公分,瘦得出奇,反而是芝芝的自信比較令人好奇。因為她早已見過 David 代言的化妝品、洗頭水、衛生棉和人造肉的廣告。
Alice 問:「沒有其他粉絲也想組織團體嗎?」
芝芝像一個只有自己知道被包養了的情婦,嘴角含春,是的,芝芝身上有這股微妙的自信已經一陣了。她回道:「這個……我有秘密渠道,要是真的做起來,其他人比不下我。」
可以告訴我嗎?
「當然可以啦……我認識他的經理人,厲不厲害?」
Alice 點點頭,原來芝芝正在談一個特許權回來,怪不得這件事比起上學還要緊。據說,芝芝也賣其他音樂人的錄音帶,但 David 出貨量非常大。當然,Alice 也是一個慣犯,情況不妙到退休的父親不時會問:妳真的不用上學嗎?妳沒有退學吧?之類。
晚上她們在地上鋪床就睡了。Alice 平時總是待到很夜,幾乎聽到雀鳥開始啼叫才睡覺,但這一晚她也躺著閉上眼。翌日她送走她們,泡了一杯進口咖啡,開始研究昨晚的瀏覽紀錄。
.2 男人們
據說,在戰後的流行樂壇,51 歲無性別歌手 Justin Morgan 稱霸了一個世代,已經進入半退休狀態,近年開設了公司方式提拔其他音樂人。有樂評家認為 Morgan 「以非二元的獨特唱腔和『世界系』音樂,表達了戰後一代人類無以名狀的悲喜交雜」,但 Morgan 近年遇到強勁的對手,來自偶像團體單飛發展的 David Song 經過轉投另一廠牌之後,成功轉型為音樂界最受熱捧的戰後一代音樂人。
另一位評論人這樣形容 Song 的音樂:
「你有時已經難以界定 Song 的音樂還算不算流行曲,當他越來越掌控自己的音樂,特別是他開始寫歌詞之後,音樂編排以至歌詞內容開始變得大膽,但也開始陰暗,你會聽到 Song 在復古搖滾的《Mother》描述了一個控制狂母親和兒子的故事,這是不是在評論他的前經理人?以電子環境音樂主導的《石碑》則談到了一塊突然降落地球的神秘石碑,有一隻猩猩接觸了石碑之後突然進化出語言能力,而該猩猩在得到智慧之後轉為奴役其他同類,並藏起了石碑不讓其他猩猩接觸。Song 甚至執導了這首單曲的 MV,在一個草原場景,他動用了兩百隻機械猩猩參演,他在一個訪問中談到:『(用機械猩猩) 是為了不想危害這個極度頻危物種,在不動用那種技術的情況下,又要表達一種超現實的情況,用擬真的東西是最好選擇。』這首歌的 MV 也獲得了北大西洋國最佳 MV 獎……」
之後的檔案有 95% 是關於 Song 的個人資料以及 (未被證實及已證實的) 感情歷史。包括他曾幾次被指控「教唆粉絲自殺」,其中一個事件中有一名 17 歲少女自殺,警方調查後定調事件:該少女因為家庭因素自殺。也有粉絲認為這是敵對勢力抹黑偶像。
這都不是 Alice 有興趣的事情。作為外快工作,網絡上會有人出錢請她工作,工作內容包括但不限於盜取企業和個人資料。最近她正觀察一個工作機會,似乎有人想組織一些「網絡維護員」,他們的任務是「維護」 Justin Morgan 的所有數據歷史,除了是刪除不利消息,最好還能夠製造半真半假、有一定根據的假資訊式宣傳。這是幾個知名業界人物之間首先吹起的風。
父親進了房。他五十出頭,穿著 T-Shirt,架著一副戰前的他珍而重之的眼鏡。「外面有個男孩。」她打開了「貪食蛇」,回答他:「外面又有一個男孩。」
父親說:「還是那個。」
對於拒絕人,其實她不真正懂得,還是使喚了父親去送人。她想像那個男孩的背影,他一定在經歷很多東西,但是她不會是能夠回應他的人。她怎麼會是?但她又放棄不了面子,不想像八婆一樣說難聽的話。
這個疑似工作崗位,表面上似乎是 Justin Morgan 粉絲面對 David Song 強勢挑戰而發起的「護主行動」。但重點提到 Morgan 就很奇怪,看到這種訊息的人就會想,原來 Morgan 已經衰落到需要用上一些手段?
在那個夏天之前的某日,她在本地網絡沖浪時發現,幾個隱約暗示過這「工作機會」的網絡足印,都來自 C 區。這好像不奇怪,C 區很多人可以上網……其實不多。想著想著覺得不太妥。C 區,上網基本上屬於游走法律灰色地帶的行為,而 C 區人千辛萬苦上網然後去尋找一個跟特定外國藝人有關的 digital artifact modifier/creator 的工作機會?十分詭異。如果要唱好 Justin Morgan ,為甚麼要在難民營找?難民營人口中的某人為甚麼會關心一個幾乎沒有進口的歌手的福祉?
當然,這完全不合理,但上網多了,對於奇怪的事情也就容易接受,很多事情你聽完之後聳聳背就過了。
這不是一個容易跟人分享的心境,這台機械帶來的資訊,好像也開始令人無法割捨。有些東西她知道了,但開始不敢跟人提及,這可能帶來危險。如果這是犯罪的工具,跟兇器待在一起久了,自己也養成了罪犯的心態。
「是知識把人類推向自我毀滅的吧,所以政府封鎖了過多的知識。擁有過多知識的人,就等於是網絡或者心靈的海盜……」那個有條件把機器交給她的男人,並不知覺自己發言詩意背後的偽善,那個男人是一個資深黑客,她知道的一切都是來自他,技術上和其他方面,都沒有跟對方平起平座過。Mr Maekawa,她一直這樣叫他。他頭髮的那種黑,像 Keiko 那種,一模一樣。跟她們相處的時候,她有時會偷偷觀看 Keiko 。
「所以這一切要解讀為,他們在找人搜集 Morgan 的敵人的黑材料。」他這樣的邏輯,她完全無法理解。也許他老了吧,她也不是小孩子了。
為此,她就去打聽 Morgan 最大的敵人即 David Song 的資料。在這個可能的反串組合之中,Song 那一方也十分有嫌疑。通過朋友們留下的資料,她也似乎就好像多認識了一個人。
.3 曲行的蛇
人口普查的季節沉默來臨,看到街上那些穿全白生化制服的普查員,她才想起人口普查。普查員來了家中,但只跟父親談話和做電子登記,乾淨俐落就離開。父親不敢多問,跟她談到這事時,便說道:「可能政府政策改了,逐個完成,是吧?」
後來她對父親說,自己已經在學校完成了人口普查,父親聽完之後也沒問甚麼。忙碌的上網和網下生活就這樣繼續著,幾乎已經忘了有這件事。
在那一季度的年末考試之後,有一個中年人在出口等她,他說自己是校長,要跟她聊一些事情,她一時有點恍神,就被帶到了另一間大房。Alice 聲稱沒有作弊,中年人揮著手笑說:
「妳是 Alice Hall,確認了。回到妳的問題,不是,妳沒有考試作弊。很多同學都做了人口普查了是嗎?」
她盡放鬆面部肌肉,回道:「是,我有留意到現在是人口普查的季節。」
她現在才看清這個中年人的細節,他是一個很乾淨的中年白人,但不知為何卻看不出一點細節,她確認自己看著他,而這個人卻似乎一點特徵都沒有。他就只是……權力的樣子。
校長說:
「那麼普查員到妳家中了嗎?」
有一刻,Alice 有大禍臨頭的感覺,有一瞬間。不過最後她還是比較淡定:「沒有……怎麼說好?他們確實來了,但只登記了我爸的電子手帶,對我基本上是置若罔聞,我們以為他們會分開來找我,但到現在都沒有,會是忘記了我嗎?」
校長聽完之後,點點頭:「原來是這樣,好的,沒事了,假期愉快。」他笑了,像一團模糊的幻覺陰影在微笑。校長走了不久,芝芝、Keiko、冬菇頭也出來,她們正討論要為 David 後援會設立一個信托基金,問她意見,她那一刻有點懊惱,只好答:
「在難民營也要搞信托嗎?」
轉念又覺得自己說了壞話,在難民營之中比較忌諱「難民營」這種字眼。人們不禁在兩種狀態中流轉,是承認這裡的暫時性,還是尋求終止它?但她們似乎沒有在意,一番迎送之後,她打起難民的精神獨自走回家。
她喜歡走路,在走路時似乎會想到很多事情,好像是自由的感覺。當然由大學走回家的路,已經走過很多次,沒有驚喜,但那天卻是陰雲密佈。她還是回家,因為那確實是她的家,還是她在做黑客賺的錢付擔的,但父親也在那裡。
突然被校長約談的經歷不尋常,Alice 開始想像父親那一方,如果有需要,他的供詞會對上嗎?他怎知道「應該」如何回應?應該跟他談這件事嗎?回家後,她最後沒有膽量提起,但父親先提起:「從以前走到現在,大家的日子都很難過。」
以前他會跟她談這些睡前故事,他們很多人都是逃避一場災難,飄洋過海來到這裡。但不是那個老版本:「大家都在逃避大戰的陰影,大家都在逃避一些事情。」
她回應:「逃來 C 區,因為有一個女兒,成為一個單親父親,獲得難民資格,是為了甚麼?」
事後回想,這句話,任何一個父親聽到都應該拍案而起或深感懊惱,但父親沒有,父親是平靜的,只是看到思緒的皺紋。他就像準備了這個演說很久,他退休前明明是一個能言善辯的記者,她有時不知道人們變老的時候是否都會變得沉默。
父親說:「我們都曾像你們一樣有好奇心……反正現在的東西,我已不知道了,其實根本沒有鹿鳴堂這間咖啡廳。」
她看看他,他又繼續說:「鹿鳴堂是我們那個年代的學運組織,我們都想往外跑,在網絡下載外面的東西……」她問:「然後…?」
他把身體往後靠攏,接著說:
「後來發生了很可怕的事,很多觸犯禁忌的同志都犧牲了,就這樣。妳想像不到,妳從那台機器知道很多吧?但很多資料都是破碎的,假造的,拜託,但妳只有 22 歲。真正發生過的東西只在我們的腦海之中。我是其中一些倖存的人。很多事情都發生在 C 區。」
這個故事,父親的確跟她聊過不只一次,不過年幼的時候,她理解為「爸爸在上一次大戰中倖存」。
「抱歉,我不能再說太多,人生嘛,一切都要妳自己領會。」他最後說。他的臉容平靜,富有人性,沒有絲毫的恐怖,也沒有拆穿女兒的一時之快。
Alice 朝他抬了抬眉,示意「知道了」,之後她謊稱去女朋友家過夜,就去了那個男孩的家。
當男人喜歡你的時候,你不需要逗留的藉口。雖然 Alice 有些懊惱,她努力尋找這個男同學的記憶碎片,她記得他多一點,他們才能談話,她才能獲得回應。有些時候你要承認,自己害怕寂寞。
最後只談到「我爸爸說了一些亂七八糟的話」,她就坐下來,喝著他提供的酒。難民營的人生活確實越來越好,連酒都很容易找到。雖然使用高速運算裝置的她如果有這種感想,亦是十分矛盾。
不記得名字的男孩也許以為她在煩惱家庭關係,但事情實在太複雜,她也願意他用一個簡化的版本來靠近自己。誰和誰不是這樣交往的?然後他們睡了一覺,他很有反應,但沒有做甚麼,Alice 覺得人和人能這樣交往,十分神奇。世界上有各種各樣的男人。但是躺得再近,她還是不敢坦露恐懼。如果在這種情況下懷疑自己的爸爸,她在地球上唯一的親人,聽起來十分可恥,然而她不敢回家,這是不是她恐懼和可恥的證據?
「謝謝你。」好像把不敢說的話這樣說了,才能心安。同床共枕的可恥,比不上動用自己的脆弱。人脆弱的時候,連冰山的雪花都是淫蕩的。
.4「因為你與我同在」
Alice 最後當然有回家,那確實是她的家。那個還未記得名字的男孩,Alice 本來沒有放在心上,但她之後將男孩放在心裡。
怎樣也好,他當日很保守的舉動,讓 Alice 感到他沒有自以為是踩入她的領域,這人值得記下。
她回去之後,也沒再跟父親再談當天的話題,他們又恢復日常的必要家居互動,自從那天她就沒有再進入難民營政府的系統,她只是個半桶水,反跟蹤程序根本可能無效,或者對方輕而易舉就破解了。總之,那些日子她的神經開始草木皆兵。
在學校,在同學朋友之前,她不會表露出內心的緊張。去到最後,她已經學會與這種內心永恆的緊張貼著臉相處,她察覺一切事物。如果這裡有人是告密者,是誰?芝芝、Keiko、冬菇頭,誰會出賣她?
有一天黃昏,在回家的必經之路,沿岸的一切都沐浴於血紅色的太陽之下,那裡有一個穿白裙的女孩,是 Keiko,她看到真實的 Keiko 的表情,那不是平日她示人的樣子。
Keiko 應該已經知道一切。她有一刻發現了這個眼前的事實。
最近的霉運總是將她殺得措手不及,但這一幕,Alice 在內心排演過很多次,是的,Keiko 總有一天會知道,原因根本不重要。是他告訴女兒,還是女兒發現的,都是折穿了她。
如同想像中的 Keiko,Keiko 快速走近,一巴掌打在她的臉,火辣辣的,混亂中 Alice 倒地,Keiko 壓過去讓她不能動彈,她可能吃過某些黑市流通的身體強壯藥,導致嬌小的 Keiko 這一刻力大無窮。在搏鬥中 Keiko 哭著大叫:「妳跟爸爸的事情是否真的?」
Keiko 沒有真的打她,而是倒在一旁。Keiko 的白裙此刻沾滿泥濘,泥土的味道十分特殊,Alice 就這樣躺著,看著沒有星光的星空。
夜幕裡沒有星的原因,是另一個區的照明系統影響這裡,相對的,我們也為其他區無法享受星空,作了應作的孽。
Keiko 哭著問她:「為甚麼是他?」
Alice 答:「這答案可能聽起來無情,但真的與 Keiko 妳沒有關係,純粹是 Mr Maekawa 和我自小就有很多交集,我從他那裡拿走了一台機器,在這段關係期間,我又學到了一些科技知識。這持續了可能六七年吧。」然後 Alice 開始朝她大喊:是的,他無疑是一頭禽獸,但如果沒有我的犧牲,妳是否也十分危險?說來……是否應該由我把妳撲倒?
她一邊說著,一邊爬起來,靠在路旁坐下。
Keiko 的聲音從後方傳來:「這是不是罪案?雖然那是我的爸爸,但那時他絕對在犯罪。」
Alice 回應:「如果我當時報警,你就會成為孤兒。在巨型難民營生活已經好痛苦了,在難民營裡面做孤兒只會更加痛苦。所以,我跟他的事以這種方式淡出,妳才不用做孤兒,妳成長階段一直都有這個爸爸,是我在背負你爸爸可怕的那一面,所以我總是羨慕你,我總是想做你的朋友,因為你擁有他好的那一面,爸爸的那一面,但我擁有的是他另一面。」
Keiko 喘氣的聲音在後面傳來。
Alice 也在鬧脾氣,從來沒人這樣打過她,所以她要恩將仇報。也許她可以選擇比較容易的路,選擇當一個受害者,是 Keiko 的惡魔電腦學家爸爸的受害者,然後受害者和兇手的女兒同樣可以做好朋友。
但 Alice 不願意視自己為受害者,她清楚知道記得自己當初發現 Mr Maekawa 這個不尋常的人,與他達成了協議,為了得到那台整個 C 區僅有一台的 Panasonic CF90 ,她知道自己選擇了不尋常的路徑。真可恥。對別人可以這樣說,讓他們用一個較能接受的版本跟她交往,但內心她知道自己沒那麼無辜。
既然不是無辜的,那就不用對自己好了,久而久之也忘記了對自己好是甚麼一回事。
機器現在屬於 Alice ,它的上一手主人是 Mr Maekawa,Mr Maekawa 從一位智能機械幕僚「阿福」手中買到,那是阿福不要的昂貴玩具之一。
阿福是「白皇帝」第六幕僚團成員,主要功能是增加 Fauci 總督的電子腦與雲端運算的聯絡速度,明乎其實是他的大腦 (之一)。由於總督的官邸是模仿美國內戰前的第一代白宮,而他又掌權了極長時間,富有詩情的人們開始用 Constantius the Pale 形容他。這位各國機構委任的難民營長,幾乎獲得一切緊急權力,他本人也是一台行走的決策運算機。
關於他身上的數據魔法,只有極少數人知道,而大部份都是吹牛,再加上宣傳部門故意放出的惡搞版本。只知道有人認為白福奇將自己的腦袋換成了電子腦,而不是電子加強,方便隨時無間斷讀取資訊和決策推介,因此他也在無時無刻讀取民意。
由於難民區甚至這個國家對電子運算的強烈壓抑,每個人的運算力都很有限,除非用其他手段獲得。「白皇帝」卻被譽為擁有情報預知力的人型機算機,他逃過了幾十宗暗殺,並且歷史一直以勝利的甘露膏抹他。
他快速解決了上一次大戰之後的某一餘波而製造的幾百萬難民,將這裡發展成可以宜居、有經濟產出的地方。所以國際聯盟暫時仍然支持總督「暫時管理」這個難民帝國。
總督已經不只是一個人,而是一個機構,他身上的寬頻多到可以分出來管理區內交通燈、警署報案系統、某一次警隊攻陷行動的前期及中期部署,全部都可以透過他的意志來操作,而結果又總是顯示:聽從「皇帝」指示總是如有神助。
他簡直是先知。
而眼前這台計算機,應該算是那一班人一時心血來潮玩過的潮物,而今天讓她撿了二手。雖然二手,但她付出了無法正常戀愛的代價。因為 Mr Maekawa 是一個天才,也是一個禽獸。這是一個分化的社會,但當你未見過另一座山,你不會知道自己有多小。
神話故事中掉入凡間的神劍魔斧,就是仙人的模型玩具。是的,她從歷史課有聽過,在大戰期間,有些地方連出賣肉體已經沒法令人基本吃飽,人們基本上都在吃人肉。當她想到這些,就會覺得自己不算宇宙中最慘的人,這想法聊勝於無,是不?
「Alice ,原來妳是那麼嘔心的人。」Keiko 最後像總結一樣說。
「妳也很嘔心,妳令我想起他。」Alice 回應。
.4 「使世界如同荒野,是這個人嗎?」
芝芝和冬菇頭的準備工作密鑼緊鼓,在 Alice 不為意的時候,她們已經召集了二百個義工會員,還有會員 T-Shirt 和整套制服。據芝芝在聚會時透露,David 來到最近 C 區那一站,就開始起動,開始招收會員。芝芝說到這些的時候兩眼放光。
Alice 看到她們,內心不禁有點悵悵,她不想成為別人的焦點,生怕被人注意到,但她們倒是不怕的,很羨慕。
冬菇頭是真心熱愛 David 的,但由於 David 並不是極少數被認可能夠輸入到難民區的藝人,冬菇頭從小把自己養成了走私行業的專家,通過她家人的關係,可以偷運各種違禁品,包括偶像的商品。
一個冬天的演員會,在盛夏開始籌備。最後她們真的成立了公司,並且獲得 David 在網上認證,等於把這一區難民歌迷的事務交給她們了。一時間,芝芝和冬菇頭變得位高權重,走路有風。有一日芝芝問:
「Alice 妳畢業之後有甚麼打算嗎?過來我們公司幫手吧,我們很需要人手呢﹗」
Alice 微笑著回應她:「好吧,但給我考慮一下,技術上我們還未行禮,還可以優哉遊哉。」
事實上,大學畢業,還是難民,不容易找到好工作。對於 Alice 來說,自己在海外的幾十個戶口已經堆滿錢。父親有時問為甚麼從未見她上學,她會隨口答:me 已經退休了,父親以為她在胡言亂語。但她實際上確實不打算去當個荷官,雖然她數學相當好,但問題純粹是,為甚麼?
她除了偶爾去上課之外,大部份精力都用在管理自己的海外資產,雖然實際上總資產不多,但都是各種加密貨幣,相對安全。
David 在「新住民區」(一個較文雅的講法) 第一場巡迴演員會就在 12 月 24 日晚上,第一場是 C 區。
新中央日報一條新聞廣播:
「國外藝人 David Song 破天荒獲准在 13 區表演,是不是北大西洋國向我國釋出善意獲得積極回應?這會是東盟與北大西洋國長期停火後的交往預熱嗎?」
入秋之後,C 區也湧入越來越多外面人,他們也想來看演唱會,難民觀眾和其他觀眾因為買票的問題而引發街頭鬥毆,有一晚搞到全城宵禁,網絡受到大重置,害她又花了很多時間重新做上網設定。
經過那次跟 Keiko 衝突之後,Alice 對維繫那段關係沒有甚麼想法,它最後好也罷,不好也罷,如果人們在自己人生的低潮,漸漸就不會計較太多事情。
不知為何那天的事似乎連芝芝都知道了,怎麼都好,她不想理會,沒法隨意上網帶來的壓力,令她不太能集中。
芝芝約 Alice 在 12 月 24 日下午「出來玩」,芝芝說話時很神秘,「是開騷前的 party ,可以見到 David 本人。」
Alice 卻不想見那個人,她只好問:「為甚麼我也有份?」
芝芝回道:「因為然是我們後援會的技術總監,所以妳也一起來吧,他真人很不可思議的。妳不想認識他嗎?」
Alice 問芝芝:「這不是甚麼選妃的環節吧?」
芝芝連忙否認:「不是這種啦,是說請妳作為 VIP 去,跟另外那種不同。」
她問:「所以妳真是已經開始幹這個生意了?」
芝芝聳了聳背,她說:「女孩都要吃飯的嘛」。
Alice 回應:「好吧,只要我在的那個場合不是在搞選妃就好。」
她們說 Keiko 也會來,但她會在午夜的那一場慶功裡出現,就是不想見到 Alice 嗎?嗯,那次說的話確實很過份。她想。
「這確實只是普通飲料、普通閒聊的派對?」
芝芝再三強調:「是的,只有普通飲料和普通閒聊,耶穌,妳骨子裡其實也很煩呢。」
David 的音樂會在 3 區中央公園舉行,中央公園被一群模仿熱帶樹林的人造樹林包圍,經過樹林會進入一個人造沙灘,這裡卻沒有海。舞台就在最中心位置,在後台有一條延長出去的草地,回到樹林,再回到外面的世界。他們在後台的後方幾十萬處搭了一個男人身高的帳篷,他們就好像傳說故事中的蒙古包。
那次見面究竟是怎樣的,相較之後的事情實在過於平淡,事後反而很難想得起。或者她懷疑是某種精神控制技術,強行蒙蔽了某些記億。
David 來了,他是一個高瘦的男人,穿著休憩的黑色睡衣,但看來是另一個世界的產物,充滿光澤,跟難民區可以買到的高級服飾,完全像是兩種事物。但他一把油頭、滿臉鬍渣,「他們還未開始準備。」她想。
芝芝和冬菇頭在跟這個親切的男人聊了一陣,然後她們向她介紹 Alice,對方望望她,走過來跟她握手,彷彿她真的是他這個粉絲後援會的技術總監。當時一開始談了甚麼,也不記得。後來大家互相傳著酒杯,分享起酒精來。後來芝芝和冬菇頭勁頭過了之後,去了處理一些「會務」,David 和 Alice 並肩站在夕陽之中,朝著他即將要開騷的那個會場,他雖然待在陰影中,但又好像晨光的寵兒。夕陽和清晨明明是兩種相對的事物,卻又是相像的現象。她是屬於晚上的,而他在鏡頭前總是出現在白天。
他們明明互不認識。她暗中調查過他,但這自然不是算是認識。
Alice 說:「我知道這個機會很難得,所以我可以問一個問題嗎?」
「請。」
「有人批評你的音樂吧?」
對方認真地想了一陣:「我覺得這是大家對成功有不同定義……有時作為一個創作者,用一般的方法獲得的成功也是成功,但在裡面我是不自由的,我總是知覺到自己需要做好某些本份,所以我有時會想在裡面鑽一些洞……當然我還在努力,這些實驗雖然很多我都認為成功了,但無疑也是有失敗的。希望之後能做出讓妳喜歡的音樂。」
Alice 轉個頭望了望他。「好,你做出了,到時我來聽。」
「妳在萬聖節時會扮女巫嗎?」
她搖頭。舞台那邊還發放煙花,觀眾似乎正在入場。
「上網的人某程度上也像女巫吧?」他又繼續逗她說話。
「放煙花了。」她說:「但我的朋友還沒回來。」
「她們回不來了。」David 望著遙遠的彩色耀光,如此說。
「為甚麼?」
「妳可以看到的人口普查,但也有一個異常的人口普查。這裡很多人口當初植入的行為控制晶片,是一批次貨。這涉及一些很複雜的數學問題。總之,接種了次貨晶片的人,慢慢就會出現精神疾病。兩個人口普查都是為了維修那一顆晶片,或者說更新它的韌體。如果不更新韌體,會影響最終的統計數據。科技會產生各種錯誤訊號,我的職責是負責偵測特定種類的錯誤晶片訊號。」
彷彿有一道可怕的閃光照顧她。
David 繼續說:「所以有人將我吸引到的粉絲,都錄制了名單,方便之後慢慢更新。」
「她們會面對甚麼?」如果不是好奇,不應繼續搭話。
「沒有甚麼,他們很人道的,只是更新一下那塊晶片,但那一刻我的粉絲就不會再愛我。他們會離開這個圈,妳的朋友也已經在登記中,但我打算放妳離開,讓妳記得這一切。」
……
「你是政府的人嗎?」
「他們造出來的生化人。我的臉孔可以隨意改變,我的人格則來自幾百萬個模擬程式互相混合的結果,其他的『我』性格完全不一樣。即使我在這裡突然被槍殺,新聞不會傳出去,這個事業也不會停,會有人代表我演出 David 這個角色。所有放出去的魚鉤都是這樣。」
……
「為甚麼跟我說這些莫名其妙的話?」她望著他,這人正在一口一口的喝酒,可以理解為超級巨星也會發酒瘋吧?
「因為接下來我只有一些時間交代妳有多重要這個問題。」
「請說。」
「如我所說,這些組織起來的人口,都會登續登記新設定檔,妳沒有登記,這才令我我注意到,應該交給上級機關。不過我沒有,想起來,我違反了守則。」
不知道是否酒醉,David 背後那個蒙古包正在飄浮,閃著妖異的光暈。她想離開,但是腳不聽使喚,她只好在醉感中聽他把話說完。
他的話音繼續傳來:「這是現實,我也說了,我是設計來吸引某種帶著缺憾的人,妳可以理解為一個精神控制的光環,妳的朋友也是我使喚走的,雖然妳不會知道傳遞方式。妳其中一個朋友以 Morgan 的名義招集打手,在我這條生產線上的下游員工,就會以此挑起爭論。她本來以為完成這件事,就可以成為 C 區的後援會首領,從她那裡,我也知道了關於妳的所有事。但這件事在今晚之後就會終結。」
「回到我們的話題,關於納米晶片(行為治療)二型的事情,妳查了很多,但都是不正確資料,我透露的比較完整。」
「一直是你負責監控我?為甚麼說了那麼多奇怪的話?你還好嗎?」她覺得很累,便躺坐下來。這很像一個暖水般的夢。
「我的時間緊迫,我要在我忘記這些事之前,讓妳記住。」他的視線投向沒有星星的夜空:「他們發現這個紀錄,我就會被回收,我的記憶會被清洗,這可以換取妳不被暴露。」
「你想要甚麼?」不知為何,她流出淚來,但她並不傷心,湧出的淚水更像是生物肉體受到某種輻射而產生的變異。
「被記住,就像明星一樣。」他微笑:「跟所有人一樣。你們像我們一樣被設定了軌道,無論多慢也好,總有人會走出另一條路。處於我們那個維度的物種,也會偶爾反抗。人們總是回到一樣的道路,但要有希望,而我擁有億萬個組合撞出來的這一個人格,這一個人格的任務成功率只有 99.9%,絕大部份時間我都服從我的本體,但有很微小的機會還是會出現 malfunction。」
她睡著了,或者是說失去知覺,在模糊中她感受到蒙古包外面捲起一股強風,是一架直昇機,上面下來了幾個男人,那個人自願跟著他們上機——下一個畫面是在醫院。
據說中央公園發生了氣體泄漏,所有觀眾疏散,音樂會無限期停止。後來 David 繼續前往其他國家演唱,但很奇怪的是,似乎由 C 區開始,Daivd 的人氣就馬上急降,他的商品、代言產品都成為蟹貨。他像旋風一樣,但在正式登陸之前離奇折翼。整個 C 區彷彿沒有發生過任何特別事情。畢竟疑似恐襲、藝人因為某些原因而無法演唱,對一般人來說司空見慣。
芝芝、Keiko、冬菇頭和 Alice 一樣,都在中區醫院醒來。據說大家都吸入了不明氣體,但都沒有永久傷害。Alice 想起,這就像上一次她們遇到那條浮屍,她們目擊了甚麼,好像記得了甚麼,但之後一切都會恢復正常。
.5 MALFUNCTION
政府化武部隊徹底清洗了中央公園。
對於 David 為何突然辭演退票,甚至出現很多種不同解釋,包括有人認為當晚有 UFO 擄人和襲擊、地底怪物出現、大戰正以隱秘方式重新爆發、觀眾集體出現多重記憶等等,有很多神秘兮兮的傳說。但她不認為如果告訴 C 區人民他們是一個大型行為—精神實驗的白老鼠同伴,這就好嗎?不會好。
整個難民城市計劃,在人口數十萬數十萬滅絕的大環境下,任何混合著科學實驗、慈善、經濟復興資源競爭的大型人口實驗,都比起大戰爆發前更容易建立。這裡也是填海出來的,人可以改造自然,憑甚麼又不能改造人類?難民營有多少人被改造了?有人的能力被加強了?有人的能力被削弱了?不敢想像下去。
夜深人靜的時候, Alice 會回憶那個夢一般的談話,記憶好像碎片,不斷拾起碎片,碎片好像變得越來越多,分不清哪些是先,哪些是後。但在不斷回憶中,她好像慢慢了解皮膚下的那個 David 交托了甚麼給她,似乎是很有重量的東西。
有很多夢都是在醒來之後逐漸記起來,原來昨晚造了一個夢。關於那個明星的事也是這樣。
「為甚麼白白放過我?」因為我不是無辜的,我已經被沾污了。
David 皮膚下的那個人向她揮手,像明星向粉絲揮手:「這是白白給妳的赦免,我賭上自己的權限清洗妳的改動記錄,因為希望是從虛無裡面來的,我是從數據污垢裡面走出來的,這是我第一次反抗,也是我第一次赦免人。」
在很多海盜網民的私下討論中,「白皇帝」也指涉整個城市的人工智能維生體系,這是所有情報的主要海洋,他們開始認為,總督已經跟生化機器融為一體,已經無法以人類的標準去看,簡直是活著的神。他知道世上所有事情,所以他是否知道他旗下的某一個 David 選擇違反本能、靜悄悄地自我毀滅,本來完美的數學算式出現了意料之外的答案?
有一晚她睡不著,到客廳去坐著,父親也在那裡,她坐下,這次她主動開口:「可以問一個問題嗎?」
他說:「sure。」
她說:「現在我有點明白你說的,你是倖存者的意思。」他喝茶,暫未回答。
「我發現一個人,他似乎無條件愛我,那種愛是令人恐懼的、陌生的,而現在這段關係已經死了,而我卻似乎生存了下來。」
父親說:「妳想跟他復合嗎?」Alice 願意父親了解自己比較顯淺的那個版本。
「但這不可能,那不是男人和女人之間的事,我不知如何解釋。」
父親問:「那妳還愛他嗎?」
現在已經完全感受不到,因為她的晶片已經暗中被更新過吧?現在 David 是一個令她情緒上討厭的存在,但她記得另一個 David,那個由人類創造的物種,竟然把希望寄托在人類身上。
她不置可否:「我收到他的心意,應該這樣說吧?」
她不打算說對方「自殺」了。
黑夜還很漫長,還有很久才會破曉。父親點頭:「是個怎樣的人?」她想了一下,結論道:「他是個會自己拿主意的人。比我見過的任何人都有主見。」那這個人很好啊,父親說。
完
17.9.2021 盧斯達
訂閱 patreon https://www.patreon.com/lewisdada
盧斯達新書 《如水赴壑—香港歷史與意識之流》:https://tinyurl.com/eyd9258v
完全二元樹 在 Facebook 的最佳解答
【明星與女巫 | 盧斯達 on Patreon】
.1 女孩們
這個城市庇護難民。入夜之後由於人工照射過於光猛,連星星都看不見,城市反而成為星星的海洋。在外人眼中,這裡豪華得不像難民營。
這些都是倒影在玻璃屏的倒影,1 分鐘之前,Alice 不小心通過一台 Panasonic CF90 登入了政府網絡,並不小心修改了人口普查紀錄,將自己從「未普查」修改為「已普查」。她是一個業餘上網者,也不是想偷竊政府的甚麼資料,只是想測試一下能否做到。然後她發現並沒想像中的困難,於是找了一個無關痛癢的地方作了修改,就當是一句不顯眼的「到此一遊」。
她懷疑在 C 區像她這樣的人有多少,也許沒有。她比較願意相信自己是特別的,這令她沒有那麼不自在。她瞄瞄電腦中的時間,三個八婆應該差不多已來到。芝芝、Keiko、冬菇頭,這是她同系的同學和朋友。這三個人看中 Alice 的電腦,在 C 區,速度夠快的電腦並不常見。而她們最近迷一個外面的男明星,叫 David,就這樣,所以她們需要夠快的網絡和電腦連接外面的網絡。Alice 千叮萬囑她們不能向其他人透露關於上網的事。
據說是在上世紀的一場大戰,具有VR 彩現能力和短期洗腦能力的高速電腦結構被定義為戰略物資,在戰後的難民營,管有高速運算機亦需要持牌。Alice 一開始認知到犯法,但上網可以看到的東西實在太多,後來她開始認為自己合法擁有它,只不過沒有文書——她對自己這樣辯解。
但具體上,她可以被控無牌管有高速運算機。
一般人根本不知道這種機器屬於戰略物資,C 區大部份人口都是科技文盲,會以為它是其他大戰前的科技產物。她向父親這樣解釋這台機器:這是一台科技文物,它主要的功能是進行類似「貪食蛇」或是「接龍」的小遊戲程式,父親顯然不懂,所以就接受了它搬入房中。她也為這台機器寫了一個反跟蹤程式,她不想別人知道她在上網。
透過仍在地球軌道運行的殘存衛星,這台運算器可以透過一種在 21 世紀初開始流行的技術——全球 Wifi——接收到訊號。
相反,C 區下達消息以實體報刊為主,近年政府也實際出資建立了電視、電台,但那不是她在網絡存庫看到的世界。這個地方誕生,就因為那場因為互聯網而爆發的毀滅性戰爭,所以大家都被灌輸了「上網行為必須嚴格管制」的文化,還有相關的一大堆一般人進入不了的防火牆。
透過斷斷續續的收發,可以讀到不少殘存的網絡檔案庫。聽說大戰後的人開始重建各地網絡,修復以前的資料。關於之前的一切像朦朧的月亮,始終是模糊不清。國際聯盟認為,對 A 區至其餘各區的長期難民人口來說,全面享受互聯網人權的人口少於 5%。這當然是一個約數,很多人也可以用互聯網,這主要是擁有權力的人、金融政府機關、有錢的難民,或者像 Alice 一樣不正當得到工具的。這個消息,並沒有在 C 區報道或廣播過。
芝芝、Keiko、冬菇頭是能夠守秘密的人嗎?她會這樣想。
她們帶著一些外賣和——紅酒——前來,還有一個小箱放她們的睡衣。芝芝一家來到這裡以前,是一個美國人。這真是一個令人懷舊的名字。她放下之後,大動作擁抱她,說著路上許多的不便。然後她望著那台機器,「已經開動了啊?就像上次一樣,很讚。」芝芝說。她們放下行裝之後就開始上網,Alice 第二次讓芝芝操作,她已經在搜索關於 David 要破天荒走入難民營開音樂會的消息。
冬菇頭據她自己說,她一家來自亞洲某個國家,因此她被定義為亞洲人的方式也很方便,她正在抄寫她們讀到的消息——實際上是速寫。據說在難民營的上流社會,人們已經開始使用電子手帳記事,政府對他們開放了某些持有電子運算裝置的權限,甚至「合法上網」。不過要如何得到那個資格,似乎要經過許多官僚程序、實力和意志的較量。有些人得到上網專利之後會用各種方式分銷出去。
有些人得到足夠數據可以下載一本書而痛哭流涕。與大戰前不一樣,這是一個欠缺數據的時代。
Alice 沒有收她們錢,因為她們有莫名其妙的友誼,這都是因為在小學六年班的時候,她們曾經一起在河邊的路上發現一具腐爛中的屍體。雖然這並不是甚麼開心的回憶。
那實際上是一大批浮屍的其中一具,具體的歷史已經不再流傳了,被刪除了,只知道這些都是鄰國戰場飄來的。你只會知道有東西被刪除了,但不會知道是甚麼被刪除了。
她們開始吃飯,芝芝和冬菇頭邊看邊吃,Keiko 問:「妳爸爸是可以的吧?」
Alice 說:「沒問題,我早已跟他說過,你們在樓下沒見到他?」
Keiko 說:「有呀,他在跟一個男人聊天,好像很忙的,所以我才問一下。」
是怎樣的人?
「像妳爸爸那個年紀,但老一點點。」
只有 Steven 會經常拜訪爸爸,Steven 是一個有著老鷹眼神的英國人,他們之間似乎是以鄉誼結緣。從小他就會來拜訪,特別是聖誕節,十幾歲的時候她特別期待 Steven 來,因為他會帶一些貴重的禮物來,有一次是一隻戰前的 casio 手錶。據說是因為爸爸和 Steven 有一些生意合作。她沒有問,正如她主動要交近幾年的房租,爸爸也沒有問。
後來她才知道 Steven 實際也做過警察,但實際年期她也不懂,who cares?她其實從沒有跟他認真聊過天,這一切只是來自童年一些模糊不清又不重要的印象。
晚餐吃完,她們繼續忙碌,Alice 下樓扔垃圾,經過客廳時他們還在。Steven 穿著休閒的 polo shirt和西褲笑著看了看她,說了一些客套的話,她就繼續出門。父親的聲音從她身後傳來,似乎正繼續之前的談話:「Steve,我上一次去鹿鳴堂喝咖啡已經像上個世紀了……」
她去了扔垃圾,又回去房間。芝芝說到正在幫 David 建立一個後授會,而她會是團長。
Alice 一邊喝著酒,打開了陽台的窗,讓微熱的海風吹進來。她不懂他,她看過照片,是一個好看的男人,27 歲左右的歐亞混血兒,175公分,瘦得出奇,反而是芝芝的自信比較令人好奇。因為她早已見過 David 代言的化妝品、洗頭水、衛生棉和人造肉的廣告。
Alice 問:「沒有其他粉絲也想組織團體嗎?」
芝芝像一個只有自己知道被包養了的情婦,嘴角含春,是的,芝芝身上有這股微妙的自信已經一陣了。她回道:「這個……我有秘密渠道,要是真的做起來,其他人比不下我。」
可以告訴我嗎?
「當然可以啦……我認識他的經理人,厲不厲害?」
Alice 點點頭,原來芝芝正在談一個特許權回來,怪不得這件事比起上學還要緊。據說,芝芝也賣其他音樂人的錄音帶,但 David 出貨量非常大。當然,Alice 也是一個慣犯,情況不妙到退休的父親不時會問:妳真的不用上學嗎?妳沒有退學吧?之類。
晚上她們在地上鋪床就睡了。Alice 平時總是待到很夜,幾乎聽到雀鳥開始啼叫才睡覺,但這一晚她也躺著閉上眼。翌日她送走她們,泡了一杯進口咖啡,開始研究昨晚的瀏覽紀錄。
.2 男人們
據說,在戰後的流行樂壇,51 歲無性別歌手 Justin Morgan 稱霸了一個世代,已經進入半退休狀態,近年開設了公司方式提拔其他音樂人。有樂評家認為 Morgan 「以非二元的獨特唱腔和『世界系』音樂,表達了戰後一代人類無以名狀的悲喜交雜」,但 Morgan 近年遇到強勁的對手,來自偶像團體單飛發展的 David Song 經過轉投另一廠牌之後,成功轉型為音樂界最受熱捧的戰後一代音樂人。
另一位評論人這樣形容 Song 的音樂:
「你有時已經難以界定 Song 的音樂還算不算流行曲,當他越來越掌控自己的音樂,特別是他開始寫歌詞之後,音樂編排以至歌詞內容開始變得大膽,但也開始陰暗,你會聽到 Song 在復古搖滾的《Mother》描述了一個控制狂母親和兒子的故事,這是不是在評論他的前經理人?以電子環境音樂主導的《石碑》則談到了一塊突然降落地球的神秘石碑,有一隻猩猩接觸了石碑之後突然進化出語言能力,而該猩猩在得到智慧之後轉為奴役其他同類,並藏起了石碑不讓其他猩猩接觸。Song 甚至執導了這首單曲的 MV,在一個草原場景,他動用了兩百隻機械猩猩參演,他在一個訪問中談到:『(用機械猩猩) 是為了不想危害這個極度頻危物種,在不動用那種技術的情況下,又要表達一種超現實的情況,用擬真的東西是最好選擇。』這首歌的 MV 也獲得了北大西洋國最佳 MV 獎……」
之後的檔案有 95% 是關於 Song 的個人資料以及 (未被證實及已證實的) 感情歷史。包括他曾幾次被指控「教唆粉絲自殺」,其中一個事件中有一名 17 歲少女自殺,警方調查後定調事件:該少女因為家庭因素自殺。也有粉絲認為這是敵對勢力抹黑偶像。
這都不是 Alice 有興趣的事情。作為外快工作,網絡上會有人出錢請她工作,工作內容包括但不限於盜取企業和個人資料。最近她正觀察一個工作機會,似乎有人想組織一些「網絡維護員」,他們的任務是「維護」 Justin Morgan 的所有數據歷史,除了是刪除不利消息,最好還能夠製造半真半假、有一定根據的假資訊式宣傳。這是幾個知名業界人物之間首先吹起的風。
父親進了房。他五十出頭,穿著 T-Shirt,架著一副戰前的他珍而重之的眼鏡。「外面有個男孩。」她打開了「貪食蛇」,回答他:「外面又有一個男孩。」
父親說:「還是那個。」
對於拒絕人,其實她不真正懂得,還是使喚了父親去送人。她想像那個男孩的背影,他一定在經歷很多東西,但是她不會是能夠回應他的人。她怎麼會是?但她又放棄不了面子,不想像八婆一樣說難聽的話。
這個疑似工作崗位,表面上似乎是 Justin Morgan 粉絲面對 David Song 強勢挑戰而發起的「護主行動」。但重點提到 Morgan 就很奇怪,看到這種訊息的人就會想,原來 Morgan 已經衰落到需要用上一些手段?
在那個夏天之前的某日,她在本地網絡沖浪時發現,幾個隱約暗示過這「工作機會」的網絡足印,都來自 C 區。這好像不奇怪,C 區很多人可以上網……其實不多。想著想著覺得不太妥。C 區,上網基本上屬於游走法律灰色地帶的行為,而 C 區人千辛萬苦上網然後去尋找一個跟特定外國藝人有關的 digital artifact modifier/creator 的工作機會?十分詭異。如果要唱好 Justin Morgan ,為甚麼要在難民營找?難民營人口中的某人為甚麼會關心一個幾乎沒有進口的歌手的福祉?
當然,這完全不合理,但上網多了,對於奇怪的事情也就容易接受,很多事情你聽完之後聳聳背就過了。
這不是一個容易跟人分享的心境,這台機械帶來的資訊,好像也開始令人無法割捨。有些東西她知道了,但開始不敢跟人提及,這可能帶來危險。如果這是犯罪的工具,跟兇器待在一起久了,自己也養成了罪犯的心態。
「是知識把人類推向自我毀滅的吧,所以政府封鎖了過多的知識。擁有過多知識的人,就等於是網絡或者心靈的海盜……」那個有條件把機器交給她的男人,並不知覺自己發言詩意背後的偽善,那個男人是一個資深黑客,她知道的一切都是來自他,技術上和其他方面,都沒有跟對方平起平座過。Mr Maekawa,她一直這樣叫他。他頭髮的那種黑,像 Keiko 那種,一模一樣。跟她們相處的時候,她有時會偷偷觀看 Keiko 。
「所以這一切要解讀為,他們在找人搜集 Morgan 的敵人的黑材料。」他這樣的邏輯,她完全無法理解。也許他老了吧,她也不是小孩子了。
為此,她就去打聽 Morgan 最大的敵人即 David Song 的資料。在這個可能的反串組合之中,Song 那一方也十分有嫌疑。通過朋友們留下的資料,她也似乎就好像多認識了一個人。
.3 曲行的蛇
人口普查的季節沉默來臨,看到街上那些穿全白生化制服的普查員,她才想起人口普查。普查員來了家中,但只跟父親談話和做電子登記,乾淨俐落就離開。父親不敢多問,跟她談到這事時,便說道:「可能政府政策改了,逐個完成,是吧?」
後來她對父親說,自己已經在學校完成了人口普查,父親聽完之後也沒問甚麼。忙碌的上網和網下生活就這樣繼續著,幾乎已經忘了有這件事。
在那一季度的年末考試之後,有一個中年人在出口等她,他說自己是校長,要跟她聊一些事情,她一時有點恍神,就被帶到了另一間大房。Alice 聲稱沒有作弊,中年人揮著手笑說:
「妳是 Alice Hall,確認了。回到妳的問題,不是,妳沒有考試作弊。很多同學都做了人口普查了是嗎?」
她盡放鬆面部肌肉,回道:「是,我有留意到現在是人口普查的季節。」
她現在才看清這個中年人的細節,他是一個很乾淨的中年白人,但不知為何卻看不出一點細節,她確認自己看著他,而這個人卻似乎一點特徵都沒有。他就只是……權力的樣子。
校長說:
「那麼普查員到妳家中了嗎?」
有一刻,Alice 有大禍臨頭的感覺,有一瞬間。不過最後她還是比較淡定:「沒有……怎麼說好?他們確實來了,但只登記了我爸的電子手帶,對我基本上是置若罔聞,我們以為他們會分開來找我,但到現在都沒有,會是忘記了我嗎?」
校長聽完之後,點點頭:「原來是這樣,好的,沒事了,假期愉快。」他笑了,像一團模糊的幻覺陰影在微笑。校長走了不久,芝芝、Keiko、冬菇頭也出來,她們正討論要為 David 後援會設立一個信托基金,問她意見,她那一刻有點懊惱,只好答:
「在難民營也要搞信托嗎?」
轉念又覺得自己說了壞話,在難民營之中比較忌諱「難民營」這種字眼。人們不禁在兩種狀態中流轉,是承認這裡的暫時性,還是尋求終止它?但她們似乎沒有在意,一番迎送之後,她打起難民的精神獨自走回家。
她喜歡走路,在走路時似乎會想到很多事情,好像是自由的感覺。當然由大學走回家的路,已經走過很多次,沒有驚喜,但那天卻是陰雲密佈。她還是回家,因為那確實是她的家,還是她在做黑客賺的錢付擔的,但父親也在那裡。
突然被校長約談的經歷不尋常,Alice 開始想像父親那一方,如果有需要,他的供詞會對上嗎?他怎知道「應該」如何回應?應該跟他談這件事嗎?回家後,她最後沒有膽量提起,但父親先提起:「從以前走到現在,大家的日子都很難過。」
以前他會跟她談這些睡前故事,他們很多人都是逃避一場災難,飄洋過海來到這裡。但不是那個老版本:「大家都在逃避大戰的陰影,大家都在逃避一些事情。」
她回應:「逃來 C 區,因為有一個女兒,成為一個單親父親,獲得難民資格,是為了甚麼?」
事後回想,這句話,任何一個父親聽到都應該拍案而起或深感懊惱,但父親沒有,父親是平靜的,只是看到思緒的皺紋。他就像準備了這個演說很久,他退休前明明是一個能言善辯的記者,她有時不知道人們變老的時候是否都會變得沉默。
父親說:「我們都曾像你們一樣有好奇心……反正現在的東西,我已不知道了,其實根本沒有鹿鳴堂這間咖啡廳。」
她看看他,他又繼續說:「鹿鳴堂是我們那個年代的學運組織,我們都想往外跑,在網絡下載外面的東西……」她問:「然後…?」
他把身體往後靠攏,接著說:
「後來發生了很可怕的事,很多觸犯禁忌的同志都犧牲了,就這樣。妳想像不到,妳從那台機器知道很多吧?但很多資料都是破碎的,假造的,拜託,但妳只有 22 歲。真正發生過的東西只在我們的腦海之中。我是其中一些倖存的人。很多事情都發生在 C 區。」
這個故事,父親的確跟她聊過不只一次,不過年幼的時候,她理解為「爸爸在上一次大戰中倖存」。
「抱歉,我不能再說太多,人生嘛,一切都要妳自己領會。」他最後說。他的臉容平靜,富有人性,沒有絲毫的恐怖,也沒有拆穿女兒的一時之快。
Alice 朝他抬了抬眉,示意「知道了」,之後她謊稱去女朋友家過夜,就去了那個男孩的家。
當男人喜歡你的時候,你不需要逗留的藉口。雖然 Alice 有些懊惱,她努力尋找這個男同學的記憶碎片,她記得他多一點,他們才能談話,她才能獲得回應。有些時候你要承認,自己害怕寂寞。
最後只談到「我爸爸說了一些亂七八糟的話」,她就坐下來,喝著他提供的酒。難民營的人生活確實越來越好,連酒都很容易找到。雖然使用高速運算裝置的她如果有這種感想,亦是十分矛盾。
不記得名字的男孩也許以為她在煩惱家庭關係,但事情實在太複雜,她也願意他用一個簡化的版本來靠近自己。誰和誰不是這樣交往的?然後他們睡了一覺,他很有反應,但沒有做甚麼,Alice 覺得人和人能這樣交往,十分神奇。世界上有各種各樣的男人。但是躺得再近,她還是不敢坦露恐懼。如果在這種情況下懷疑自己的爸爸,她在地球上唯一的親人,聽起來十分可恥,然而她不敢回家,這是不是她恐懼和可恥的證據?
「謝謝你。」好像把不敢說的話這樣說了,才能心安。同床共枕的可恥,比不上動用自己的脆弱。人脆弱的時候,連冰山的雪花都是淫蕩的。
.4「因為你與我同在」
Alice 最後當然有回家,那確實是她的家。那個還未記得名字的男孩,Alice 本來沒有放在心上,但她之後將男孩放在心裡。
怎樣也好,他當日很保守的舉動,讓 Alice 感到他沒有自以為是踩入她的領域,這人值得記下。
她回去之後,也沒再跟父親再談當天的話題,他們又恢復日常的必要家居互動,自從那天她就沒有再進入難民營政府的系統,她只是個半桶水,反跟蹤程序根本可能無效,或者對方輕而易舉就破解了。總之,那些日子她的神經開始草木皆兵。
在學校,在同學朋友之前,她不會表露出內心的緊張。去到最後,她已經學會與這種內心永恆的緊張貼著臉相處,她察覺一切事物。如果這裡有人是告密者,是誰?芝芝、Keiko、冬菇頭,誰會出賣她?
有一天黃昏,在回家的必經之路,沿岸的一切都沐浴於血紅色的太陽之下,那裡有一個穿白裙的女孩,是 Keiko,她看到真實的 Keiko 的表情,那不是平日她示人的樣子。
Keiko 應該已經知道一切。她有一刻發現了這個眼前的事實。
最近的霉運總是將她殺得措手不及,但這一幕,Alice 在內心排演過很多次,是的,Keiko 總有一天會知道,原因根本不重要。是他告訴女兒,還是女兒發現的,都是折穿了她。
如同想像中的 Keiko,Keiko 快速走近,一巴掌打在她的臉,火辣辣的,混亂中 Alice 倒地,Keiko 壓過去讓她不能動彈,她可能吃過某些黑市流通的身體強壯藥,導致嬌小的 Keiko 這一刻力大無窮。在搏鬥中 Keiko 哭著大叫:「妳跟爸爸的事情是否真的?」
Keiko 沒有真的打她,而是倒在一旁。Keiko 的白裙此刻沾滿泥濘,泥土的味道十分特殊,Alice 就這樣躺著,看著沒有星光的星空。
夜幕裡沒有星的原因,是另一個區的照明系統影響這裡,相對的,我們也為其他區無法享受星空,作了應作的孽。
Keiko 哭著問她:「為甚麼是他?」
Alice 答:「這答案可能聽起來無情,但真的與 Keiko 妳沒有關係,純粹是 Mr Maekawa 和我自小就有很多交集,我從他那裡拿走了一台機器,在這段關係期間,我又學到了一些科技知識。這持續了可能六七年吧。」然後 Alice 開始朝她大喊:是的,他無疑是一頭禽獸,但如果沒有我的犧牲,妳是否也十分危險?說來……是否應該由我把妳撲倒?
她一邊說著,一邊爬起來,靠在路旁坐下。
Keiko 的聲音從後方傳來:「這是不是罪案?雖然那是我的爸爸,但那時他絕對在犯罪。」
Alice 回應:「如果我當時報警,你就會成為孤兒。在巨型難民營生活已經好痛苦了,在難民營裡面做孤兒只會更加痛苦。所以,我跟他的事以這種方式淡出,妳才不用做孤兒,妳成長階段一直都有這個爸爸,是我在背負你爸爸可怕的那一面,所以我總是羨慕你,我總是想做你的朋友,因為你擁有他好的那一面,爸爸的那一面,但我擁有的是他另一面。」
Keiko 喘氣的聲音在後面傳來。
Alice 也在鬧脾氣,從來沒人這樣打過她,所以她要恩將仇報。也許她可以選擇比較容易的路,選擇當一個受害者,是 Keiko 的惡魔電腦學家爸爸的受害者,然後受害者和兇手的女兒同樣可以做好朋友。
但 Alice 不願意視自己為受害者,她清楚知道記得自己當初發現 Mr Maekawa 這個不尋常的人,與他達成了協議,為了得到那台整個 C 區僅有一台的 Panasonic CF90 ,她知道自己選擇了不尋常的路徑。真可恥。對別人可以這樣說,讓他們用一個較能接受的版本跟她交往,但內心她知道自己沒那麼無辜。
既然不是無辜的,那就不用對自己好了,久而久之也忘記了對自己好是甚麼一回事。
機器現在屬於 Alice ,它的上一手主人是 Mr Maekawa,Mr Maekawa 從一位智能機械幕僚「阿福」手中買到,那是阿福不要的昂貴玩具之一。
阿福是「白皇帝」第六幕僚團成員,主要功能是增加 Fauci 總督的電子腦與雲端運算的聯絡速度,明乎其實是他的大腦 (之一)。由於總督的官邸是模仿美國內戰前的第一代白宮,而他又掌權了極長時間,富有詩情的人們開始用 Constantius the Pale 形容他。這位各國機構委任的難民營長,幾乎獲得一切緊急權力,他本人也是一台行走的決策運算機。
關於他身上的數據魔法,只有極少數人知道,而大部份都是吹牛,再加上宣傳部門故意放出的惡搞版本。只知道有人認為白福奇將自己的腦袋換成了電子腦,而不是電子加強,方便隨時無間斷讀取資訊和決策推介,因此他也在無時無刻讀取民意。
由於難民區甚至這個國家對電子運算的強烈壓抑,每個人的運算力都很有限,除非用其他手段獲得。「白皇帝」卻被譽為擁有情報預知力的人型機算機,他逃過了幾十宗暗殺,並且歷史一直以勝利的甘露膏抹他。
他快速解決了上一次大戰之後的某一餘波而製造的幾百萬難民,將這裡發展成可以宜居、有經濟產出的地方。所以國際聯盟暫時仍然支持總督「暫時管理」這個難民帝國。
總督已經不只是一個人,而是一個機構,他身上的寬頻多到可以分出來管理區內交通燈、警署報案系統、某一次警隊攻陷行動的前期及中期部署,全部都可以透過他的意志來操作,而結果又總是顯示:聽從「皇帝」指示總是如有神助。
他簡直是先知。
而眼前這台計算機,應該算是那一班人一時心血來潮玩過的潮物,而今天讓她撿了二手。雖然二手,但她付出了無法正常戀愛的代價。因為 Mr Maekawa 是一個天才,也是一個禽獸。這是一個分化的社會,但當你未見過另一座山,你不會知道自己有多小。
神話故事中掉入凡間的神劍魔斧,就是仙人的模型玩具。是的,她從歷史課有聽過,在大戰期間,有些地方連出賣肉體已經沒法令人基本吃飽,人們基本上都在吃人肉。當她想到這些,就會覺得自己不算宇宙中最慘的人,這想法聊勝於無,是不?
「Alice ,原來妳是那麼嘔心的人。」Keiko 最後像總結一樣說。
「妳也很嘔心,妳令我想起他。」Alice 回應。
.4 「使世界如同荒野,是這個人嗎?」
芝芝和冬菇頭的準備工作密鑼緊鼓,在 Alice 不為意的時候,她們已經召集了二百個義工會員,還有會員 T-Shirt 和整套制服。據芝芝在聚會時透露,David 來到最近 C 區那一站,就開始起動,開始招收會員。芝芝說到這些的時候兩眼放光。
Alice 看到她們,內心不禁有點悵悵,她不想成為別人的焦點,生怕被人注意到,但她們倒是不怕的,很羨慕。
冬菇頭是真心熱愛 David 的,但由於 David 並不是極少數被認可能夠輸入到難民區的藝人,冬菇頭從小把自己養成了走私行業的專家,通過她家人的關係,可以偷運各種違禁品,包括偶像的商品。
一個冬天的演員會,在盛夏開始籌備。最後她們真的成立了公司,並且獲得 David 在網上認證,等於把這一區難民歌迷的事務交給她們了。一時間,芝芝和冬菇頭變得位高權重,走路有風。有一日芝芝問:
「Alice 妳畢業之後有甚麼打算嗎?過來我們公司幫手吧,我們很需要人手呢﹗」
Alice 微笑著回應她:「好吧,但給我考慮一下,技術上我們還未行禮,還可以優哉遊哉。」
事實上,大學畢業,還是難民,不容易找到好工作。對於 Alice 來說,自己在海外的幾十個戶口已經堆滿錢。父親有時問為甚麼從未見她上學,她會隨口答:me 已經退休了,父親以為她在胡言亂語。但她實際上確實不打算去當個荷官,雖然她數學相當好,但問題純粹是,為甚麼?
她除了偶爾去上課之外,大部份精力都用在管理自己的海外資產,雖然實際上總資產不多,但都是各種加密貨幣,相對安全。
David 在「新住民區」(一個較文雅的講法) 第一場巡迴演員會就在 12 月 24 日晚上,第一場是 C 區。
新中央日報一條新聞廣播:
「國外藝人 David Song 破天荒獲准在 13 區表演,是不是北大西洋國向我國釋出善意獲得積極回應?這會是東盟與北大西洋國長期停火後的交往預熱嗎?」
入秋之後,C 區也湧入越來越多外面人,他們也想來看演唱會,難民觀眾和其他觀眾因為買票的問題而引發街頭鬥毆,有一晚搞到全城宵禁,網絡受到大重置,害她又花了很多時間重新做上網設定。
經過那次跟 Keiko 衝突之後,Alice 對維繫那段關係沒有甚麼想法,它最後好也罷,不好也罷,如果人們在自己人生的低潮,漸漸就不會計較太多事情。
不知為何那天的事似乎連芝芝都知道了,怎麼都好,她不想理會,沒法隨意上網帶來的壓力,令她不太能集中。
芝芝約 Alice 在 12 月 24 日下午「出來玩」,芝芝說話時很神秘,「是開騷前的 party ,可以見到 David 本人。」
Alice 卻不想見那個人,她只好問:「為甚麼我也有份?」
芝芝回道:「因為然是我們後援會的技術總監,所以妳也一起來吧,他真人很不可思議的。妳不想認識他嗎?」
Alice 問芝芝:「這不是甚麼選妃的環節吧?」
芝芝連忙否認:「不是這種啦,是說請妳作為 VIP 去,跟另外那種不同。」
她問:「所以妳真是已經開始幹這個生意了?」
芝芝聳了聳背,她說:「女孩都要吃飯的嘛」。
Alice 回應:「好吧,只要我在的那個場合不是在搞選妃就好。」
她們說 Keiko 也會來,但她會在午夜的那一場慶功裡出現,就是不想見到 Alice 嗎?嗯,那次說的話確實很過份。她想。
「這確實只是普通飲料、普通閒聊的派對?」
芝芝再三強調:「是的,只有普通飲料和普通閒聊,耶穌,妳骨子裡其實也很煩呢。」
David 的音樂會在 3 區中央公園舉行,中央公園被一群模仿熱帶樹林的人造樹林包圍,經過樹林會進入一個人造沙灘,這裡卻沒有海。舞台就在最中心位置,在後台有一條延長出去的草地,回到樹林,再回到外面的世界。他們在後台的後方幾十萬處搭了一個男人身高的帳篷,他們就好像傳說故事中的蒙古包。
那次見面究竟是怎樣的,相較之後的事情實在過於平淡,事後反而很難想得起。或者她懷疑是某種精神控制技術,強行蒙蔽了某些記億。
David 來了,他是一個高瘦的男人,穿著休憩的黑色睡衣,但看來是另一個世界的產物,充滿光澤,跟難民區可以買到的高級服飾,完全像是兩種事物。但他一把油頭、滿臉鬍渣,「他們還未開始準備。」她想。
芝芝和冬菇頭在跟這個親切的男人聊了一陣,然後她們向她介紹 Alice,對方望望她,走過來跟她握手,彷彿她真的是他這個粉絲後援會的技術總監。當時一開始談了甚麼,也不記得。後來大家互相傳著酒杯,分享起酒精來。後來芝芝和冬菇頭勁頭過了之後,去了處理一些「會務」,David 和 Alice 並肩站在夕陽之中,朝著他即將要開騷的那個會場,他雖然待在陰影中,但又好像晨光的寵兒。夕陽和清晨明明是兩種相對的事物,卻又是相像的現象。她是屬於晚上的,而他在鏡頭前總是出現在白天。
他們明明互不認識。她暗中調查過他,但這自然不是算是認識。
Alice 說:「我知道這個機會很難得,所以我可以問一個問題嗎?」
「請。」
「有人批評你的音樂吧?」
對方認真地想了一陣:「我覺得這是大家對成功有不同定義……有時作為一個創作者,用一般的方法獲得的成功也是成功,但在裡面我是不自由的,我總是知覺到自己需要做好某些本份,所以我有時會想在裡面鑽一些洞……當然我還在努力,這些實驗雖然很多我都認為成功了,但無疑也是有失敗的。希望之後能做出讓妳喜歡的音樂。」
Alice 轉個頭望了望他。「好,你做出了,到時我來聽。」
「妳在萬聖節時會扮女巫嗎?」
她搖頭。舞台那邊還發放煙花,觀眾似乎正在入場。
「上網的人某程度上也像女巫吧?」他又繼續逗她說話。
「放煙花了。」她說:「但我的朋友還沒回來。」
「她們回不來了。」David 望著遙遠的彩色耀光,如此說。
「為甚麼?」
「妳可以看到的人口普查,但也有一個異常的人口普查。這裡很多人口當初植入的行為控制晶片,是一批次貨。這涉及一些很複雜的數學問題。總之,接種了次貨晶片的人,慢慢就會出現精神疾病。兩個人口普查都是為了維修那一顆晶片,或者說更新它的韌體。如果不更新韌體,會影響最終的統計數據。科技會產生各種錯誤訊號,我的職責是負責偵測特定種類的錯誤晶片訊號。」
彷彿有一道可怕的閃光照顧她。
David 繼續說:「所以有人將我吸引到的粉絲,都錄制了名單,方便之後慢慢更新。」
「她們會面對甚麼?」如果不是好奇,不應繼續搭話。
「沒有甚麼,他們很人道的,只是更新一下那塊晶片,但那一刻我的粉絲就不會再愛我。他們會離開這個圈,妳的朋友也已經在登記中,但我打算放妳離開,讓妳記得這一切。」
……
「你是政府的人嗎?」
「他們造出來的生化人。我的臉孔可以隨意改變,我的人格則來自幾百萬個模擬程式互相混合的結果,其他的『我』性格完全不一樣。即使我在這裡突然被槍殺,新聞不會傳出去,這個事業也不會停,會有人代表我演出 David 這個角色。所有放出去的魚鉤都是這樣。」
……
「為甚麼跟我說這些莫名其妙的話?」她望著他,這人正在一口一口的喝酒,可以理解為超級巨星也會發酒瘋吧?
「因為接下來我只有一些時間交代妳有多重要這個問題。」
「請說。」
「如我所說,這些組織起來的人口,都會登續登記新設定檔,妳沒有登記,這才令我我注意到,應該交給上級機關。不過我沒有,想起來,我違反了守則。」
不知道是否酒醉,David 背後那個蒙古包正在飄浮,閃著妖異的光暈。她想離開,但是腳不聽使喚,她只好在醉感中聽他把話說完。
他的話音繼續傳來:「這是現實,我也說了,我是設計來吸引某種帶著缺憾的人,妳可以理解為一個精神控制的光環,妳的朋友也是我使喚走的,雖然妳不會知道傳遞方式。妳其中一個朋友以 Morgan 的名義招集打手,在我這條生產線上的下游員工,就會以此挑起爭論。她本來以為完成這件事,就可以成為 C 區的後援會首領,從她那裡,我也知道了關於妳的所有事。但這件事在今晚之後就會終結。」
「回到我們的話題,關於納米晶片(行為治療)二型的事情,妳查了很多,但都是不正確資料,我透露的比較完整。」
「一直是你負責監控我?為甚麼說了那麼多奇怪的話?你還好嗎?」她覺得很累,便躺坐下來。這很像一個暖水般的夢。
「我的時間緊迫,我要在我忘記這些事之前,讓妳記住。」他的視線投向沒有星星的夜空:「他們發現這個紀錄,我就會被回收,我的記憶會被清洗,這可以換取妳不被暴露。」
「你想要甚麼?」不知為何,她流出淚來,但她並不傷心,湧出的淚水更像是生物肉體受到某種輻射而產生的變異。
「被記住,就像明星一樣。」他微笑:「跟所有人一樣。你們像我們一樣被設定了軌道,無論多慢也好,總有人會走出另一條路。處於我們那個維度的物種,也會偶爾反抗。人們總是回到一樣的道路,但要有希望,而我擁有億萬個組合撞出來的這一個人格,這一個人格的任務成功率只有 99.9%,絕大部份時間我都服從我的本體,但有很微小的機會還是會出現 malfunction。」
她睡著了,或者是說失去知覺,在模糊中她感受到蒙古包外面捲起一股強風,是一架直昇機,上面下來了幾個男人,那個人自願跟著他們上機——下一個畫面是在醫院。
據說中央公園發生了氣體泄漏,所有觀眾疏散,音樂會無限期停止。後來 David 繼續前往其他國家演唱,但很奇怪的是,似乎由 C 區開始,Daivd 的人氣就馬上急降,他的商品、代言產品都成為蟹貨。他像旋風一樣,但在正式登陸之前離奇折翼。整個 C 區彷彿沒有發生過任何特別事情。畢竟疑似恐襲、藝人因為某些原因而無法演唱,對一般人來說司空見慣。
芝芝、Keiko、冬菇頭和 Alice 一樣,都在中區醫院醒來。據說大家都吸入了不明氣體,但都沒有永久傷害。Alice 想起,這就像上一次她們遇到那條浮屍,她們目擊了甚麼,好像記得了甚麼,但之後一切都會恢復正常。
.5 MALFUNCTION
政府化武部隊徹底清洗了中央公園。
對於 David 為何突然辭演退票,甚至出現很多種不同解釋,包括有人認為當晚有 UFO 擄人和襲擊、地底怪物出現、大戰正以隱秘方式重新爆發、觀眾集體出現多重記憶等等,有很多神秘兮兮的傳說。但她不認為如果告訴 C 區人民他們是一個大型行為—精神實驗的白老鼠同伴,這就好嗎?不會好。
整個難民城市計劃,在人口數十萬數十萬滅絕的大環境下,任何混合著科學實驗、慈善、經濟復興資源競爭的大型人口實驗,都比起大戰爆發前更容易建立。這裡也是填海出來的,人可以改造自然,憑甚麼又不能改造人類?難民營有多少人被改造了?有人的能力被加強了?有人的能力被削弱了?不敢想像下去。
夜深人靜的時候, Alice 會回憶那個夢一般的談話,記憶好像碎片,不斷拾起碎片,碎片好像變得越來越多,分不清哪些是先,哪些是後。但在不斷回憶中,她好像慢慢了解皮膚下的那個 David 交托了甚麼給她,似乎是很有重量的東西。
有很多夢都是在醒來之後逐漸記起來,原來昨晚造了一個夢。關於那個明星的事也是這樣。
「為甚麼白白放過我?」因為我不是無辜的,我已經被沾污了。
David 皮膚下的那個人向她揮手,像明星向粉絲揮手:「這是白白給妳的赦免,我賭上自己的權限清洗妳的改動記錄,因為希望是從虛無裡面來的,我是從數據污垢裡面走出來的,這是我第一次反抗,也是我第一次赦免人。」
在很多海盜網民的私下討論中,「白皇帝」也指涉整個城市的人工智能維生體系,這是所有情報的主要海洋,他們開始認為,總督已經跟生化機器融為一體,已經無法以人類的標準去看,簡直是活著的神。他知道世上所有事情,所以他是否知道他旗下的某一個 David 選擇違反本能、靜悄悄地自我毀滅,本來完美的數學算式出現了意料之外的答案?
有一晚她睡不著,到客廳去坐著,父親也在那裡,她坐下,這次她主動開口:「可以問一個問題嗎?」
他說:「sure。」
她說:「現在我有點明白你說的,你是倖存者的意思。」他喝茶,暫未回答。
「我發現一個人,他似乎無條件愛我,那種愛是令人恐懼的、陌生的,而現在這段關係已經死了,而我卻似乎生存了下來。」
父親說:「妳想跟他復合嗎?」Alice 願意父親了解自己比較顯淺的那個版本。
「但這不可能,那不是男人和女人之間的事,我不知如何解釋。」
父親問:「那妳還愛他嗎?」
現在已經完全感受不到,因為她的晶片已經暗中被更新過吧?現在 David 是一個令她情緒上討厭的存在,但她記得另一個 David,那個由人類創造的物種,竟然把希望寄托在人類身上。
她不置可否:「我收到他的心意,應該這樣說吧?」
她不打算說對方「自殺」了。
黑夜還很漫長,還有很久才會破曉。父親點頭:「是個怎樣的人?」她想了一下,結論道:「他是個會自己拿主意的人。比我見過的任何人都有主見。」那這個人很好啊,父親說。
完
17.9.2021
訂閱 patreon https://www.patreon.com/lewisdada
盧斯達新書 《如水赴壑—香港歷史與意識之流》:https://tinyurl.com/eyd9258v
完全二元樹 在 在地上滾的工程師 Nic Youtube 的最佳貼文
硬核的知識也許不是每個工程師都能夠在職涯發展中完全運用到,但無論是本科系、轉職、自學成為工程師的朋友,都應該要知道,這些紮實的背景知識提早學習起來,在未來的日子裡,只有好沒有壞。
就透過本影片我的真實經驗分享,告訴你這些我在大學時期看似枯燥乏味的理論,其實就是程式設計內功,而日後沉睡已久的內功卻又恰巧的在職涯旅途中碰上用處。
章節:
00:00 學這些有用嗎
00:52 我與速成班的距離
04:45 業務增長後的影響
06:36 基本功知識科普
喜歡影片的話!可以幫忙點個喜歡以及分享、訂閱唷!😘
━━━━━━━━━━━━━━━━
⭐ 蝦皮賣場: https://shopee.tw/bboyceo
⭐ instagram (生活日常): https://www.instagram.com/niclin_tw/
⭐ Facebook (資訊分享): https://www.facebook.com/niclin.dev
⭐ Blog (技術筆記): https://blog.niclin.tw
⭐ Linkedin (個人履歷): https://www.linkedin.com/in/nic-lin
⭐ Github: https://github.com/niclin
⭐ Podcast: https://anchor.fm/niclin
━━━━━━━━━━━━━━━━
🌟 任何問題或合作邀約信箱: niclin0226@gmail.com
#資料結構 #演算法 #計算機概論 #前端 #後端 #工程師
![post-title](https://i.ytimg.com/vi/-Y_4rOXeqHQ/hqdefault.jpg)
完全二元樹 在 JavaScript 學演算法(十二)- 樹& 二元樹 - 竹白記事本 的推薦與評價
二元樹 (Binary tree),簡單來說就是限制每個節點最多只能有兩個的子節點, ... 歪斜樹(Skewed Tree),指一棵樹完全沒有左或右其中一邊節點的二元 ... ... <看更多>
完全二元樹 在 [理工] 完整二元樹問題- 看板Grad-ProbAsk - PTT網頁版 的推薦與評價
假設有一棵完整二元樹,其高度h=4時, 請問此棵二元樹的節點數n 最少與最多各多少? 解答給n的範圍是:7 < n < 15 我的疑問: 是不是7 < n <= 15才對? 因為完滿二元樹 ... ... <看更多>
完全二元樹 在 [討論] binary tree - 看板ncyu_phyedu - 批踢踢實業坊 的推薦與評價
在電腦科學中,二元樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱作「左子樹」(left subtree)和「右子樹」(right subtree)。二元樹常被用於實現二元搜尋樹和二叉堆。
二元樹的每個結點至多只有二棵子樹(不存在度大於2的結點),二元樹的子樹有左右之分,次序不能顛倒。二元樹的第i層至多有個結點;深度為k的二元樹至多有個結點;對任何一棵二元樹T,如果其終端結點數為,度為2的結點數為,則。
樹和二元樹的三個主要差別:
1.樹的結點個數至少為1,而二元樹的結點個數可以為0;
2.樹中結點的最大度數沒有限制,而二元樹結點的最大度數為2;
3.樹的結點無左、右之分,而二元樹的結點有左、右之分。
<完全二元樹和滿二元樹>
1.滿二元樹:一棵深度為k,且有個節點成為滿二元樹
2.完全二元樹:深度為k,有n個節點的二元樹,若且唯若其每一個節點都與深度為k的滿二元樹中序號為1至n的節點對應時,稱之為完全二元樹
目錄 [隱藏]
1 圖論中的定義
2 二元樹(Binary Tree)的類型
3 存儲二元樹的方法
3.1 順序存儲表示
3.1.1 儲存結構
3.1.2 基本操作
3.2 二叉鏈表存儲表示
3.2.1 存儲結構
3.2.2 基本操作
3.3 三叉鏈表存儲表示
3.3.1 存儲結構
3.3.2 基本操作
4 訪問二元樹的方法
4.1 前(先)序、中序、後序遍歷
4.2 深度優先遍歷
4.3 廣度優先遍歷
5 將n叉樹轉換為二元樹
5.1 存儲結構與基本操作
5.1.1 樹的二叉鏈表存儲表示
5.1.2 樹的二叉鏈表存儲的基本操作
6 線索二元樹 (threaded binary tree)
6.1 二叉線索存儲表示
6.1.1 存儲結構
6.1.2 基本操作
[編輯] 圖論中的定義二元樹在圖論中是這樣定義的:二元樹是一個連通的無環圖,並且每一個頂點的度不大於3。有根二元樹還要滿足根結點的度不大於2。有了根結點之後,每個頂點定義了唯一的父結點,和最多2個子結點。然而,沒有足夠的訊息來區分左結點和右結點。如果不考慮連通性,允許圖中有多個連通分量,這樣的結構叫做森林。
[編輯] 二元樹(Binary Tree)的類型二元樹是一個有根樹,並且每個節點最多有2個子節點。非空的二元樹,若樹葉總數為 n0,分支度為2的總數為 n2,則 n0 = n2 + 1。
一棵深度為k,且有個節點的二元樹,稱為滿二元樹(Full Binary Tree)。這種樹的特點是每一層上的節點數都是最大節點數。在一棵二元樹中,除最後一層外,若其餘層都是滿的,並且最後一層或者是滿的,或者是在右邊缺少連續若干節點,則此二元樹為完全二元樹(Complete Binary Tree)。具有n個節點的完全二元樹的深度為。深度為k的完全二元樹,至少有個節點,至多有個節點。
Complete Binary Tree Full Binary Tree
總節點k < k < k =
樹高h h = h =
[編輯] 存儲二元樹的方法在編程語言中能用多種方法來構造二元樹。
[編輯]
順序存儲表示二元樹可以用數組或線性表來存儲,而且如果這是完全二元樹,這種方法不會浪費空間。用這種緊湊排列,如果一個結點的索引為i,它的子結點能在索引2i+1和2i+2找到,並且它的父節點(如果有)能在索引floor((i-1)/2)找到(假設根節點的索引為0)。這種方法更有利於緊湊存儲和更好的訪問的局部性,特別是在前序遍歷中。然而,它需要連續的存儲空間,這樣在存儲高度為h的n個結點組成的一般普通樹時將會浪費很多空間。一種最極壞的情況下如果深度為h的二元樹每個節點只有右孩子需要佔用2的h次冪減1,而實際卻只有h個結點,空間的浪費太大,這갊O順序存儲結構的一大缺點。
[編輯] 儲存結構 /* 二叉?的?序存?表示 */
#define MAX_TREE_SIZE 100 /* 二叉?的最大??? */
typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0??元存?根?? */
typedef struct
{
int level,order; /* ??的?,本?序?(按?二叉??算) */
}position;
[編輯] 基本操作顯示▼隱藏▲基於C/C++的實作演算法 /* 二叉?的?序存?的基本操作(23?)*/
#define ClearBiTree InitBiTree /* 在順序存儲結構中,兩函數完全一樣 */
#define DestroyBiTree InitBiTree /* 在順序存儲結構中,兩函數完全一樣 */
void InitBiTree(SqBiTree T) ---(SqBiTree & T)
{ /* 構造空二叉樹T。因為T是數組名,故不需要& */
int i;
for(i=0;i<MAX_TREE_SIZE;i++)
T[i]=Nil; /* 初值為空(Nil在主程中定義) */
}
void CreateBiTree(SqBiTree T)
{ /* 按層序次序輸入二叉樹中結點的值(字符型或整型), 構造順序存儲的二叉樹T */
int i=0;
#if CHAR /* 結點類型為字符 */
int l;
char s[MAX_TREE_SIZE];
InitBiTree(T); /* 構造空二叉樹T */
printf("請按層序輸入結點的值(字符),空格表示空結點,結點數≦%d:\n",MAX_TREE_SIZE);
gets(s); /* 輸入字符串 */
l=strlen(s); /* 求字符串的長度 */
for(;i<l;i++) /* 將字符串賦值給T */
T[i]=s[i];
#else /* 結點類型為整型 */
InitBiTree(T); /* 構造空二叉樹T */
printf("請按層序輸入結點的值(整型),0表示空結點,輸999結束。結點數≦%d:\n",MAX_TREE_SIZE);
while(1)
{
scanf("%d",&T[i]);
if(T[i]==999)
{
T[i]=Nil;
break;
}
i++;
}
#endif
for(i=1;i<MAX_TREE_SIZE;i++)
if(T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此非根結點(不空)無雙親 */
{
printf("出現無雙親的非根結點"form"\n",T[i]);
exit(ERROR);
}
}
Status BiTreeEmpty(SqBiTree T)
{ /* 初始條件:二叉樹T存在。操作結果:若T為空二叉樹,則返回TRUE,否則FALSE */
if(T[0]==Nil) /* 根結點為空,則樹空 */
return TRUE;
else
return FALSE;
}
int BiTreeDepth(SqBiTree T)
{ /* 初始條件:二叉樹T存在。操作結果:返回T的深度 */
int i,j=-1;
for(i=MAX_TREE_SIZE-1;i>=0;i--) /* 找到最後一個結點 */
if(T[i]!=Nil)
break;
i++; /* 為了便於計算 */
do
j++;
while(i>=pow(2,j)); /*pow是原型為double pow( double x, double y ),計算x的y次方,h = log<sub>2</sub>k + 1來計算二叉樹的深度*/
return j;
}
Status Root(SqBiTree T,TElemType *e)
{ /* 初始條件:二叉樹T存在。操作結果:當T不空,用e返回T的根,返回OK;否則返回ERROR,e無定義 */
if(BiTreeEmpty(T)) /* T空 */
return ERROR;
else
{
*e=T[0];
return OK;
}
}
TElemType Value(SqBiTree T,position e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點(的位置) */
/* 操作結果:返回處於位置e(層,本層序號)的結點的值 */
return T[(int)pow(2,e.level-1)+e.order-2];
}
Status Assign(SqBiTree T,position e,TElemType value)
{ /* 初始條件:二叉樹T存在,e是T中某個結點(的位置) */
/* 操作結果:給處於位置e(層,本層序號)的結點賦新值value */
int i=(int)pow(2,e.level-1)+e.order-2; /* 將層、本層序號轉為矩陣的序號 */
if(value!=Nil&&T[(i+1)/2-1]==Nil) /* 給葉子賦非空值但雙親為空 */
return ERROR;
else if(value==Nil&&(T[i*2+1]!=Nil||T[i*2+2]!=Nil)) /* 給雙親賦空值但有葉子(不空) */
return ERROR;
T[i]=value;
return OK;
}
TElemType Parent(SqBiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點 */
/* 操作結果:若e是T的非根結點,則返回它的雙親,否則返回”空” */
int i;
if(T[0]==Nil) /* 空樹 */
return Nil;
for(i=1;i<=MAX_TREE_SIZE-1;i++)
if(T[i]==e) /* 找到e */
return T[(i+1)/2-1];
return Nil; /* 沒找到e */
}
TElemType LeftChild(SqBiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點。操作結果:返回e的左孩子。若e無左孩子,則返回"空" */
int i;
if(T[0]==Nil) /* 空樹 */
return Nil;
for(i=0;i<=MAX_TREE_SIZE-1;i++)
if(T[i]==e) /* 找到e */
return T[i*2+1];
return Nil; /* 沒找到e */
}
TElemType RightChild(SqBiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點。操作結果:返回e的右孩子。若e無右孩子,則返回"空" */
int i;
if(T[0]==Nil) /* 空樹 */
return Nil;
for(i=0;i<=MAX_TREE_SIZE-1;i++)
if(T[i]==e) /* 找到e */
return T[i*2+2];
return Nil; /* 沒找到e */
}
TElemType LeftSibling(SqBiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點 */
/* 操作結果:返回e的左兄弟。若e是T的左孩子或無左兄弟,則返回”空” */
int i;
if(T[0]==Nil) /* 空樹 */
return Nil;
for(i=1;i<=MAX_TREE_SIZE-1;i++)
if(T[i]==e&&i%2==0) /* 找到e且其序號為偶數(是右孩子) */
return T[i-1];
return Nil; /* 沒找到e */
}
TElemType RightSibling(SqBiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點 */
/* 操作結果:返回e的右兄弟。若e是T的右孩子或無右兄弟,則返回”空” */
int i;
if(T[0]==Nil) /* 空樹 */
return Nil;
for(i=1;i<=MAX_TREE_SIZE-1;i++)
if(T[i]==e&&i%2) /* 找到e且其序號為奇數(是左孩子) */
return T[i+1];
return Nil; /* 沒找到e */
}
void Move(SqBiTree q,int j,SqBiTree T,int i) /* InsertChild()用到。加 */
{ /* 把從q的j結點開始的子樹移為從T的i結點開始的子樹 */
if(q[2*j+1]!=Nil) /* q的左子樹不空 */
Move(q,(2*j+1),T,(2*i+1)); /* 把q的j結點的左子樹移為T的i結點的左子樹 */
if(q[2*j+2]!=Nil) /* q的右子樹不空 */
Move(q,(2*j+2),T,(2*i+2)); /* 把q的j結點的右子樹移為T的i結點的右子樹 */
T[i]=q[j]; /* 把q的j結點移為T的i結點 */
q[j]=Nil; /* 把q的j結點置空 */
}
void InsertChild(SqBiTree T,TElemType p,int LR,SqBiTree c)
{ /* 初始條件:二叉樹T存在,p是T中某個結點的值,LR為0或1,非空二叉樹c與T不相交且右子樹為空 */
/* 操作結果: 根據LR為0或1,插入c為T中p結點的左或右子樹。p結點的原有左或右子樹則成為c的右子樹 */
int j,k,i=0;
for(j=0;j<(int)pow(2,BiTreeDepth(T))-1;j++) /* 查找p的序號 */
if(T[j]==p) /* j為p的序號 */
break;
k=2*j+1+LR; /* k為p的左或右孩子的序號 */
if(T[k]!=Nil) /* p原來的左或右孩子不空 */
Move(T,k,T,2*k+2); /* 把從T的k結點開始的子樹移為從k結點的右子樹開始的子樹 */
Mov/* InOrderTraverse()調用 */
if(T[2*e+1]!=Nil) /* 左子樹不空 */
InTraverse(T,2*e+1);
VisitFunc(T[e]);
if(T[2*e+2]!=Nil) /* 右子樹不空 */
InTraverse(T,2*e+2);
}
void InOrderTraverse(SqBiTree T,void(*Visit)(TElemType))
{ /* 初始條件:二叉樹存在,Visit是對結點操作的應用函數 */
/* 操作結果:中序遍歷T,對每個結點調用函數Visit一次且僅一次 */
VisitFunc=Visit;
if(!BiTreeEmpty(T)) /* 樹不空 */
InTraverse(T,0);
printf("\n");
}
void PostTraverse(SqBiTree T,int e)
{ /* PostOrderTraverse()調用 */
if(T[2*e+1]!=Nil) /* 左子樹不空 */
PostTraverse(T,2*e+1);
if(T[2*e+2]!=Nil) /* 右子樹不空 */
PostTraverse(T,2*e+2);
VisitFunc(T[e]);
}
void PostOrderTraverse(SqBiTree T,void(*Visit)(TElemType))
{ /* 初始條件:二叉樹T存在,Visit是對結點操作的應用函數 */
/* 操作結果:後序遍歷T,對每個結點調用函數Visit一次且僅一次 */
VisitFunc=Visit;
if(!BiTreeEmpty(T)) /* 樹不空 */
PostTraverse(T,0);
printf("\n");
}
void LevelOrderTraverse(SqBiTree T,void(*Visit)(TElemType))
{ /* 層序遍歷二叉樹 */
int i=MAX_TREE_SIZE-1,j;
while(T[i]==Nil)
i--; /* 找到最後一個非空結點的序號 */
for(j=0;j<=i;j++) /* 從根結點起,按層序遍歷二叉樹 */
if(T[j]!=Nil)
Visit(T[j]); /* 只遍歷非空的結點 */
printf("\n");
}
void Print(SqBiTree T)
{ /* 逐層、按本層序號輸出二叉樹 */
int j,k;
position p;
TElemType e;
for(j=1;j<=BiTreeDepth(T);j++)
{
printf("第%d層: ",j);
for(k=1;k<=pow(2,j-1);k++)
{
p.level=j;
p.order=k;
e=Value(T,p);
if(e!=Nil)
printf("%d:"form" ",k,e);
}
printf("\n");
}
}
[編輯] 二叉鏈表存儲表示
基於連結串列的二元樹邏輯結構示意在使用記錄或記憶體位址指標的編程語言中,二元樹通常用樹結點結構來存儲。有時也包含指向唯一的父節點的指針。如果一個結點的子結點個數小於2,一些子結點指針可能為空值,或者為特殊的哨兵結點。 使用連結串列能避免順序儲存浪費空間的問題,演算法和結構相對簡單,但使用二叉連結串列,由於缺乏父鏈的指引,在找回父節點時需要重新掃描樹得知父節點的節點位址。
[編輯] 存儲結構/* 二叉樹的二叉鏈表存儲表示 */
typedef struct BiTNode
{
TElemType data;
struct BiTNode *lchild,*rchild; /* 左右孩子指針 */
}BiTNode,*BiTree;
[編輯] 基本操作顯示▼隱藏▲基於C/C++的實作演算法 /* 二叉樹的二叉鏈表存儲的基本操作(22個) */
#define ClearBiTree DestroyBiTree /* 清空二叉樹和銷毀二叉樹的操作一樣 */
#include"func6-3.c"
/* 包括InitBiTree()、DestroyBiTree()、PreOrderTraverse()和InOrderTraverse()4函數 */
void CreateBiTree(BiTree *T)
{ /* 算法6.4:按先序次序輸入二叉樹中結點的值(可為字符型或整型,在主程中定義),*/
/* 構造二叉鏈表表示的二叉樹T。變量Nil表示空(子)樹。有改動 */
TElemType ch;
scanf(form,&ch);
if(ch==Nil) /* 空 */
*T=NULL;
else
{
*T=(BiTree)malloc(sizeof(BiTNode)); /* 生成根結點 */
if(!*T)
exit(OVERFLOW);
(*T)->data=ch;
CreateBiTree(&(*T)->lchild); /* 構造左子樹 */
CreateBiTree(&(*T)->rchild); /* 構造右子樹 */
}
}
Status BiTreeEmpty(BiTree T)
{ /* 初始條件:二叉樹T存在。操作結果:若T為空二叉樹,則返回TRUE,否則FALSE */
if(T)
return FALSE;
else
return TRUE;
}
int BiTreeDepth(BiTree T)
{ /* 初始條件:二叉樹T存在。操作結果:返回T的深度 */
int i,j;
if(T==NULL) /*如果T=NULL,???便于理解,?然也可以?成if(!T)*/;
return 0; /* 空樹深度為0 */
if(T->lchild)
i=BiTreeDepth(T->lchild); /* i為左子樹的深度 */
else
i=0;
if(T->rchild)
j=BiTreeDepth(T->rchild); /* j為右子樹的深度 */
else
j=0;
return i>j?i+1:j+1; /* T的深度為其左右子樹的深度中的大者+1 */
}
TElemType Root(BiTree T)
{ /* 初始條件:二叉樹T存在。操作結果:返回T的根 */
if(BiTreeEmpty(T))
return Nil;
else
return T->data;
}
TElemType Value(BiTree p)
{ /* 初始條件:二叉樹T存在,p指向T中某個結點。操作結果:返回p所指結點的值 */
return p->data;
}
void Assign(BiTree p,TElemType value)
{ /* 給p所指結點賦值為value */
p->data=value;
}
typedef BiTree QElemType; /* 設隊列元素為二叉樹的指針類型 */
#include"c3-2.h" /* 鏈隊列 */
#include"bo3-2.c" /* 鏈隊列的基本操作 */
TElemType Parent(BiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點 */
/* 操作結果:若e是T的非根結點,則返回它的雙親,否則返回”空”*/
LinkQueue q;
QElemType a;
if(T) /* 非空樹 */
{
InitQueue(&q); /* 初始化隊列 */
EnQueue(&q,T); /* 樹根指針入隊 */
while(!QueueEmpty(q)) /* 隊不空 */
{
DeQueue(&q,&a); /* 出隊,隊列元素賦給a */
if(a->lchild&&a->lchild->data==e||a->rchild&&a->rchild->data==e)
/* 找到e(是其左或右孩子) */
return a->data; /* 返回e的雙親的值 */
else /* 沒找到e,則入隊其左右孩子指針(如果非空) */
{
if(a->lchild)
EnQueue(&q,a->lchild);
if(a->rchild)
EnQueue(&q,a->rchild);
}
}
}
return Nil; /* 樹空或沒找到e */
}
BiTree Point(BiTree T,TElemType s)
{ /* 返回二叉樹T中指向元素值為s的結點的指針。另加 */
LinkQueue q;
QElemType a;
if(T) /* 非空樹 */
{
InitQueue(&q); /* 初始化隊列 */
EnQueue(&q,T); /* 根指針入隊 */
while(!QueueEmpty(q)) /* 隊不空 */
{
DeQueue(&q,&a); /* 出隊,隊列元素賦給a */
if(a->data==s)
return a;
if(a->lchild) /* 有左孩子 */
EnQueue(&q,a->lchild); /* 入隊左孩子 */
if(a->rchild) /* 有右孩子 */
EnQueue(&q,a->rchild); /* 入隊右孩子 */
}
}
return NULL;
}
TElemType LeftChild(BiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點。操作結果:返回e的左孩子。若e無左孩子,則返回"空" */
BiTree a;
if(T) /* 非空樹 */
{
a=Point(T,e); /* a是結點e的指針 */
if(a&&a->lchild) /* T中存在結點e且e存在左孩子 */
return a->lchild->data; /* 返回e的左孩子的值 */
}
return Nil; /* 其餘情況返回空 */
}
TElemType RightChild(BiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點。操作結果:返回e的右孩子。若e無右孩子,則返回"空" */
BiTree a;
if(T) /* 非空樹 */
{
a=Point(T,e); /* a是結點e的指針 */
if(a&&a->rchild) /* T中存在結點e且e存在右孩子 */
return a->rchild->data; /* 返回e的右孩子的值 */
}
return Nil; /* 其餘情況返回空 */
}
TElemType LeftSibling(BiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點 */
/* 操作結果:返回e的左兄弟。若e是T的左孩子或無左兄弟,則返回”空”*/
TElemType a;
BiTree p;
if(T) /* 非空樹 */
{
a=Parent(T,e); /* a為e的雙親 */
if(a!=Nil) /* 找到e的雙親 */
{
p=Point(T,a); /* p為指向結點a的指針 */
if(p->lchild&&p->rchild&&p->rchild->data==e) /* p存在左右孩子且右孩子是e */
return p->lchild->data; /* 返回p的左孩子(e的左兄弟) */
}
}
return Nil; /* 其餘情況返回空 */
}
TElemType RightSibling(BiTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點 */
/* 操作結果:返回e的右兄弟。若e是T的右孩子或無右兄弟,則返回”空”*/
TElemType a;
BiTree p;
if(T) /* 非空樹 */
{
a=Parent(T,e); /* a為e的雙親 */
if(a!=Nil) /* 找到e的雙親 */
{
p=Point(T,a); /* p為指向結點a的指針 */
if(p->lchild&&p->rchild&&p->lchild->data==e) /* p存在左右孩子且左孩子是e */
return p->rchild->data; /* 返回p的右孩子(e的右兄弟) */
}
}
return Nil; /* 其餘情況返回空 */
}
Status InsertChild(BiTree p,int LR,BiTree c) /* 形參T無用 */
{ /* 初始條件:二叉樹T存在,p指向T中某個結點,LR為0或1,非空二叉樹c與T不相交且右子樹為空 */
/* 操作結果:根據LR為0或1,插入c為T中p所指結點的左或右子樹。p所指結點的 */
/* 原有左或右子樹則成為c的右子樹 */
if(p) /* p不空 */
{
if(LR==0)
{
c->rchild=p->lchild;
p->lchild=c;
}
else /* LR==1 */
{
c->rchild=p->rchild;
p->rchild=c;
}
return OK;
}
return ERROR; /* p空 */
}
Status DeleteChild(BiTree p,int LR) /* 形參T無用 */
{ /* 初始條件:二叉樹T存在,p指向T中某個結點,LR為0或1 */
/* 操作結果:根據LR為0或1,刪除T中p所指結點的左或右子樹 */
if(p) /* p不空 */
{
if(LR==0) /* 刪除左子樹 */
ClearBiTree(&p->lchild);
else /* 刪除右子樹 */
ClearBiTree(&p->rchild);
return OK;
}
return ERROR; /* p空 */
}
typedef BiTree SElemType; /* 設棧元素為二叉樹的指針類型 */
#include"c3-1.h" /* 順序棧 */
#include"bo3-1.c" /* 順序棧的基本操作 */
void InOrderTraverse1(BiTree T,void(*Visit)(TElemType))
{ /* 採用二叉鏈表存儲結構,Visit是對數據元素操作的應用函數。算法6.3,有改動 */
/* 中序遍歷二叉樹T的非遞歸算法(利用棧),對每個數據元素調用函數Visit */
SqStack S;
InitStack(&S);
while(T||!StackEmpty(S))
{
if(T)
{ /* 根指針進棧,遍歷左子樹 */
Push(&S,T);
T=T->lchild;
}
else
{ /* 根指針退棧,訪問根結點,遍歷右子樹 */
Pop(&S,&T);
Visit(T->data);
T=T->rchild;
}
}
printf("\n");
}
void InOrderTraverse2(BiTree T,void(*Visit)(TElemType))
{ /* 採用二叉鏈表存儲結構,Visit是對數據元素操作的應用函數。算法6.2,有改動 */
/* 中序遍歷二叉樹T的非遞歸算法(利用棧),對每個數據元素調用函數Visit */
SqStack S;
BiTree p;
InitStack(&S);
Push(&S,T); /* 根指針進棧 */
while(!StackEmpty(S))
{
while(GetTop(S,&p)&&p)
Push(&S,p->lchild); /* 向左走到盡頭 */
Pop(&S,&p); /* 空指針退棧 */
if(!StackEmpty(S))
{ /* 訪問結點,向右一步 */
Pop(&S,&p);
Visit(p->data);
Push(&S,p->rchild);
}
}
printf("\n");
}
void PostOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ /* 初始條件:二叉樹T存在,Visit是對結點操作的應用函數 */
/* 操作結果:後序遞歸遍歷T,對每個結點調用函數Visit一次且僅一次 */
if(T) /* T不空 */
{
PostOrderTraverse(T->lchild,Visit); /* 先後序遍歷左子樹 */
PostOrderTraverse(T->rchild,Visit); /* 再後序遍歷右子樹 */
Visit(T->data); /* 最後訪問根結點 */
}
}
void LevelOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ /* 初始條件:二叉樹T存在,Visit是對結點操作的應用函數 */
/* 操作結果:層序遞歸遍歷T(利用隊列),對每個結點調用函數Visit一次且僅一次 */
LinkQueue q;
QElemType a;
if(T)
{
InitQueue(&q); /* 初始化隊列q */
EnQueue(&q,T); /* 根指針入隊 */
while(!QueueEmpty(q)) /* 隊列不空 */
{
DeQueue(&q,&a); /* 出隊元素(指針),賦給a */
Visit(a->data); /* 訪問a所指結點 */
if(a->lchild!=NULL) /* a有左孩子 */
EnQueue(&q,a->lchild); /* 入隊a的左孩子 */
if(a->rchild!=NULL) /* a有右孩子 */
EnQueue(&q,a->rchild); /* 入隊a的右孩子 */
}
printf("\n");
}
}
[編輯] 三叉鏈表存儲表示改進於二叉連結串列,增加父節點的指引,能更好地實作節點間的存取,不過演算法相對複雜。
[編輯] 存儲結構 /* 二叉樹的三叉鏈表存儲表示 */
typedef struct BiTPNode
{
TElemType data;
struct BiTPNode *parent,*lchild,*rchild; /* 雙親、左右孩子指針 */
}BiTPNode,*BiPTree;
[編輯] 基本操作顯示▼隱藏▲基於C/C++的實作演算法 /* 二叉樹的三叉鏈表存儲的基本操作(21個) */
#define ClearBiTree DestroyBiTree /* 清空二叉樹和銷毀二叉樹的操作一樣 */
void InitBiTree(BiPTree *T)
{ /* 操作結果:構造空二叉樹T */
*T=NULL;
}
void DestroyBiTree(BiPTree *T)
{ /* 初始條件:二叉樹T存在。操作結果:銷毀二叉樹T */
if(*T) /* 非空樹 */
{
if((*T)->lchild) /* 有左孩子 */
DestroyBiTree(&(*T)->lchild); /* 銷毀左孩子子樹 */
if((*T)->rchild) /* 有右孩子 */
DestroyBiTree(&(*T)->rchild); /* 銷毀右孩子子樹 */
free(*T); /* 釋放根結點 */
*T=NULL; /* 空指針賦0 */
}
}
void CreateBiTree(BiPTree *T)
{ /* 按先序次序輸入二叉樹中結點的值(可為字符型或整型,在主程中定義),*/
/* 構造三叉鏈表表示的二叉樹T */
TElemType ch;
scanf(form,&ch);
if(ch==Nil) /* 空 */
*T=NULL;
else
{
*T=(BiPTree)malloc(sizeof(BiTPNode)); /* 動態生成根結點 */
if(!*T)
exit(OVERFLOW);
(*T)->data=ch; /* 給根結點賦值 */
(*T)->parent=NULL; /* 根結點無雙親 */
CreateBiTree(&(*T)->lchild); /* 構造左子樹 */
if((*T)->lchild) /* 有左孩子 */
(*T)->lchild->parent=*T; /* 給左孩子的雙親域賦值 */
CreateBiTree(&(*T)->rchild); /* 構造右子樹 */
if((*T)->rchild) /* 有右孩子 */
(*T)->rchild->parent=*T; /* 給右孩子的雙親域賦值 */
}
}
Status BiTreeEmpty(BiPTree T)
{ /* 初始條件:二叉樹T存在。操作結果:若T為空二叉樹,則返回TRUE,否則FALSE */
if(T)
return FALSE;
else
return TRUE;
}
int BiTreeDepth(BiPTree T)
{ /* 初始條件:二叉樹T存在。操作結果:返回T的深度 */
int i,j;
if(!T)
return 0; /* 空樹深度為0 */
if(T->lchild)
i=BiTreeDepth(T->lchild); /* i為左子樹的深度 */
else
i=0;
if(T->rchild)
j=BiTreeDepth(T->rchild); /* j為右子樹的深度 */
else
j=0;
return i>j?i+1:j+1; /* T的深度為其左右子樹的深度中的大者+1 */
}
TElemType Root(BiPTree T)
{ /* 初始條件:二叉樹T存在。操作結果:返回T的根 */
if(T)
return T->data;
else
return Nil;
}
TElemType Value(BiPTree p)
{ /* 初始條件:二叉樹T存在,p指向T中某個結點。操作結果:返回p所指結點的值 */
return p->data;
}
void Assign(BiPTree p,TElemType value)
{ /* 給p所指結點賦值為value */
p->data=value;
}
typedef BiPTree QElemType; /* 設隊列元素為二叉樹的指針類型 */
#include"c3-2.h" /* 鏈隊列 */
#include"bo3-2.c" /* 鏈隊列的基本操作 */
BiPTree Point(BiPTree T,TElemType e)
{ /* 返回二叉樹T中指向元素值為e的結點的指針。加 */
LinkQueue q;
QElemType a;
if(T) /* 非空樹 */
{
InitQueue(&q); /* 初始化隊列 */
EnQueue(&q,T); /* 根結點入隊 */
while(!QueueEmpty(q)) /* 隊不空 */
{
DeQueue(&q,&a); /* 出隊,隊列元素賦給a */
if(a->data==e)
return a;
if(a->lchild) /* 有左孩子 */
EnQueue(&q,a->lchild); /* 入隊左孩子 */
if(a->rchild) /* 有右孩子 */
EnQueue(&q,a->rchild); /* 入隊右孩子 */
}
}
return NULL;
}
TElemType Parent(BiPTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點 */
/* 操作結果:若e是T的非根結點,則返回它的雙親,否則返回”空”*/
BiPTree a;
if(T) /* 非空樹 */
{
a=Point(T,e); /* a是結點e的指針 */
if(a&&a!=T) /* T中存在結點e且e是非根結點 */
return a->parent->data; /* 返回e的雙親的值 */
}
return Nil; /* 其餘情況返回空 */
}
TElemType LeftChild(BiPTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點。操作結果:返回e的左孩子。若e無左孩子,則返回"空" */
BiPTree a;
if(T) /* 非空樹 */
{
a=Point(T,e); /* a是結點e的指針 */
if(a&&a->lchild) /* T中存在結點e且e存在左孩子 */
return a->lchild->data; /* 返回e的左孩子的值 */
}
return Nil; /* 其餘情況返回空 */
}
TElemType RightChild(BiPTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點。操作結果:返回e的右孩子。若e無右孩子,則返回"空" */
BiPTree a;
if(T) /* 非空樹 */
{
a=Point(T,e); /* a是結點e的指針 */
if(a&&a->rchild) /* T中存在結點e且e存在右孩子 */
return a->rchild->data; /* 返回e的右孩子的值 */
}
return Nil; /* 其餘情況返回空 */
}
TElemType LeftSibling(BiPTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點 */
/* 操作結果:返回e的左兄弟。若e是T的左孩子或無左兄弟,則返回”空”*/
BiPTree a;
if(T) /* 非空樹 */
{
a=Point(T,e); /* a是結點e的指針 */
if(a&&a!=T&&a->parent->lchild&&a->parent->lchild!=a) /* T中存在結點e且e存在左兄弟 */
return a->parent->lchild->data; /* 返回e的左兄弟的值 */
}
return Nil; /* 其餘情況返回空 */
}
TElemType RightSibling(BiPTree T,TElemType e)
{ /* 初始條件:二叉樹T存在,e是T中某個結點 */
/* 操作結果:返回e的右兄弟。若e是T的右孩子或無右兄弟,則返回”空”*/
BiPTree a;
if(T) /* 非空樹 */
{
a=Point(T,e); /* a是結點e的指針 */
if(a&&a!=T&&a->parent->rchild&&a->parent->rchild!=a) /* T中存在結點e且e存在右兄弟 */
return a->parent->rchild->data; /* 返回e的右兄弟的值 */
}
return Nil; /* 其餘情況返回空 */
}
Status InsertChild(BiPTree p,int LR,BiPTree c) /* 形參T無用 */
{ /* 初始條件:二叉樹T存在,p指向T中某個結點,LR為0或1,非空二叉樹c與T不相交且右子樹為空 */
/* 操作結果:根據LR為0或1,插入c為T中p所指結點的左或右子樹。p所指結點 */
/* 的原有左或右子樹則成為c的右子樹 */
if(p) /* p不空 */
{
if(LR==0)
{
c->rchild=p->lchild;
if(c->rchild) /* c有右孩子(p原有左孩子) */
c->rchild->parent=c;
p->lchild=c;
c->parent=p;
}
else /* LR==1 */
{
c->rchild=p->rchild;
if(c->rchild) /* c有右孩子(p原有右孩子) */
c->rchild->parent=c;
p->rchild=c;
c->parent=p;
}
return OK;
}
return ERROR; /* p空 */
}
Status DeleteChild(BiPTree p,int LR) /* 形參T無用 */
{ /* 初始條件:二叉樹T存在,p指向T中某個結點,LR為0或1 */
/* 操作結果:根據LR為0或1,刪除T中p所指結點的左或右子樹 */
if(p) /* p不空 */
{
if(LR==0) /* 刪除左子樹 */
ClearBiTree(&p->lchild);
else /* 刪除右子樹 */
ClearBiTree(&p->rchild);
return OK;
}
return ERROR; /* p空 */
}
void PreOrderTraverse(BiPTree T,void(*Visit)(BiPTree))
{ /* 先序遞歸遍歷二叉樹T */
if(T)
{
Visit(T); /* 先訪問根結點 */
PreOrderTraverse(T->lchild,Visit); /* 再先序遍歷左子樹 */
PreOrderTraverse(T->rchild,Visit); /* 最後先序遍歷右子樹 */
}
}
void InOrderTraverse(BiPTree T,void(*Visit)(BiPTree))
{ /* 中序遞歸遍歷二叉樹T */
if(T)
{
InOrderTraverse(T->lchild,Visit); /* 中序遍歷左子樹 */
Visit(T); /* 再訪問根結點 */
InOrderTraverse(T->rchild,Visit); /* 最後中序遍歷右子樹 */
}
}
void PostOrderTraverse(BiPTree T,void(*Visit)(BiPTree))
{ /* 後序遞歸遍歷二叉樹T */
if(T)
{
PostOrderTraverse(T->lchild,Visit); /* 後序遍歷左子樹 */
PostOrderTraverse(T->rchild,Visit); /* 後序遍歷右子樹 */
Visit(T); /* 最後訪問根結點 */
}
}
void LevelOrderTraverse(BiPTree T,void(*Visit)(BiPTree))
{ /* 層序遍歷二叉樹T(利用隊列) */
LinkQueue q;
QElemType a;
if(T)
{
InitQueue(&q);
EnQueue(&q,T);
while(!QueueEmpty(q))
{
DeQueue(&q,&a);
Visit(a);
if(a->lchild!=NULL)
EnQueue(&q,a->lchild);
if(a->rchild!=NULL)
EnQueue(&q,a->rchild);
}
}
}
[編輯] 訪問二元樹的方法主條目:樹的遍歷
我們經常希望訪問樹中的每一個結點並且檢視它的值。有很多常見的順序來訪問所有的結點,而且每一種都有有用的性質。
[編輯] 前(先)序、中序、後序遍歷遍歷二元樹:L、D、R分別表示遍歷左子樹、訪問根結點和遍歷右子樹,則先(根)序遍歷二元樹的順序是DLR,中(根)序遍歷二元樹的順序是LDR,後(根)序遍歷二元樹的順序是LRD。還有按層遍歷二元樹。這些方法的時間複雜度都是O(n),n為結點個數。
如果T2是由有序樹T轉換而來的二元樹,那麼T中結點的前序就是T2中結點的前序,T中結點的後序就是T2中結點的中序。任何一棵二元樹的葉結點在先序、中序和後序遍歷中的相對次序不發改變。設n,m為一棵二元樹上的兩個結點,在中序遍歷時,n在m前的條件是n在m的左方。前序序列和中序序列相同的二元樹為空樹或任一結點均無左孩子的非空二元樹;中序序列和後序序列相同的二元樹為空樹或任一結點均無右孩子的非空二元樹;前序序列和後序序列相同的二元樹為空樹或僅有一個結點的二元樹。
假設我們有一個包含值的value和指向兩個子結點的left和right的樹結點結構。我們可以寫出這樣的過程:
visit(node)
print node.value
if node.left != null then visit(node.left)
if node.right != null then visit(node.right)
這樣會用中序列印出樹中的值。在中序,每個結點在訪問它的子結點之前訪問。類似地,如果列印語句在最後,每個結點在訪問他的子節點之後訪問,樹中的值會用後序來列印。在這兩種情況中,左子樹中的值比右子樹中得值先列印。
visit(node)
if node.left != null then visit(node.left)
print node.value
if node.right != null then visit(node.right)
最後,上面的中序遍歷,每個結點在訪問左子樹和右子樹之間訪問。這在遍歷二叉搜尋樹時很常用,因為它能用遞增的順序來遍歷所有的值。
為什麼呢?如果n是二叉搜尋樹的結點,那麼n的左子樹的所有結點的值都比n的值要小,而且n的右子樹的所有節點的值都比n的值要大。因此,如果我們順序遍歷左子樹,然後訪問n,然後順序遍歷右子樹。我們就已經順序訪問了整個樹。
在這個二元樹中,
前序遍歷的結果:2, 7, 2, 6, 5, 11, 5, 9, 4
後序遍歷的結果:2, 5, 11, 6, 7, 4, 9, 5, 2
中序遍歷的結果:2, 7, 5, 6, 11, 2, 5, 4, 9
以上的遞歸演算法使用與樹的高度成比例的棧空間。如果我們在每個結點中存儲指向父結點的指針,那樣可以使用迭代演算法,只使用常數空間實現所有這些遍歷。然而,指向父結點的指針佔用更多的空間。這只在需要指向父節點的指針或棧空間有限時才使用。例如, 這是一個中序遍歷的迭代演算法:
visit(root)
prev := null
current := root
next := null
while current != null
if prev == current.parent
prev := current
next := current.left
if next == null or prev == current.left
print current.value
prev := current
next := current.right
if next == null or prev == current.right
prev := current
next := current.parent
current := next
用二元樹表示下述表達式:a+b*(c-d)-e/f
先序遍歷的序列是:-+a*b-cd/ef
中序遍歷的序列是:a+b*c-d-e/f
後序遍歷的序列是:abcd-*+ef/-
[編輯] 深度優先遍歷在深度優先順序中,我們希望從根結點訪問最遠的結點。和圖的深度優先搜尋不同的是,不需記住訪問過的每一個結點,因為樹中不會有環。前序,中序和後序遍歷都是深度優先遍歷的特例。參見深度優先搜尋。
[編輯] 廣度優先遍歷和深度優先遍歷不同,廣度優先遍歷會先訪問離根節點最近的節點。參見廣度優先搜尋。 二元樹的廣度優先遍歷又稱按層次遍歷。演算法藉助隊列實現。
[編輯] 將n叉樹轉換為二元樹一般有序樹和二元樹之間有一一對映關係,能進行相互轉換。
n叉樹轉換為二元樹的方法:二元樹中結點x的左子結點為n叉樹中結點x的左子結點;二元樹中結點x的右子結點為n叉樹中結點x的第一個右邊的同級結點y。
例如,在左邊的樹中,A有6個子結點{B,C,D,E,F,G}。它能被轉換成右邊的二元樹。
將一棵樹轉換為二元樹的方法:
1.在兄弟之間加一連線;
2.對每個結點,除了其左孩子外,去除其與其餘孩子之間的聯繫;
3.以樹的根結點為軸心,將整樹順時針轉45度。
[編輯] 存儲結構與基本操作樹的二叉鏈表表示法(孩子兄弟表示法)是樹和二元樹轉換的媒介。
[編輯] 樹的二叉鏈表存儲表示 /* 樹的二叉鏈表(孩子—兄弟)存儲表示 */
typedef struct CSNode
{
TElemType data;
struct CSNode *firstchild,*nextsibling;
}CSNode,*CSTree;
[編輯] 樹的二叉鏈表存儲的基本操作顯示▼隱藏▲基於C/C++的演算法實作 /* 樹的二叉鏈表(孩子—兄弟)存儲的基本操作(17個) */
#define ClearTree DestroyTree /* 二者操作相同 */
#include"func6-2.c" /* 包括PreOrderTraverse() */
void InitTree(CSTree *T)
{ /* 操作結果:構造空樹T */
*T=NULL;
}
void DestroyTree(CSTree *T)
{ /* 初始條件:樹T存在。操作結果:銷毀樹T */
if(*T)
{
if((*T)->firstchild) /* T有長子 */
DestroyTree(&(*T)->firstchild); /* 銷毀T的長子為根結點的子樹 */
if((*T)->nextsibling) /* T有下一個兄弟 */
DestroyTree(&(*T)->nextsibling); /* 銷毀T的下一個兄弟為根結點的子樹 */
free(*T); /* 釋放根結點 */
*T=NULL;
}
}
typedef CSTree QElemType; /* 定義隊列元素類型 */
#include"c3-2.h" /* 定義LinkQueue類型(鏈隊列) */
#include"bo3-2.c" /* LinkQueue類型的基本操作 */
void CreateTree(CSTree *T)
{ /* 構造樹T */
char c[20]; /* 臨時存放孩子結點(設不超過20個)的值 */
CSTree p,p1;
LinkQueue q;
int i,l;
InitQueue(&q);
printf("請輸入根結點(字符型,空格為空): ");
scanf("%c%*c",&c[0]);
if(c[0]!=Nil) /* 非空樹 */
{
*T=(CSTree)malloc(sizeof(CSNode)); /* 建立根結點 */
(*T)->data=c[0];
(*T)->nextsibling=NULL;
EnQueue(&q,*T); /* 入隊根結點的指針 */
while(!QueueEmpty(q)) /* 隊不空 */
{
DeQueue(&q,&p); /* 出隊一個結點的指針 */
printf("請按長幼順序輸入結點%c的所有孩子: ",p->data);
gets(c);
l=strlen(c);
if(l>0) /* 有孩子 */
{
p1=p->firstchild=(CSTree)malloc(sizeof(CSNode)); /* 建立長子結點 */
p1->data=c[0];
for(i=1;i<l;i++)
{
p1->nextsibling=(CSTree)malloc(sizeof(CSNode)); /* 建立下一個兄弟結點 */
EnQueue(&q,p1); /* 入隊上一個結點 */
p1=p1->nextsibling;
p1->data=c[i];
}
p1->nextsibling=NULL;
EnQueue(&q,p1); /* 入隊最後一個結點 */
}
else
p->firstchild=NULL; /* 長子指針為空 */
}
}
else
*T=NULL; /* 空樹 */
}
Status TreeEmpty(CSTree T)
{ /* 初始條件:樹T存在。操作結果:若T為空樹,則返回TURE,否則返回FALSE */
if(T) /* T不空 */
return FALSE;
else
return TRUE;
}
int TreeDepth(CSTree T)
{ /* 初始條件:樹T存在。操作結果:返回T的深度 */
CSTree p;
int depth,max=0;
if(!T) /* 樹空 */
return 0;
if(!T->firstchild) /* 樹無長子 */
return 1;
for(p=T->firstchild;p;p=p->nextsibling)
{ /* 求子樹深度的最大值 */
depth=TreeDepth(p);
if(depth>max)
max=depth;
}
return max+1; /* 樹的深度=子樹深度最大值+1 */
}
TElemType Value(CSTree p)
{ /* 返回p所指結點的值 */
return p->data;
}
TElemType Root(CSTree T)
{ /* 初始條件:樹T存在。操作結果:返回T的根 */
if(T)
return Value(T);
else
return Nil;
}
CSTree Point(CSTree T,TElemType s)
{ /* 返回二叉鏈表(孩子—兄弟)樹T中指向元素值為s的結點的指針。另加 */
LinkQueue q;
QElemType a;
if(T) /* 非空樹 */
{
InitQueue(&q); /* 初始化隊列 */
EnQueue(&q,T); /* 根結點入隊 */
while(!QueueEmpty(q)) /* 隊不空 */
{
DeQueue(&q,&a); /* 出隊,隊列元素賦給a */
if(a->data==s)
return a;
if(a->firstchild) /* 有長子 */
EnQueue(&q,a->firstchild); /* 入隊長子 */
if(a->nextsibling) /* 有下一個兄弟 */
EnQueue(&q,a->nextsibling); /* 入隊下一個兄弟 */
}
}
return NULL;
}
Status Assign(CSTree *T,TElemType cur_e,TElemType value)
{ /* 初始條件:樹T存在,cur_e是樹T中結點的值。操作結果:改cur_e為value */
CSTree p;
if(*T) /* 非空樹 */
{
p=Point(*T,cur_e); /* p為cur_e的指針 */
if(p) /* 找到cur_e */
{
p->data=value; /* 賦新值 */
return OK;
}
}
return ERROR; /* 樹空或沒找到 */
}
TElemType Parent(CSTree T,TElemType cur_e)
{ /* 初始條件:樹T存在,cur_e是T中某個結點 */
/* 操作結果:若cur_e是T的非根結點,則返回它的雙親,否則函數值為”空”*/
CSTree p,t;
LinkQueue q;
InitQueue(&q);
if(T) /* 樹非空 */
{
if(Value(T)==cur_e) /* 根結點值為cur_e */
return Nil;
EnQueue(&q,T); /* 根結點入隊 */
while(!QueueEmpty(q))
{
DeQueue(&q,&p);
if(p->firstchild) /* p有長子 */
{
if(p->firstchild->data==cur_e) /* 長子為cur_e */
return Value(p); /* 返回雙親 */
t=p; /* 雙親指針賦給t */
p=p->firstchild; /* p指向長子 */
EnQueue(&q,p); /* 入隊長子 */
while(p->nextsibling) /* 有下一個兄弟 */
{
p=p->nextsibling; /* p指向下一個兄弟 */
if(Value(p)==cur_e) /* 下一個兄弟為cur_e */
return Value(t); /* 返回雙親 */
EnQueue(&q,p); /* 入隊下一個兄弟 */
}
}
}
}
return Nil; /* 樹空或沒找到cur_e */
}
TElemType LeftChild(CSTree T,TElemType cur_e)
{ /* 初始條件:樹T存在,cur_e是T中某個結點 */
/* 操作結果:若cur_e是T的非葉子結點,則返回它的最左孩子,否則返回”空”*/
CSTree f;
f=Point(T,cur_e); /* f指向結點cur_e */
if(f&&f->firstchild) /* 找到結點cur_e且結點cur_e有長子 */
return f->firstchild->data;
else
return Nil;
}
TElemType RightSibling(CSTree T,TElemType cur_e)
{ /* 初始條件:樹T存在,cur_e是T中某個結點 */
/* 操作結果:若cur_e有右兄弟,則返回它的右兄弟,否則返回”空”*/
CSTree f;
f=Point(T,cur_e); /* f指向結點cur_e */
if(f&&f->nextsibling) /* 找到結點cur_e且結點cur_e有右兄弟 */
return f->nextsibling->data;
else
return Nil; /* 樹空 */
}
Status InsertChild(CSTree *T,CSTree p,int i,CSTree c)
{ /* 初始條件:樹T存在,p指向T中某個結點,1≦i≦p所指結點的度+1,非空樹c與T不相交 */
/* 操作結果:插入c為T中p結點的第i棵子樹 */
/* 因為p所指結點的地址不會改變,故p不需是引用類型 */
int j;
if(*T) /* T不空 */
{
if(i==1) /* 插入c為p的長子 */
{
c->nextsibling=p->firstchild; /* p的原長子現是c的下一個兄弟(c本無兄弟) */
p->firstchild=c;
}
else /* 找插入點 */
{
p=p->firstchild; /* 指向p的長子 */
j=2;
while(p&&i>j)
{
p=p->nextsibling;
j++;
}
if(j==i) /* 找到插入位置 */
{
c->nextsibling=p->nextsibling;
p->nextsibling=c;
}
else /* p原有孩子數小於i-1 */
return ERROR;
}
return OK;
}
else /* T空 */
return ERROR;
}
Status DeleteChild(CSTree *T,CSTree p,int i)
{ /* 初始條件:樹T存在,p指向T中某個結點,1≦i≦p所指結點的度 */
/* 操作結果:刪除T中p所指結點的第i棵子樹 */
/* 因為p所指結點的地址不會改變,故p不需是引用類型 */
CSTree b;
int j;
if(*T) /* T不空 */
{
if(i==1) /* 刪除長子 */
{
b=p->firstchild;
p->firstchild=b->nextsibling; /* p的原次子現是長子 */
b->nextsibling=NULL;
DestroyTree(&b);
}
else /* 刪除非長子 */
{
p=p->firstchild; /* p指向長子 */
j=2;
while(p&&i>j)
{
p=p->nextsibling;
j++;
}
if(j==i) /* 找到第i棵子樹 */
{
b=p->nextsibling;
p->nextsibling=b->nextsibling;
b->nextsibling=NULL;
DestroyTree(&b);
}
else /* p原有孩子數小於i */
return ERROR;
}
return OK;
}
else
return ERROR;
}
void PostOrderTraverse(CSTree T,void(*Visit)(TElemType))
{ /* 後根遍歷孩子—兄弟二叉鏈表結構的樹T */
CSTree p;
if(T)
{
if(T->firstchild) /* 有長子 */
{
PostOrderTraverse(T->firstchild,Visit); /* 後根遍歷長子子樹 */
p=T->firstchild->nextsibling; /* p指向長子的下一個兄弟 */
while(p)
{
PostOrderTraverse(p,Visit); /* 後根遍歷下一個兄弟子樹 */
p=p->nextsibling; /* p指向再下一個兄弟 */
}
}
Visit(Value(T)); /* 最後訪問根結點 */
}
}
void LevelOrderTraverse(CSTree T,void(*Visit)(TElemType))
{ /* 層序遍歷孩子—兄弟二叉鏈表結構的樹T */
CSTree p;
LinkQueue q;
InitQueue(&q);
if(T)
{
Visit(Value(T)); /* 先訪問根結點 */
EnQueue(&q,T); /* 入隊根結點的指針 */
while(!QueueEmpty(q)) /* 隊不空 */
{
DeQueue(&q,&p); /* 出隊一個結點的指針 */
if(p->firstchild) /* 有長子 */
{
p=p->firstchild;
Visit(Value(p)); /* 訪問長子結點 */
EnQueue(&q,p); /* 入隊長子結點的指針 */
while(p->nextsibling) /* 有下一個兄弟 */
{
p=p->nextsibling;
Visit(Value(p)); /* 訪問下一個兄弟 */
EnQueue(&q,p); /* 入隊兄弟結點的指針 */
}
}
}
}
}
[編輯] 線索二元樹 (threaded binary
tree)線索二元樹(保留遍歷時結點在任一序列的前驅和後繼的訊息):若結點有左子樹,則其lchild域指示其左孩子,否則令lchild域指示其前驅;若結點有右子樹,則其rchild域指示其右孩子,否則令rchild指示其後繼。還需在結點結構中增加兩個標誌域LTag和RTag。LTag=0時,lchild域指示結點的左孩子,LTag=1時,lchild域指示結點的前驅;RTag=0時,rchild域指示結點的右孩子,RTag=1時,rchild域指示結點的後繼。以這種結點結構構成的二叉鏈表作為二元樹的存儲結構,叫做線索鏈表,其中指向結點前驅和後繼的指針叫做線索,加上線索的二元樹稱為線索二元樹ꄊC對二元樹以某種次序遍歷使其變為線索二元樹的過程叫做線索化。若對二元樹進行中序遍歷,則所得的線索二元樹稱為中序線索二元樹,線索鏈表稱為為中序線索鏈表。線索二元樹是一種物理結構。
在中序線索樹找結點後繼的規律是:若其右標誌為1,則右鏈為線索,指示其後繼,否則遍歷其右子樹時訪問的第一個結點(右子樹最左下的結點)為其後繼;找結點前驅的規律是:若其左標誌為1,則左鏈為線索,指示其前驅,否則遍歷左子樹時最後訪問的一個結點(左子樹中最右下的結點)為其前驅。
在後序線索樹中找到結點的後繼分三種情況:
1.若結點是二元樹的根,則其後繼為空;
2.若結點是其雙親的右孩子,或是其雙親的左孩子且其雙親沒有右子樹,則其後繼即為雙親結點;
3.若結點是其雙親的左孩子,且其雙親有右子樹,則其後繼為雙親右子樹上按後序遍歷列出的第一個結點。
[編輯] 二叉線索存儲表示[編輯] 存儲結構二元樹的二叉線索存儲表示:在線索鏈表上添加一個頭結點,並令其lchild域的指針指向二元樹的根結點,其rchild域的指針指向中序遍歷時訪問的最後一個結點。令二元樹中序序列中的第一個結點的lchild域指針和最後一個結點的rchild域的指針均指向頭結點,這樣就建立了一個雙向線索鏈表
/* 二叉樹的二叉線索存儲表示 */
typedef enum{Link,Thread}PointerTag; /* Link(0):指針,Thread(1):線索 */
typedef struct BiThrNode
{
TElemType data;
struct BiThrNode *lchild,*rchild; /* 左右孩子指針 */
PointerTag LTag,RTag; /* 左右標誌 */
}BiThrNode,*BiThrTree;
[編輯] 基本操作顯示▼隱藏▲基於C/C++的演算法實作 /* 二叉樹的二叉線索存儲的基本操作 */
void CreateBiThrTree(BiThrTree *T)
{ /* 按先序輸入線索二叉樹中結點的值,構造線索二叉樹T。0(整型)/空格(字符型)表示空結點 */
TElemType ch;
scanf(form,&ch);
if(ch==Nil)
*T=NULL;
else
{
*T=(BiThrTree)malloc(sizeof(BiThrNode)); /* 生成根結點(先序) */
if(!*T)
exit(OVERFLOW);
(*T)->data=ch; /* 給根結點賦植 */
CreateBiThrTree(&(*T)->lchild); /* 遞歸構造左子樹 */
if((*T)->lchild) /* 有左孩子 */
(*T)->LTag=Link; /* 給左標誌賦值(指針) */
CreateBiThrTree(&(*T)->rchild); /* 遞歸構造右子樹 */
if((*T)->rchild) /* 有右孩子 */
(*T)->RTag=Link; /* 給右標誌賦值(指針) */
}
}
BiThrTree pre; /* 全局變量,始終指向剛剛訪問過的結點 */
void InThreading(BiThrTree p)
{ /* 通過中序遍歷進行中序線索化,線索化之後pre指向最後一個結點。算法6.7 */
if(p) /* 線索二叉樹不空 */
{
InThreading(p->lchild); /* 遞歸左子樹線索化 */
if(!p->lchild) /* 沒有左孩子 */
{
p->LTag=Thread; /* 左標誌為線索(前驅) */
p->lchild=pre; /* 左孩子指針指向前驅 */
}
d;
Visit(p->data); /* 訪問此結點 */
while(p->RTag==Thread&&p->rchild!=T) /* p->rchild是線索(後繼),且不是遍歷的最後一個結點 */
{
p=p->rchild;
Visit(p->data); /* 訪問後繼結點 */
}
p=p->rchild; /* 若p->rchild不是線索(是右孩子),p指向右孩子,返回循環,*/
} /* 找這棵子樹中序遍歷的第1個結點 */
}
void PreThreading(BiThrTree p)
{ /* PreOrderThreading()調用的遞歸函數 */
if(!pre->rchild) /* p的前驅沒有右孩子 */
{
pre->rchild=p; /* p前驅的後繼指向p */
pre->RTag=Thread; /* pre的右孩子為線索 */
}
if(!p->lchild) /* p沒有左孩子 */
{
p->LTag=Thread; /* p的左孩子為線索 */
p->lchild=pre; /* p的左孩子指向前驅 */
}
pre=p; /* 移動前驅 */
if(p->LTag==Link) /* p有左孩子 */
PreThreading(p->lchild); /* 對p的左孩子遞歸調用preThreading() */
if(p->RTag==Link) /* p有右孩子 */
PreThreading(p->rchild); /* 對p的右孩子遞歸調用preThreading() */
}
void PreOrderThreading(BiThrTree *Thrt,BiThrTree T)
{ /* 先序線索化二叉樹T,頭結點的右指針指向先序遍歷的最後1個結點 */
*Thrt=(BiThrTree)malloc(sizeof(BiThrNode));
if(!*Thrt) /* 生成頭結點 */
exit(OVERFLOW);
(*Thrt)->LTag=Link; /* 頭結點的左指針為孩子 */
(*Thrt)->RTag=Thread; /* 頭結點的右指針為線索 */
(*Thrt)->rchild=*Thrt; /* 頭結點的右指針指向自身 */
if(!T) /* 空樹 */
(*Thrt)->lchild=*Thrt; /* 頭結點的左指針也指向自身 */
else
{ /* 非空樹 */
(*Thrt)->lchild=T; /* 頭結點的左指針指向根結點 */
pre=*Thrt; /* 前驅為頭結點 */
PreThreading(T); /* 從頭結點開始先序遞歸線索化 */
pre->rchild=*Thrt; /* 最後一個結點的後繼指向頭結點 */
pre->RTag=Thread;
(*Thrt)->rchild=pre; /* 頭結點的後繼指向最後一個結點 */
}
}
void PreOrderTraverse_Thr(BiThrTree T,void(*Visit)(TElemType))
{ /* 先序遍歷線索二叉樹T(頭結點)的非遞歸算法 */
BiThrTree p=T->lchild; /* p指向根結點 */
while(p!=T) /* p沒指向頭結點(遍歷的最後1個結點的後繼指向頭結點) */
{
Visit(p->data); /* 訪問根結點 */
if(p->LTag==Link) /* p有左孩子 */
p=p->lchild; /* p指向左孩子(後繼) */
else /* p無左孩子 */
p=p->rchild; /* p指向右孩子或後繼 */
}
}
void PostThreading(BiThrTree p)
{ /* PostOrderThreading()調用的遞歸函數 */
if(p) /* p不空 */
{
PostThreading(p->lchild); /* 對p的左孩子遞歸調用PostThreading() */
PostThreading(p->rchild); /* 對p的右孩子遞歸調用PostThreading() */
if(!p->lchild) /* p沒有左孩子 */
{
p->LTag=Thread; /* p的左孩子為線索 */
p->lchild=pre; /* p的左孩子指向前驅 */
}
if(!pre->rchild) /* p的前驅沒有右孩子 */
{
pre->RTag=Thread; /* p前驅的右孩子為線索 */
pre->rchild=p; /* p前驅的後繼指向p */
}
pre=p; /* 移動前驅 */
}
}
void PostOrderThreading(BiThrTree *Thrt,BiThrTree T)
{ /* 後序遞歸線索化二叉樹 */
*Thrt=(BiThrTree)malloc(sizeof(BiThrNode));
if(!*Thrt) /* 生成頭結點 */
exit(OVERFLOW);
(*Thrt)->LTag=Link; /* 頭結點的左指針為孩子 */
(*Thrt)->RTag=Thread; /* 頭結點的右指針為線索 */
if(!T) /* 空樹 */
(*Thrt)->lchild=(*Thrt)->rchild=*Thrt; /* 頭結點的左右指針指向自身 */
else
{ /* 非空樹 */
(*Thrt)->lchild=(*Thrt)->rchild=T; /* 頭結點的左右指針指向根結點(最後一個結點) */
pre=*Thrt; /* 前驅為頭結點 */
PostThreading(T); /* 從頭結點開始後序遞歸線索化 */
if(pre->RTag!=Link) /* 最後一個結點沒有右孩子 */
{
pre->rchild=*Thrt; /* 最後一個結點的後繼指向頭結點 */
pre->RTag=Thread;
}
}
}
void DestroyBiTree(BiThrTree *T)
{ /* DestroyBiThrTree調用的遞歸函數,T指向根結點 */
if(*T) /* 非空樹 */
{
if((*T)->LTag==0) /* 有左孩子 */
DestroyBiTree(&(*T)->lchild); /* 銷毀左孩子子樹 */
if((*T)->RTag==0) /* 有右孩子 */
DestroyBiTree(&(*T)->rchild); /* 銷毀右孩子子樹 */
free(*T); /* 釋放根結點 */
T=NULL; /* 空指針賦0 */
}
}
void DestroyBiThrTree(BiThrTree *Thrt)
{ /* 初始條件:線索二叉樹Thrt存在。操作結果:銷毀線索二叉樹Thrt */
if(*Thrt) /* 頭結點存在 */
{
if((*Thrt)->lchild) /* 根結點存在 */
DestroyBiTree(&(*Thrt)->lchild); /* 遞歸銷毀頭結點lchild所指二叉樹 */
free(*Thrt); /* 釋放頭結點 */
*Thrt=NULL; /* 線索二叉樹Thrt指針賦0 */
}
}
顯示▼隱藏▲檢 論 編電腦科學中的樹
二元樹 二元樹 二元搜尋樹 (BST) 笛卡爾樹 Top tree T樹
自平衡二元搜尋樹 AA樹 AVL樹 紅黑樹 伸展樹 樹堆 節點大小平衡樹
B樹 B樹 B+樹 B*樹 Bx樹 UB樹 2-3樹 2-3-4樹 (a,b)-樹 Dancing tree H樹
Trie 字尾樹 基數樹
空間劃分樹 四叉樹 八叉樹 k-d樹 vp-樹 R樹 R*樹 R+樹 X樹 M樹 線段樹 希爾伯特R樹 優先R樹
非二元樹 Exponential tree Fusion tree 區間樹 PQ tree Range tree SPQR tree Van Emde Boas tree
其他型別 堆 雜湊樹 Finger tree Metric tree Cover tree BK-tree Doubly-chained tree iDistance Link-cut tree 樹狀陣列
取自「https://zh.wikipedia.org/w/index.php?title=二叉?&oldid=24229733」
查看本頁評分給本文評分
給本文評分
本頁評分
這是什麼?目前平均評分
可信度
客觀性
完整性
可讀性
我非常了解與本主題相關的知識(可選)
我有與其有關學院/大學學位這是我專業的一部分個人對此有深厚的興趣此處未列出我的知識的來源 我想幫助改善維基百科,請給我發送一封電子郵件(可選) 我們將向您發送確認電子郵件。基於反饋隱私政策,我們不會與任何人分享您的地址。提交評分
保存成功你的評分尚未提交你的評分已過期請重新評估本頁並重新評分。
發生了錯誤。請稍後再試。
謝謝!您的評分已保存。你想要創建帳戶嗎?帳戶將幫助您跟蹤您所做的編輯,參與討論,並成為社區的一部分。創建帳戶或者登入以後再說
謝謝!您的評分已保存。您知道您可以編輯此頁嗎?編輯本頁以後再說 3個分類:資料結構樹結構圖論1個隱藏分類:自2007年10月缺少來源的條目
--
plurk
https://www.plurk.com/dasea2010
face book
https://www.facebook.com/dasea.chien
google+
https://plus.google.com/u/0/
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.130.189.48
... <看更多>