ticoAg/ChineseCorpus-Kaggle-fanti huggingface dataset:
《清明上河圖》的作者是宋徽宗朝任朝翰林畫院畫史張擇端，也有一說作者不止張擇端一人；董其昌《容臺集》說：「乃南宋人追憶故京之盛，而寓清明節繁盛之景，傳世者不一，以張擇端所作為佳。」「紹興初，故老閒坐，必談京師風物，聽之感慨有流涕者，故其時西北耆舊，談宣政故事者，為人所重。」甚至有人提出觀點說是南宋人懷念昔日強盛時期而作。宋徽宗酷愛此畫，用“瘦金體”在圖上題寫“清明上河圖”五字。
《清明上河圖》歷十年畫成，最早由北宋宮廷收藏，后為宋神宗向皇后族人所藏。靖康之禍後流入金國。1186年，金朝張著、張公藥、酈權、王磵、張世積等人先後得此畫，識畫睹畫思故國，分別題跋于圖後。後歷經輾轉，為南宋賈似道所得。元朝時期再度進宮，被收入秘府。爲官匠裝池者以贗本偷換出宮。售予某貴官，中途又爲保管人偷售給杭州陳彥廉。至正年間又被調包，流落民間。
明朝初期，由大理寺卿朱文徽、大學士徐溥收藏。1451年，李東陽在圖後兩次題寫長跋，詳記畫面內容和在明代中朝流傳始末；弘治以後，固歸華蓋殿大學土徐溥所有。徐溥臨終前贈予李東陽，嘉靖三年（1524年）圖歸兵部尚書陸完，陸完死後，其夫人將《清明上河圖》縫入枕中，後被娘家外甥王某曾臨摩此畫。陸完之子將《清明上河圖》賣至昆山顧鼎臣家。後來落到宰相嚴嵩、嚴世蕃父子手上，明人田藝蘅《留青日札》載嚴嵩為得《清明上河圖》，以1,200百金從蘇州陸氏處購得，“饞得其贗本，卒破數十家”。嚴嵩倒臺，圖被沒收，第三次納入宮廷。經明代皇室收藏，後來太監馮保偷出，在畫上加了題跋，之後真本又不知去向。
清朝時由陸費墀保存，在上面矜印題跋。後由湖廣總督畢沅收藏。嘉慶二年（1797年）畢沅死後，《清明上河圖》第四次進宮，深藏紫禁城迎春閣內，嘉慶帝命人將其收錄於《石渠寶笈·三編》一書之中，此後《清明上河圖》一直在清宮珍藏；雖經歷1860年英法聯軍入侵和1900年八國聯軍入侵北京二難，但均未受損。
1924年曾被溥儀和兩幅仿作一起帶至東北，但溥儀也不知何者為真品。1932年，溥儀在日本人扶植下，建立滿洲國，于是這幅名畫又被帶到長春，存在皇宮東院圖書樓中。1945年被收入東北博物館（今遼寧省博物館）當成贗品處理，直至1950年冬天才由楊仁愷等人從庫房的贗品堆裡鑑定出真跡，後藏于北京故宮。文化大革命中，李作鵬曾利用權勢將《清明上河圖》強行從北京故宮“借”出，據爲己有。林彪倒臺後，《清明上河圖》才又重見天日，如今依舊收藏於北京故宮。
張擇端的《清明上河圖》以清明時節作為引子，展開對汴京的精描細繪，是寫實風俗畫的杰作，受到歷代畫家的喜愛因而有許多仿本出現。其中“明四家”之一仇英仿作的《清明上河圖》最有影響，蘇州一帶仿間大都以“仇本”為底本。明朝后期，大量蘇州仿制的《清明上河圖》散落民間，后來紛紛進入清內府，一時間魚龍莫辯，清宮不得不組織畫工，另起爐灶再畫了一張「加長版」《清明上河圖》，是為歷代版本中內容最為富麗的一幅，幅度也較張本及仇本長，今人稱為“清院本”。
《清明上河圖》是一幅舉世聞名的現實主義風俗畫卷。千余年來，此畫聲名顯赫，廣受青睞，仿摹者眾多。各地公私藏家手中還有許多摹本和僞造本。資料載僅清代皇宮所藏的摹本就有12幅。有統計指出現存《清明上河圖》有30多本；包括中國大陸藏10余幅，臺灣藏9幅，美國藏5幅，法國藏4幅，英國和日本各藏一幅，其中臺灣光是臺北國立故宮博物院就藏有8幅。至于流傳到社會上還有多少幅，沒有人能弄清楚。
清院本《清明上河圖》是由清宮畫院的五位畫家——陳枚、孫祜、金昆、戴洪、程志道在乾隆元年（公元1736年）協作畫成，是參照了各朝仿本、集各家所長的作品。同時增加了明清時代的特殊風俗，如踏青、表演等等娛樂活動，亦增添了許多豐富的情節，如戲劇、猴戲、特技、擂臺等等，使畫中人物增加到超過4,000人，畫作尺寸擴大至長1152.8公分及寬35.6公分；而且受到西洋畫風的影響，街道房舍均以透視原理作畫，并有西式建筑行置其中。此卷用色鮮麗明亮，用筆達圓熟細致，所畫之橋梁、屋宇、人物皆細膩嚴謹，是院畫中的精品之作。現藏於臺北國立故宮博物院。
此版本為明代著名畫家仇英，根據「清明上河」這一題材，參照「張本」的構圖結構，以明代蘇州城爲背景，采用青綠重設色方式，重新創作了一幅全新畫卷，其風格與宋本迥異。仇本高約30.5公分，長約987公分。「仇本」又稱「明本」、「仇英本」，是後世衆仿作鼻祖，明人筆記載當時各種以此為藍本的仿本層出不窮，一時間成爲達官豪門相互饋贈的高檔禮物，被稱爲仇英仿本。現藏於遼寧省博物館。
*2009年卡通電影麥兜響噹噹出現了兩分多鐘的3D立體動畫片段
*2010年上海世博及香港亞洲國際博覽館電子動態版《清明上河圖》
清明上河圖的畫軸大致分成左、右兩部份，右半部分大體描述鄉間的從容步調，主要構成為農戶、牧羊人、豬舍等；從一條鄉間小徑逐漸拓寬、並連接到市鎮中的馬路。畫面左半部分則描繪都市日常，具體刻畫北宋繁榮的市場經濟運作，例如碼頭、商家、官府等，以及各行各業的生活百態，包含推車小販、雜技、戲班、乞丐、僧侶、占卜師、醫者、客棧、私塾、磨坊、鐵匠、木匠、石匠、儒生等，細節之講究為後世研究宋代社會構成影響甚鉅。貫穿全卷的的汴河為當時南北交通樞紐，對汴京具有極大重要性，在陸路交通不發達的年代，城中的物資供給全靠汴河供應。畫中隨處可見穿梭的船舶，搬運貨物的苦力，彰顯汴河對於宋代不可取代的地位。
畫面左端經過望火樓後，各式各樣的商業活動包含酒家、穀物市集、二手貨店、廚具舖、武器舖、燈籠店、樂器行、銀樓、布莊、畫廊、藥房、飯館等應有盡有。
畫面中的虹橋為全畫的中心。經現代學者考究，虹橋右側一艘帆船由於來不及收起桅桿，即將撞上橋面，因此可以看見橋上人群觀望與船上水手手忙腳亂的畫面，也看得出畫家特別著重此景刻畫。
繁忙的河道，造就汴河兩岸蓬勃的工商百業。汴京城的街道商店林立，有邸店（旅館）、醫藥舖、各式攤販等。宋代的人喜愛飲酒，因此汴京城內酒肆林立，資本雄厚的大酒商開設的酒店，稱為「正店」，中、小型的酒店，則稱為「腳店」，還有一些賣下價酒的「小店」，酒業可算是汴京的一大行業。由於酒客眾多，因此亦吸引了許多小販在店前擺賣。除了商店和小吃攤以外，畫面中還包含許多寺廟、私人住宅、官邸等各種階級和型態的房舍，有些還有前院和後院。畫面中的人們用各種不同型式的交通工具，有馬車、驢車、轎子等。河川中央滿是漁船和客串，河邊則有工人正拉著大船使其靠岸固定。當中婦女形象不多，大戶人家的婦女上街都得坐轎，酒樓、茶肆更不是婦女人家流連之地，由此可見宋代社會對婦女「拋頭露面」的限制。新娘嫁娶內容平易近人，反應當時生活樣態。
總之，有關《清明上河圖》之描述可總結為以下三點：
*結構嚴謹，繁而不亂，長而不冗，段落分明。
*在技法上，大手筆與精細的雕琢相結合。
《清明上河圖》不僅僅是偉大的現實主義繪畫藝術珍品，同時也為我們提供了北宋大都市的商業、手工業、民俗、建築、交通工具等詳實形象的第一手資料，具有重要歷史文獻價值。其豐富的思想內涵、獨特的審美視角、現實主義的表現手法，都使其在中國乃至世界繪畫史上被奉爲經典之作。
白壽彜任顧問的《中國通史（彩圖本）》對《清明上河圖》的評價：全卷所繪人物五百余位，牲畜五十多只，各種車船二十余輛艘，房屋眾多，道具無數，場面巨大，段落分明，結構嚴密，有條不紊。技法閑熟，用筆細致，線條遒勁，凝重老練。反映了高度精純的繪畫功力和出色的藝術成就。同時，因爲畫中所繪爲當時社會實錄，爲後世了解研究宋朝城市社會生活提供了重要的歷史資料。
《簡明不列顛百科全書》在“張擇端”詞條內對《清明上河圖》的評價：是一幅具有重要歷史價值的風俗長卷，畫家成功地描繪出汴京城內及近郊在清明時節社會上各階層的生活景象。主要表現的是勞動者和小市民。對人物、建築物、交通工具、樹木、水流之間的相互關係的處理，非常巧妙，整體感很強，具有極大的考史價值。此後歷代繪制的都市風俗畫，無不受其影響。
歷史上對張擇端創作《清明上河圖》的年代，以及“上河”一詞曾有過一些爭論；對畫中描繪的是清明時節，從金代以來似無異議。明代的《味水軒日記》中記載，這幅畫不但有宋徽宗的瘦金體題簽、雙龍小印，並且還有宋徽宗的題詩；詩中有“水在上河春”一句。這樣一來，這畫卷描繪的是春天景色就更不用懷疑了，中國近代及當代美術史家鄭振鐸、徐邦達、張安治等均主“春景”之說。但是，也有人對此提出異議。
20世紀80年代中期，鄒身城先生在中國宋史研究會上提出論文《宋代形象史料〈清明上河圖〉的社會意義》，認爲“清明”既非節令，亦非地名。這裏“清明”一詞，本是畫家張擇端進獻此畫時所作的頌辭。故有人認爲，這裏的“清明”要從廣義上去理解。《後漢書》有例證，是出云：“固幸得生‘清明之世’……”從語氣看這個“清明”係指政治開明。畫中題款“清明”語，本是張擇端進獻此畫，請帝王們賞識所作的頌辭。金人在畫面上留下的跋文說：“當日翰林呈畫本，承産風物正堪傳。”點明此畫主題在于表現承平風物。考張擇端行年，他於徽宗朝在翰林書畫院供職，此畫的第一位收藏人便是宋徽宗，證畫家意在稱頌盛世，討最高統治者歡心。知道了這個背景，顯然“清明”一詞不是指節令。
還有人認爲清明之意是指“清明坊”。根據是當時東京城劃分一百三十六坊，外城東郊區共劃分三坊，第一坊就是“清明坊”。
同時長期以來一些專家學者對“上河”二字的含義也有諸多解釋。關於“上河”的含義主要有幾種觀點：有專家學者認爲“上河”是指“河的上游”；有專家學者認爲“上河”是“逆水行舟”之意；也有專家學者認爲“上河”即“上墳之意”；還有專家學者認爲“上河”即“趕集上街之意”。
2011年臺北國立故宮博物院、公視與歐洲藝術媒體Arte頻道法國公視聯手製作的紀錄片《話·畫——清明上河圖》，其拍攝的是故宮典藏的清院本《清明上河圖》真跡；帶領觀眾從新媒體的角度與名人口白，重現當年清明佳節古城熱鬧繁盛的景象。該片於2011年7月7日首播。
*  《清明上河圖》網上介紹圖文 - 中國北京故宮博物院
*  《清院本清明上河圖》線上鑑賞 －臺灣國立故宮博物院
*  公共電視－話．畫－清明上河圖 City of Cathay 導覽
*  臺灣公共電視臺－話．畫－清明上河圖
*  導覽－清明上河圖 －臺灣國立故宮博物院
*  介紹清明上河圖的英文紀錄片
*  3D動畫版 清明上河圖 - 北宋 張擇端 版 2010 世博展 ，描繪宋朝汴京城市生活。
*  2016年新書《清明上河圖》黃秀蘭/張幃超， 天行書苑  ，對全畫作細膩解讀的專書。
澳洲同性婚姻於2017年12月9日全國合法化。
澳大利亞同性結合
2004年1月1日，塔斯馬尼亞州率先以法律認可同性間的民事結合，包括收養子女的權利。
澳洲自由黨籍前總理約翰·霍華德（1996-2007）執政期間，一直長期反對同性婚姻。爾後在澳大利亞工黨執政（2007-2013）期間，反對同性婚姻也一直是工黨政府的立場，直至2013年才逐漸改變。
2013年10月22日，澳大利亞首都特區議會通過婚姻平等法(The Marriage Equality Act)，使其同性婚姻正式合法化，成為澳大利亞第一個承認同性婚姻的地區。時任自由黨籍長期強烈反對同性婚姻的總理-{zh-cn:托尼·阿博特;zh-hk:東尼·艾博特;zh-tw:東尼·艾伯特;}-(Tony Abbott)表示，將循求以合法權力廢止該特區同性婚姻法案，但2011年澳大利亞新法通過後，-{zh-cn:阿博特;zh-hk:艾博特;zh-tw:艾伯特;}-要以合法權力廢止首都特區同性婚姻法案面臨不小困難與風險。
爾後在2013年12月12日澳洲高等法院裁定，同性婚姻合法應交由國會決定，地方政府無權通過，推翻澳大利亞首都特區婚姻平等法，27對結婚的同性伴侶婚姻宣告無效。
此後澳洲便陷入了同婚合法與否的爭執當中，即使鄰國紐西蘭開放同性婚姻，澳洲政府仍不為所動，與歐美其他國家比較下，澳洲政府在同婚的立場上顯得有些裹足不前。
2016年改選後的國會中，小黨中的綠黨成員全部支持同性婚姻，工黨參眾兩院議員支持同性婚姻的成員也居多，而向來被視為保守的自由黨國家黨聯盟在自由黨籍總理麥肯·布萊·滕博爾（Malcolm Bligh Turnbull）帶領下，其支持同性婚姻合法化的勢力也開始急速茁壯。
另外在此之前澳大利亞的塔斯馬尼亞州也曾兩度發起過同性婚姻提案，但最終都遭到封殺而沒成功。國會眾議院也曾表決相關法案，但未獲通過。
在2017年12月9日同性婚姻於澳大利亞獲得聯邦法律的正式認可之前，在州級別上，塔斯馬尼亞州、維多利亞州、新南威爾斯州、昆士蘭州、澳大利亞首都特區及南澳州已先後通過民事結合的法案，而西澳洲則承認事實同性伴侶關係。
澳洲統計局受政府委託，於2017年9月12日至11月7日進行全國自願性同性婚姻郵寄調查，於11月15日公布參與郵寄調查的澳洲公民61.6%支持同性婚姻。
同年11月30日，澳洲參議院以43票支持，12票反對，三讀通過同性婚姻合法化。12月7日，澳洲眾議院以136票支持，4票反對，9票棄權三讀通過參議院版本的同性婚姻法，澳洲成為全球第25個同婚合法化的國家。翌日由澳洲總督代表英國女王簽署，正式於同年12月9日生效。按澳洲婚姻法，結婚當事人須於結婚日30天前向官方提出申請，所以除非獲得特許可以提前結婚的個案，一般澳洲聯邦政府官方合法承認的本國同性婚姻於2018年1月9日起執行。
*  Recognition of same-sex relationships - an international and comparative perspective.
*  PM joins opposition to gay marriage as cleric's election stalls (Sydney Morning Herald)
*  Latham promises same sex rights (The Age)
*   Labor Right sinks same-sex scheme (The Age)
*  Latham flirts with prejudice over gay marriage ban (Greens media release)
*  Same-sex wedding fever (Sydney Morning Herald)
*  Love, honour and gay (The Bulletin)
左慈，字元放，東漢末方士，廬江郡（今安徽省潛山縣）人。
左慈少知“補導之術。並為軍吏”，後居天柱山，習煉丹。曹植《辯道論》中說他擅長房中術。《后漢書·方術列傳》說左慈善道術，記載了許多怪誕奇異之事，例如說他嘗與曹操宴，操欲得松江鱸魚，慈以銅盤盛水釣得，操大喜。又應曹操要求在頃刻間取得蜀中生薑，同時得帶話囑咐當地操使增買兩匹錦緞，事後得到符合的匯報。后在郊宴中他用幻術悉取諸壚的酒脯以餉百許操從者，被操追殺而隱身循形，復見于羊山頭隱入羊群，卒不可得。葛洪《神仙傳》也說他能夠役使鬼神（理解天干地支），會變化、辟谷，自稱活了三百歲以上。曹植《辯道論》：世有方士，吾王悉所招致，甘陵有甘始，廬江有左慈，陽城有郤儉。始行氣導引，慈曉房中之術，儉善辟穀，悉號三百歲。
《抱樸子·金丹篇》載，左慈是葛玄之師。《抱樸子·金丹篇》，“葛玄從慈受之”。左慈知曉補導之術，宦官嚴峻曾跟從左慈問受。
*《三國演義》第六十八回記載樣貌“眇一眼，跛一足，頭戴白藤冠，身穿青懶衣”，道號烏角先生。著名的就是左慈戲曹操。
*1983年香港版邵氏電影：《神通術與小霸王》：關鋒飾演左慈
*1996年臺灣版中視電視劇：《三國英雄傳之關公》：管管飾演左慈。
*2009年臺灣版民視電視劇：《終極三國》：巴戈飾演左慈。
*《火鳳燎原》（陳某）:設定是「南華八怪」之一，與袁紹素有往來。亦是袁紹之私生子、水鏡八奇之首袁方之師傅，曾派人以毒箭伏擊孫策以報于吉之仇，使孫策痛苦百日而死。官渡之戰時曾率太平道衆響應袁方，其後投靠曹操，實為密謀為袁紹、袁方報仇等待機會，赤壁之戰後乘機刺殺曹操，被盟友司馬懿出賣，死於殘兵成員三船之手。
* 《天子傳奇7三國驕皇》:設定為仙道之一員，於張角三兄弟死後、于吉成為百觸水獸後，在峨眉山修道意外獲得遁甲天書，並修練成書中之人遁便遁身於董卓體內及控制董卓以挾劉協，卻因女流之流主百歲夫人唆擺呂布殺害董卓而失敗告終。
*《三國誌異》（鄭健和）:以主角身份來演繹三國故事，設定上真正身份其實應為漢靈帝劉宏，被兒時玩伴真左慈陷害交換身份，以左慈之名展開人生，先後與少年的曹操、袁紹、劉備、呂布等人於洛陽共抗為禍人間的闇靈，度過一段單純的少年友情時光，長大之後各自際遇和歧異想法，走上不同的道路。
*2005年起：真三國無雙系列（CV：佐藤正治）
*2016年：朕的江山、Crash Fever
*《三國志·魏志·方技傳》華佗傳附注
*葛洪《神仙傳·卷八》?《抱樸子內篇·金丹》
*《三國演義第六十八回·甘寧百騎劫魏營 左慈擲盃戲曹操》
*《曹植·辯道論》（《全三國文·卷十八》完整版）
*《歷世真仙體道通鑑·卷十五》
文翁，名黨，字仲翁，西漢官史。廬江郡舒縣（今屬安徽舒城）人。漢景帝末年為蜀郡守，興教育、舉賢能、修水利，政績卓著。
漢初四川成都一帶為邊陲。文翁治蜀首重教育，選派小吏至長安，受業博士，或學律令，結業回歸，擇優“為右職，次舉官至郡守刺史者”；在成都興“石室”，辦地方“官學”，招下縣子弟入學，入學者免除徭役，以成績優良者補郡縣吏，促進當地文化的發展。班固在《漢書》中評論說：“至今巴蜀好文雅，文翁之化也”。
文翁在任職期間，帶領人民“穿湔江，灌溉繁田一千七百頃”。是第一個擴大都江堰灌區的官員。由于注重興修水利，發展農業，使蜀郡出現了“世平道治，民物阜康”的局面。
后世人緬懷文翁，蜀立專祠歲時祭祀。
這個句子“this is an example of a huffman tree”中得到的字母頻率來建構霍夫曼樹。句中字母的編碼和頻率如圖所示。編碼此句子需要135 bit（不包括保存樹所用的空間）
霍夫曼編碼，又譯為哈夫曼編碼、赫夫曼編碼，是一種用於無損數據壓縮的熵編碼（權編碼）演算法。由美國計算機科學家大衛·霍夫曼在1952年發明。
在計算機資料處理中，霍夫曼編碼使用變長編碼表對源符號（如文件中的一個字母）進行編碼，其中變長編碼表是通過一種評估來源符號出現機率的方法得到的，出現機率高的字母使用較短的編碼，反之出現機率低的則使用較長的編碼，這便使編碼之後的字符串的平均長度、期望值降低，從而達到無損壓縮數據的目的。
例如，在英文中，e的出現機率最高，而z的出現機率則最低。當利用霍夫曼編碼對一篇英文進行壓縮時，e極有可能用一個位元來表示，而z則可能花去25個位元（不是26）。用普通的表示方法時，每個英文字母均占用一個字節，即8個位元。二者相比，e使用了一般編碼的1/8的長度，z則使用了3倍多。倘若我們能實現對於英文中各個字母出現機率的較準確的估算，就可以大幅度提高無損壓縮的比例。
霍夫曼樹又稱最優二叉樹，是一種帶權路徑長度最短的二叉樹。所謂樹的帶權路徑長度，就是樹中所有的葉結點的權值乘上其到根結點的路徑長度（若根結點爲0層，葉結點到根結點的路徑長度爲葉結點的層數）。樹的路徑長度是從樹根到每一結點的路徑長度之和，記爲WPL=（W1*L1+W2*L2+W3*L3+...+Wn*Ln），N個權值Wi（i=1,2,...n）構成一棵有N個葉結點的二叉樹，相應的葉結點的路徑長度爲Li（i=1,2,...n）。可以證明霍夫曼樹的WPL是最小的。
1951年，霍夫曼在麻省理工學院（MIT）攻讀博士學位，他和修讀信息論課程的同學得選擇是完成學期報告還是期末考試。導師羅伯特·法諾（Robert Fano）出的學期報告題目是：尋找最有效的二進制編碼。由於無法證明哪個已有編碼是最有效的，霍夫曼放棄對已有編碼的研究，轉向新的探索，最終發現了基於有序頻率二叉樹編碼的想法，並很快證明了這個方法是最有效的。霍夫曼使用自底向上的方法構建二叉樹，避免了次優算法香農-范諾編碼（Shannon–Fano coding）的最大弊端──自頂向下構建樹。
1952年，於論文《一種構建極小多餘編碼的方法》中發表了這個編碼方法。
''Fig.1''
''Fig.2''霍夫曼編碼演算步驟, 左右樹排列順序可以加限制或不加限制
''Fig.3''
:一組符號（Symbol）和其對應的權重值（weight），其權重通常表示成-{zh-cn:概率;zh-tw:機率;}-（%）。
:一組二元的前置碼，其二元碼的長度為最短。
:符號集合，其S集合的大小為。
:權重集合，其W集合不為負數且。
:一組編碼，其C集合是一組二進制編碼且為相對應的編碼，。
:設為的加權的路徑長，對所有編碼，則
霍夫曼樹常處理符號編寫工作。根據整組資料中符號出現的頻率高低，決定如何給符號編碼。如果符號出現的頻率越高，則給符號的碼越短，相反符號的號碼越長。假設我們要給一個英文單字"F O R G E T"進行霍夫曼編碼，而每個英文字母出現的頻率分別列在''Fig.1''。
（一）進行霍夫曼編碼前，我們先建立一個霍夫曼樹。
:⒈將每個英文字母依照出現頻率由小排到大，最小在左，如''Fig.1''。
:⒉每個字母都代表一個終端節點（葉節點），比較F.O.R.G.E.T六個字母中每個字母的出現頻率，將最小的兩個字母頻率相加合成一個新的節點。如''Fig.2''所示，發現F與O的頻率最小，故相加2+3=5。
:⒊比較5.R.G.E.T，發現R與G的頻率最小，故相加4+4=8。
:⒋比較5.8.E.T，發現5與E的頻率最小，故相加5+5=10。
:⒌比較8.10.T，發現8與T的頻率最小，故相加8+7=15。
:⒍最後剩10.15，沒有可以比較的對象，相加10+15=25。
最後產生的樹狀圖就是霍夫曼樹，參考''Fig.2''。
（二）進行編碼
:1.給霍夫曼樹的所有左鏈結'0'與右鏈結'1'。
:2.從樹根至樹葉依序記錄所有字母的編碼，如''Fig.3''。
實現霍夫曼編碼的方式主要是創建一個二元樹和其節點。這些樹的節點可以儲存在陣列裡，陣列的大小為符號（symbols）數的大小n，而節點分別是終端節點（葉節點）與非終端節點（內部節點）。
一開始，所有的節點都是終端節點，節點內有三個欄位：
1.符號（Symbol）
2.權重（Weight、Probabilities、Frequency）
3.指向父節點的鏈結（Link to its parent node）
而非終端節點內有四個欄位：
1.權重（Weight、Probabilities、Frequency）
2.指向兩個子節點的 鏈結（Links to two child node）
基本上，我們用'0'與'1'分別代表指向左子節點與右子節點，最後為完成的二元樹共有n個終端節點與n-1個非終端節點，去除了不必要的符號並產生最佳的編碼長度。
過程中，每個終端節點都包含著一個權重（Weight、Probabilities、Frequency），兩兩終端節點結合會產生一個新節點，新節點的權重是由兩個權重最小的終端節點權重之總和，並持續進行此過程直到只剩下一個節點為止。
實現霍夫曼樹的方式有很多種，可以使用優先佇列（Priority Queue）簡單達成這個過程，給與權重較低的符號較高的優先順序（Priority），演算法如下：
⒈把n個終端節點加入優先佇列，則n個節點都有一個優先權Pi，1 ≤ i ≤ n
⒉如果佇列內的節點數>1，則：
:⑴從佇列中移除兩個最小的Pi節點，即連續做兩次remove（min（Pi）, Priority_Queue)
:⑵產生一個新節點，此節點為（1）之移除節點之父節點，而此節點的權重值為（1）兩節點之權重和
:⑶把（2）產生之節點加入優先佇列中
⒊最後在優先佇列裡的點為樹的根節點（root）
而此演算法的時間複雜度（ Time Complexity）為O（''n'' log ''n''）；因為有n個終端節點，所以樹總共有2n-1個節點，使用優先佇列每個迴圈須O（log ''n''）。
此外，有一個更快的方式使時間複雜度降至線性時間（Linear Time）O（''n''），就是使用兩個佇列（Queue）創件霍夫曼樹。第一個佇列用來儲存n個符號（即n個終端節點）的權重，第二個佇列用來儲存兩兩權重的合（即非終端節點）。此法可保證第二個佇列的前端（Front）權重永遠都是最小值，且方法如下：
⒈把n個終端節點加入第一個佇列（依照權重大小排列，最小在前端）
:⑴從佇列前端移除兩個最低權重的節點
:⑵將（1）中移除的兩個節點權重相加合成一個新節點
:⑶加入第二個佇列
⒊最後在第一個佇列的節點為根節點
雖然使用此方法比使用優先佇列的時間複雜度還低，但是注意此法的第1項，節點必須依照權重大小加入佇列中，如果節點加入順序不按大小，則需要經過排序，則至少花了O（''n'' log ''n''）的時間複雜度計算。
但是在不同的狀況考量下，時間複雜度並非是最重要的，如果我們今天考慮英文字母的出現頻率，變數n就是英文字母的26個字母，則使用哪一種演算法時間複雜度都不會影響很大，因為n不是一筆龐大的數字。
簡單來說，霍夫曼碼樹的解壓縮就是將得到的前置碼（Prefix Huffman code）轉換回符號，通常藉由樹的追蹤（Traversal），將接收到的位元串（Bits stream）一步一步還原。但是要追蹤樹之前，必須要先重建霍夫曼樹；某些情況下，如果每個符號的權重可以被事先預測，那麼霍夫曼樹就可以預先重建，並且儲存並重複使用，否則，傳送端必須預先傳送霍夫曼樹的相關資訊給接收端。
最簡單的方式，就是預先統計各符號的權重並加入至壓縮之位元串，但是此法的運算量花費相當大，並不適合實際的應用。若是使用Canonical encoding，則可精準得知樹重建的資料量只占''B''2^''B''位元（其中B為每個符號的位元數（bits））。如果簡單將接收到的位元串一個位元一個位元的重建，例如：'0'表示父節點，'1'表示終端節點，若每次讀取到1時，下8個位元則會被解讀是終端節點（假設資料為8-bit字母），則霍夫曼樹則可被重建，以此方法，資料量的大小可能為2~320位元組不等。雖然還有很多方法可以重建霍夫曼樹，但因為壓縮的資料串包含"trailing bits"，所以還原時一定要考慮何時停止，不要還原到錯誤的值，如在資料壓縮時時加上每筆資料的長度等。
考量到不同的應用領域以及該領域的平均性質，將會使用不同的通用機率，又或者，這個機率是可以從被壓縮文本中的實際頻率所取得。
原始的霍夫曼演算法是一個符號與符號間已知輸入機率分佈的最佳編碼方式，也就是說將不相關的符號個別編碼為如此的資料串流。然而，當符號間的限制被捨棄或是質量機率函數是未知的時候，如此方式則並非最佳化。此外，當這些符號之間不是互相獨立，且分佈不相同的時候，單一一個符號可能不足以實現最佳化。在這種情況之下，算術編碼可能比起霍夫曼編碼會有更佳的壓縮能力。
雖然上述兩種方法都可以組合任意數量的符號以實現更高效的編碼效果，並且通常適應於實際的輸入統計層面，但儘管最簡單的版本比霍夫曼編碼更慢且更複雜，算術編碼不會顯著增加其計算或算法複雜度。當輸入概率不是精確已知或在流內顯著變化時，這種靈活性特別有用。然而，霍夫曼編碼通常更快，並且算術編碼在歷史上是專利問題的一些主題。因此，許多技術歷來避免使用有利於霍夫曼和其他前綴編碼技術的算術編碼。截至2010年中期，隨著早期專利的到期，這種替代霍夫曼編碼的最常用技術已經進入公有領域。
對於具有均勻概率分佈的一組符號，以及作為2的冪之成員，霍夫曼編碼等同於簡單的二進位制編碼，例如 ASCII 編碼。這反映了如此的事實：無論壓縮方法是什麼，這種輸入都不可能進行壓縮，或只是說對數據無所作為，比起壓縮才是最佳選擇。
在任何情況下，霍夫曼編碼在所有方法中是最佳的方式，其中每個輸入符號是具有二元機率的已知獨立且相同分佈的隨機變量。前綴碼，特別是霍夫曼編碼，往往在小字母表上產生較差的效率，其中概率通常落在這些最佳（二元）點之間。當最可能符號的概率遠超過0.5時，可能發生霍夫曼編碼的最壞情況，使低效率的上限無限制。
在使用霍夫曼編碼的同時，有兩種相關的方法可以解決這種特定的低效問題。將固定數量的符號組合在一起（阻塞）通常會增加（並且永不減少）壓縮。隨著塊的大小接近無窮大，霍夫曼編碼理論上接近熵限制，即最佳壓縮。然而，阻塞任意大的符號組是不切實際的，因為霍夫曼代碼的複雜性在要編碼的可能性的數量上是線性的，這是在塊的大小中呈指數的數字。這限制了在實踐中完成的阻塞量。
廣泛使用的實際替代方案是行程編碼。該技術在熵編碼之前增加一步，特別是對重複符號進行執行次數的計數，然後對其進行編碼。對於伯努力（Bernoulli）過程的簡單情況，哥倫（Golomb）編碼在編碼遊程長度的前綴碼中是最佳的，這是通過霍夫曼編碼技術證明的事實。使用改進的霍夫曼編碼的傳真機採用類似的方法。但是，遊程編碼並不像其他壓縮技術那樣適應許多輸入類型。
霍夫曼編碼有衍生出許多的許多變化，其中一些使用類似霍夫曼的算法，而其他一些算法找到最佳前綴碼（例如，對輸出施加不同的限制）。注意，在後一種情況下，該方法不需要像霍夫曼那樣，實際上甚至不需要到多項式複雜度。
多元樹霍夫曼編碼演算法使用字母集 {0, 1, ... , ''n'' ? 1} ，來構建一棵 ''n'' 元樹。霍夫曼在他的原始論文中考慮了這種方法。這與二進制（''n''=2）算法僅有的差別，就是它每次把 ''n'' 個最低權的符號合併，而不僅是兩個最低權的符號。倘若 n ≥ 2, 則並非所有源字集都可以正確地形成用於霍夫曼編碼的多元樹。在這些情況下，必須添加額外的零概率佔位符。這是因為該樹必須為滿的 ''n'' 叉樹，所以每次合併會令符號數恰好減少 (''n'' -1), 故這樣的 ''n'' 叉樹存在當且僅當源字的數量模 (''n'' -1) 餘 1. 對於二進制編碼，任何大小的集合都可以形成這樣的二叉樹，因為 ''n'' -1 = 1.
自適應霍夫曼編碼的變化，涉及基於源符號序列中的最近實際頻率動態地計算概率，以及改變編碼樹結構以匹配更新的概率估計。它在實踐中很少使用，因為更新樹的成本使其比優化的自適應算術編碼慢，後者更靈活並且具有更好的壓縮。
在霍夫曼編碼的實現中，通常會使用權重表示數值概率，但是上面給出的算法不需要這樣;它只需要權重形成一個完全有序的可交換么半群，這意味著一種訂購權重和添加權重的方法。霍夫曼模板算法使人們能夠使用任何類型的權重（成本，頻率，權重對，非數字權重）和許多組合方法之一（不僅僅是加法），這個問題首先應用於電路設計。
長度受限的霍夫曼編碼是一種變體，其目標仍然是實現最小加權路徑長度，但是存在另外的限制，即每個碼字的長度必須小於給定常數。包合併算法通過一種與霍夫曼演算法非常相似的簡單貪婪方法解決了這個問題。
在標準的霍夫曼編碼問題中，假設集合中構成碼字的每個符號具有相同的傳輸成本：長度為''N''位的碼字總是具有''N''的成本，無論多少這些數字是0，有多少是1，等等。在這個假設下工作時，最小化消息的總成本和最小化數字總數是相同的。
具有不等字母成本的霍夫曼編碼是沒有這種假設的概括：由於傳輸介質的特性，編碼字母表的字母可能具有不均勻的長度。一個例子是摩爾斯電碼的編碼字母表，其中'破折號'比'點'需要更長的發送時間，因此傳輸時間中破折號的成本更高。目標仍然是最小化加權平均碼字長度，但僅僅最小化消息使用的符號數量已經不夠了。沒有算法以與傳統霍夫曼編碼相同的方式或相同的效率來解決這個問題，儘管它已經由卡普（Karp）解決，其解決方案已經針對哥林（Golin）的整數成本的情況進行了改進。
在標準霍夫曼編碼問題中，假設任何碼字可以對應於任何輸入符號。在字母表中，輸入和輸出的字母順序必須相同。
如果對應於按字母順序排列的輸入的權重是按數字順序排列的，則霍夫曼代碼具有與最佳字母代碼相同的長度，這可以從計算這些長度中找到，從而不需要使用胡 - 塔克（Hu-Tucker）編碼。由數字（重新）有序輸入產生的代碼有時被稱為規範霍夫曼代碼，並且由於易於編碼/解碼，通常是實踐中使用的代碼。用於找到該代碼的技術有時被稱為霍夫曼 - 香農 - 法諾編碼，因為它像霍夫曼編碼一樣是最優的，但是在重量概率上是字母的，例如香農 - 法諾編碼。
設符號集合，為發生的機率
，為編碼的長度
第三與第四個範例，同樣是五種組合，機率分布越集中，則亂度越少
:Shannon編碼定理：  ≤  ≤   ，若使用進位的編碼
霍夫曼碼的平均編碼長度：設，為資料長度
: ≤  ≤
*當有100個位子，有白色佔60%、咖啡色佔20%，藍色和紅色各佔10%，則該如何分配才能最佳化此座位?
(a)direct:
假設結果為：白色為00、咖啡色01，藍色10和紅色11個bits
則結果為:100*2 = 200bits
(b)huffman code: (must be satisfy the following conditions，if not change the node)
(1) 所有碼皆在Coding Tree的端點，再下去沒有分枝(滿足一致解碼跟瞬間解碼)
(2) 機率越大，code length越短；機率越小，code length越長
(3) 假設是第L層的node，是第L+1層的node
假設結果為：白色佔0、咖啡色10，藍色110和紅色111個bits
則結果為:60*1+20*2+20*3=160bits
相互比較兩個結果huffman code 整整少了40bits的儲存空間。
// 以下為C++程式碼，在G++下編譯通過
// 僅用於示範如何根據權值建構霍夫曼樹，
// 沒有經過性能上的優化及加上完善的異常處理。
const int size = 10;
struct node {                               // 霍夫曼樹節點結構
unsigned key;                           // 保存權值
node *lchild;                           // 左孩子指針
node *rchild;                           // 右孩子指針
deque forest;
deque code;                           // 此處也可使用bitset
node *ptr;
int frequencysize = {0};
void printCode(deque ptr);            // 用於輸出霍夫曼編碼
bool compare( node *a, node *b) {
return a->key key;
for (int i = 0; i > frequencyi;                // 輸入10個權值
ptr = new node;
ptr->key = frequencyi;
ptr->lchild = NULL;
ptr->rchild = NULL;
forest.push_back(ptr);
} // 形成森林，森林中的每一棵樹都是一個節點
// 從森林構建霍夫曼樹
for (int i = 0; i key = forest0->key + forest1->key;
ptr->lchild = forest0;
ptr->rchild = forest1;
forest.pop_front;
ptr = forest.front; // ptr是一個指向根的指針
system("PAUSE");
return EXIT_SUCCESS;
void printCode(deque ptr) {
// deque
huffman.h文件
#ifndef __HUFFMAN_H__
#define __HUFFMAN_H__
#define START printf("=====start=====\n")
#define END printf("=====end=====\n")
#define toByte(n) ((n) / 8 + ((n) % 8 > 0))
typedef struct HuffListNode HuffListNode,*hufflistnodep;
typedef struct HuffNode HuffNode,*huffnodep;
typedef struct HuffTree HuffTree,*hufftreep;
typedef struct HuffCode HuffCode,*huffcodep;
typedef struct HuffList HuffList,*hufflistp;
typedef struct HuffResult HuffResult,*huffresultp;
typedef struct HuffCode HuffBuf,*huffbufp;  //緩存類型
struct HuffListNode{
huffnodep node;     //huffman節點
hufflistnodep next; //后繼節點
};  //huffman頻率節點
struct HuffList{
hufflistnodep head;         //頭結點
int keys256;              //鍵值字典
int size;                   //鏈表長度
struct HuffNode{
int key;            //鍵
int weight;         //權重
huffnodep left;     //左節點
huffnodep right;    //右節點
};  //huffman節點
struct HuffCode{
char* code; //huffman code
int size;   //huffman code size
struct HuffTree{
huffnodep root;         //根
huffcodep codes256;   //key對應的代碼
int size;               //大小
};  //huffman樹
struct HuffResult{
char* code;      //生成的代碼
hufftreep tree;  //對應的霍夫曼樹
#ifndef __BOOLEAN__
#define __BOOLEAN__
typedef enum{
FALSE = 0,
TRUE = 1,
}Boolean;
huffnodep huffnode(int key,int weight); //初始化huffman節點
hufflistp hufflist;   //初始化hufflist
Boolean insertHuffNode(hufflistp list,huffnodep node);  //向指定的節點鏈表添加一個節點
huffnodep shiftHuffNode(hufflistp list);    //刪除第一個節點
hufftreep hufftree(hufflistp list);   //構建一棵huffman tree
huffbufp getFileBuf(const char* filename); //獲取文件的buf
hufftreep genhuffcodes(hufftreep tree,huffnodep node,char codes,int idx);  //獲取當前節點之下的節點的huffman編碼
hufflistp getHuffListByFile(const char* filename); //根據文件創建huffman鏈表
hufflistp getHuffListByBuf(huffbufp buf); //根據文件buf創建huffman鏈表
huffcodep getHuffCode(hufftreep tree,int key);  //獲取指定鍵值的huffcode
huffresultp getHuffCodesByFile(const char* filename);     //獲取文件的huffman code
huffresultp getHuffCodesByBuf(huffbufp buf);    //通過buf獲取codes
huffbufp getOriginBuf(huffresultp result);       //從result中解析出原始的字符串
huffbufp str2bin(char* str); //二進制字符串轉二進制數組
int putOriginToFile(huffresultp result,const char* filename);   //將result存儲到filename中
char* bin2str(huffbufp buf);    //二進制數組轉二進制字符串
huffbufp readHuffFile(const char* filename); //解析huff文件
huffman.c文件:
#include "huffman.h"
huffnodep huffnode(int key,int weight){
huffnodep ret = (huffnodep)malloc(sizeof(HuffNode));
ret->key = key;
ret->weight = weight;
ret->left = ret->right = NULL;
hufflistp hufflist{
hufflistp ret = (hufflistp)malloc(sizeof(HuffList));
ret->head = NULL;
memset(ret->keys,0,sizeof(ret->keys0)*256);
ret->size = 0;
Boolean insertHuffNode(hufflistp list,huffnodep node){
if(list == NULL
node == NULL
node->weight head;
hufflistnodep* rootp = &(list->head);
hufflistnodep* last = NULL; //當前指針的前驅指針
hufflistnodep tmp = (hufflistnodep)malloc(sizeof(HuffListNode));
tmp->node = node;
tmp->next = NULL;
if(node->key >= 0 && node->key keysnode->key = node->weight;   //添加key到keys字典
list->size++;
for(;cur != NULL  && cur->node->weight weight; cur = cur->next){
last = rootp;
rootp = &(cur->next);
tmp->next = cur;
if(last == NULL){   //第一個元素
list->head = tmp;
}else{  //向當前節點前面插入tmp節點
(*last)->next = tmp;
huffnodep shiftHuffNode(hufflistp list){
list->head == NULL) return NULL;
huffnodep ret = list->head->node;
hufflistnodep next = list->head->next;
free(list->head);
list->head = next;
list->size--;
//通過huffman list構建
hufftreep hufftree(hufflistp list){
hufftreep tree = (hufftreep)malloc(sizeof(HuffTree));
tree->root = NULL;
tree->size = 0;
memset(tree->codes,0,sizeof(tree->codes));
huffnodep a = NULL;
huffnodep b = NULL;
huffnodep c = NULL;
tree->size = 2 * list->size - 1;
while(list->size > 1){  //hufflistp長度大于1
a = shiftHuffNode(list);
b = shiftHuffNode(list);
c = huffnode(-256,a->weight+b->weight);    //新的節點
c->left = a;
c->right = b;
insertHuffNode(list,c); //將c壓回list
tree->root = c;
//生成所有key的huffman編碼
char codes8092;   //huffman編輯路徑
return genhuffcodes(tree,tree->root,codes,0);
//獲取文件內容的BUF
huffbufp getFileBuf(const char* filename){
FILE* fp = fopen(filename,"r");
if(fp == NULL) return NULL;
fseek(fp,0L,SEEK_END);
int len = ftell(fp);
rewind(fp); //重設
huffbufp ret = (huffbufp)malloc(sizeof(HuffBuf));
ret->code = (char*)malloc(len+1);
ret->size = len;
fread(ret->code,1,len,fp);
fclose(fp);
hufftreep genhuffcodes(hufftreep tree,huffnodep node,char codes,int idx){
if(tree == NULL
node == NULL){   //到達底部
if(node->left == NULL && node->right == NULL){  //葉子節點
int key = node->key;
huffcodep code = (huffcodep)malloc(sizeof(HuffCode));
code->code = (char*)malloc(idx+1);
code->size = idx;
memcpy(code->code,codes,code->size);
code->codecode->size = '\0';
tree->codeskey = code;
codesidx = '1'; //右
genhuffcodes(tree,node->right,codes,idx+1);
codesidx = '0'; //左
genhuffcodes(tree,node->left,codes,idx+1);
//通過文件生成huffman list
hufflistp getHuffListByFile(const char* filename){
huffbufp buf = getFileBuf(filename);
if(buf == NULL) return NULL;
hufflistp list = getHuffListByBuf(buf);
free(buf->code);
buf->code = NULL;
buf = NULL;
return list;
hufflistp getHuffListByBuf(huffbufp buf){
if(buf == NULL
buf->code == NULL) return NULL;
char* code = buf->code;
hufflistp list = hufflist;
for(int i = 0; codei != '\0'; i++){
unsigned char ch = codei;
list->keysch++;
for(int i = 0; i keysi > 0){   //插入存在的字符
insertHuffNode(list,huffnode(i,list->keysi));
huffcodep getHuffCode(hufftreep tree,int key){
if(key = 0 && tree->codeskey > 0){
return tree->codeskey;
huffresultp getHuffCodesByFile(const char* filename){
huffbufp buf = getFileBuf(filename);   //文件緩存
return getHuffCodesByBuf(buf);
huffresultp getHuffCodesByBuf(huffbufp buf){
huffresultp result = (huffresultp)malloc(sizeof(HuffResult));
result->code = NULL;
hufflistp list = getHuffListByBuf(buf); //huffman list
result->tree = hufftree(list);
int buf_len = buf->size;
for(int i = 0; buf->codei != '\0'; i++){
int key = (unsigned char)buf->codei;
huffcodep code = getHuffCode(result->tree,key);
if(code == NULL){
printf("LLL:%c{%d}\n",key,key);
len+=code->size;
result->code = (char*)malloc(len+1);
result->code0 = '\0';
unsigned char key = buf->codei;
strncat(result->code,code->code,code->size);
huffbufp getOriginBuf(huffresultp result){
if(result == NULL
result->code == NULL
result->tree == NULL) return NULL;
hufftreep tree = result->tree;
char* code = result->code;
for(int i = 0; codei != '\0';){
huffnodep root = tree->root;    //根節點
while(root->left != NULL && root->right != NULL && codei != '\0'){   //雙子節點存在
root = (codei == '0' ? root->left : root->right);
if((root->left != NULL
root->right != NULL) && codei == '\0'){ //錯誤
// printf("解析:%c{%s}\n",root->key,tree->codesroot->key->code);
ret->code0 = '\0';
int idx = 0;
ret->codeidx++ = root->key;
ret->codeidx = '\0';
int putOriginToFile(huffresultp result,const char* filename){
if(result == NULL) return 0;
// printf("res1%d:%s\n",(int)strlen(result->code),result->code);
// huffbufp b = str2bin(result->code);
// printf("%d\n",b->size);
// printf("res2:%s\n",bin2str(b));
// return 0;
huffbufp buf = str2bin(result->code);   //huffman code轉成buf
int i = 0;
for(i = 0; i tree->codesi > 0){ //
len+= 5+result->tree->codesi->size;   //key1:len4:size
huffbufp keys = (huffbufp)malloc(sizeof(HuffBuf));
keys->code = (char*)malloc(len);
keys->size = 0;
//獲取keys
keys->codeidx++ = i;    //key
int len = result->tree->codesi->size;
memcpy(keys->code+idx,&len,4);    //key size
// printf("%c%d:%d{%s}\n",i,i,len,result->tree->codesi->code);
idx+=4;
huffbufp tmp = str2bin(result->tree->codesi->code);
// printf("%d,%d\n",tmp->code0,tmp->size);
int tsize = toByte(tmp->size);
memcpy(keys->code+idx,tmp->code,tsize);
idx+=tsize;
keys->size = idx;   //諸多鍵的總空間
//寫出標準文件
//HUF\n
//size: 4b
//keys
//codes
FILE* fp = fopen(filename,"w");
if(fp == NULL) return -1;
fwrite("HUF\n",1,4,fp);
fwrite(&idx,1,4,fp);    //size
fwrite(keys->code,1,keys->size,fp); //寫入code
fwrite(&(buf->size),1,4,fp);    //size
fwrite(buf->code,1,toByte(buf->size),fp);
return 4+4+keys->size+4+buf->size;
huffbufp str2bin(char* str){ //二進制字符串轉二進制數組
// printf("bin:%s\n",str);
if(str == NULL) return NULL;
huffbufp buf = (huffbufp)malloc(sizeof(HuffBuf));
int l = strlen(str);
int size = (l / 8) + (l % 8 > 0);
buf->code = (char*)malloc(l);
memset(buf->code,0,l);
for(int i = 0; i codeidx |= (stri == '0' ? 0:1) size = l;
return buf;
char* bin2str(huffbufp buf){
char* ret = (char*)malloc(buf->size+1);
for(int i = 0; i size; i++){
int idx = i / 8;
int offset = i % 8;
reti = (buf->codeidx & (0x01 size = '\0';
huffbufp readHuffFile(const char* filename){
if(memcmp(buf->code,"HUF\n",4) != 0) return NULL;   //文件不以BUF\n開頭
//BUF\n
//key size
int key_size = *(int*)(buf->code+4);
int base = 8; //偏移量
huffcodep* codes = tree->codes;   //key對應代碼
memset(codes,0,sizeof(huffcodep)*256);
int oft = 0;
for(;oft codeoffset;
// printf("%d%c\n",key,key);
int size = *(int*)(buf->code+offset+1); //長度
int byte = toByte(size);
huffbufp htmp = (huffbufp)malloc(sizeof(HuffBuf));
//鍵對應代碼
htmp->code = buf->code+offset+5;    //緩存代碼
htmp->size = size;  //緩存大小
// printf("%c%d\n",key,key);
huffcodep tmp = (huffcodep)malloc(sizeof(HuffCode));
tmp->size = size;   //key的大小
tmp->code = bin2str(htmp);
tree->codeskey = tmp;
tree->size++;   //樹的大小增加
huffnodep root = tree->root;
if(root == NULL){
tree->root = huffnode(-256,0);
root = tree->root;
char ch = tmp->codei;
huffnodep node = NULL;
if(ch == '0'){
node = root->left;
if(node == NULL){
node = huffnode(-256,0);
root->left = node;
node = root->right;
root->right = node;