專(zhuān)利名稱(chēng):一種用于檢索字符串的方法
技術(shù)領(lǐng)域:
本發(fā)明涉及大量字符串集合管理相關(guān)的技術(shù)領(lǐng)域,特別是涉及一種用于檢索字符串的方法。
背景技術(shù):
今年來(lái),隨著計(jì)算機(jī)用戶(hù)的持續(xù)增加,各種計(jì)算機(jī)應(yīng)用不斷涌現(xiàn),而許多計(jì)算機(jī)應(yīng)用都涉及到對(duì)一個(gè)非常大的字符串集合的有效管理問(wèn)題。例如,從檔案管理、文獻(xiàn)目錄查找、地理信息索引、搜索引擎到WEB上大量文本的處理都涉及到一個(gè)非常大的字符串集合。同時(shí),隨著IPv6的興起,如何在巨量的IP地址中實(shí)現(xiàn)對(duì)IP的快速檢索成為一個(gè)人們關(guān)心的問(wèn)題;目前已有許多用于字符串管理的數(shù)據(jù)結(jié)構(gòu),其中二叉搜索樹(shù)BST是最簡(jiǎn)單且最直觀(guān)的一種。BST結(jié)構(gòu)的性能主要取決于樹(shù)的形態(tài),與輸入字符串集的排列有關(guān)。假設(shè)字符串集合的分布是穩(wěn)定的,則BST結(jié)構(gòu)是相當(dāng)快的;如果字符串集合的分布不穩(wěn)定,特別是有序的,BST的性能最差為(o(n));BST退化為一棵單枝樹(shù)。因此BST特別不適合有序排列的輸入字符串集合。此外BST有許多的變種,如AVL-樹(shù)和紅-黑樹(shù),它們與BST樹(shù)的不同在于插入字符串的過(guò)程中重組樹(shù)的結(jié)構(gòu),保持樹(shù)的近似平衡,從而保證不會(huì)出現(xiàn)單枝樹(shù),BST樹(shù)及其變種雖然占用空間少但速度慢,所以并不是最理想的數(shù)據(jù)結(jié)構(gòu)。字符串處理中常用的另外一種數(shù)據(jù)結(jié)構(gòu)是哈希表和B樹(shù)。哈希表是一種直接計(jì)算記錄存放地址的方法,它在關(guān)鍵碼(字符串)與存儲(chǔ)位置之間直接建立映像。但是,在某些要求字符串有序存儲(chǔ)(如索引維護(hù)及前綴查找)的應(yīng)用中,哈希表就價(jià)值就不是很大了。B樹(shù)在要求快速檢索字符串時(shí)也存在這個(gè)問(wèn)題;如果能針對(duì)要訪(fǎng)問(wèn)數(shù)據(jù)的內(nèi)部結(jié)構(gòu)特點(diǎn),定義一個(gè)通用的數(shù)據(jù)存儲(chǔ)和訪(fǎng)問(wèn)方法,則可以提高存儲(chǔ)效率,并降低數(shù)據(jù)訪(fǎng)問(wèn)的時(shí)間。
發(fā)明內(nèi)容
本發(fā)明的目的在于提供一種用于高效檢索字符串的方法。
本發(fā)明解決其技術(shù)問(wèn)題采用的技術(shù)方案如下1)以多叉樹(shù)的存儲(chǔ)方式來(lái)記錄字符串的字符序列結(jié)構(gòu)信息,同時(shí)對(duì)多叉樹(shù)結(jié)點(diǎn)的內(nèi)存分配進(jìn)行了分層管理用多叉樹(shù)的形式來(lái)存儲(chǔ)字符串,樹(shù)的第一層為根結(jié)點(diǎn),接下來(lái)的每一層依次表示該字符串中的一個(gè)字符,每個(gè)樹(shù)結(jié)點(diǎn)存儲(chǔ)了當(dāng)前字符,從根結(jié)點(diǎn)到該結(jié)點(diǎn)所形成的字符串的編號(hào)id和后繼結(jié)點(diǎn)的指針,該編號(hào)id用于標(biāo)識(shí)一個(gè)唯一的字符串,程序中默認(rèn)從1開(kāi)始,按序分配,或由用戶(hù)指定;對(duì)中文字符串來(lái)說(shuō),多叉樹(shù)的第一層為根結(jié)點(diǎn),第二層則按照字符串第一個(gè)漢字的GB2312編碼來(lái)標(biāo)識(shí),共有三千多個(gè)分支,分別表示三千多個(gè)漢字,最左邊分支的GB2312編碼最小,表示漢字“阿”,其他的漢字就利用它與“阿”的GB2312編碼的差值來(lái)索引;第三層表示字符串中的第二個(gè)漢字,由于漢語(yǔ)詞匯固定的組合和搭配形式,并不是任意兩個(gè)漢字都可以組成一個(gè)詞語(yǔ),每個(gè)漢字后面可能出現(xiàn)的漢字是有限的,而不是漢字的全集;所以從第三層開(kāi)始,如果每個(gè)漢字結(jié)點(diǎn)下一層可能出現(xiàn)的后續(xù)漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,就用后繼漢字與“阿”的GB2312編碼的差值來(lái)索引;否則,如果每個(gè)漢字結(jié)點(diǎn)下一層可能出現(xiàn)的后續(xù)漢字的數(shù)目小于不同漢字?jǐn)?shù)目的一半,就只存儲(chǔ)漢字結(jié)點(diǎn)下一層可能出現(xiàn)的后續(xù)漢字的信息;依此類(lèi)推,這樣就可以大大節(jié)省存儲(chǔ)空間;對(duì)英文字符串來(lái)說(shuō),多叉樹(shù)的第一層也為根結(jié)點(diǎn),第二層表示字符串的第一個(gè)字母,共有26個(gè)分支,分別對(duì)應(yīng)26個(gè)英文字母,由于英文字母的個(gè)數(shù)少,不會(huì)占用很大的存儲(chǔ)空間,因此多叉樹(shù)第二層以下的各層也采用同樣的方式來(lái)依次表示字符串中的各個(gè)字母,即每一層都包括26個(gè)分支;2)將字符串插入到多叉樹(shù)中a)對(duì)于中文字符串第一步,以字符串中的第一個(gè)漢字的GB2312編碼與“阿”的GB2312編碼的差值索引到多叉樹(shù)第二層的分支結(jié)點(diǎn),這個(gè)分支結(jié)點(diǎn)存儲(chǔ)的是其下層結(jié)點(diǎn),也就是字符串的第二個(gè)漢字的信息的指針;第二步,如果第一個(gè)漢字可能的后繼漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,則后繼漢字的GB2312編碼與“阿”的GB2312編碼的差值索引到第三層的分支結(jié)點(diǎn);否則為第一個(gè)漢字結(jié)點(diǎn)預(yù)分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元(這里為了避免每次添加字符串時(shí)都要重新分配,每次分配時(shí)將一次性預(yù)分配16個(gè)下層結(jié)點(diǎn)單元);如果已經(jīng)為該分支結(jié)點(diǎn)分配了存儲(chǔ)下層(第三層)結(jié)點(diǎn)的空間,則給第二個(gè)漢字分配其中的一個(gè)單元;如果上一次分配的16個(gè)單元已經(jīng)用完,則重新再分配16個(gè);第三層結(jié)點(diǎn)單元中存儲(chǔ)了第二個(gè)漢字,和當(dāng)前已添加的字符串的編號(hào)id號(hào)以及第三個(gè)漢字的信息的指針;第三步,同理,如果第二個(gè)漢字可能的后繼漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,則后繼漢字的GB2312編碼與“阿”的GB2312編碼的差值索引到第四層的分支結(jié)點(diǎn);否則給第三層結(jié)點(diǎn)預(yù)分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元,存儲(chǔ)第三個(gè)漢字和當(dāng)前已添加的字符串的編號(hào)id號(hào)以及第四個(gè)漢字的信息的指針;依此類(lèi)推,依次為每一個(gè)結(jié)點(diǎn)分配其下層結(jié)點(diǎn)的存儲(chǔ)空間,直到字符串的末尾,此時(shí)該字符串就添加到多叉樹(shù)中了;b)對(duì)于英文字符串第一步,根據(jù)字符串中的第一個(gè)字母在字母表中的序號(hào)索引到多叉樹(shù)第二層的分支結(jié)點(diǎn),這個(gè)分支結(jié)點(diǎn)存儲(chǔ)的是第三層結(jié)點(diǎn),也就是字符串的第二個(gè)字母的信息的指針;第二步,同理根據(jù)字符串中第二個(gè)字母在字母表中的序號(hào)索引到多叉樹(shù)第三層的分支結(jié)點(diǎn);依此類(lèi)推,直到字符串的末尾,此時(shí)該字符串就添加到多叉樹(shù)中了;3)字符串集的壓縮由于建立多叉樹(shù)時(shí),有些層可能存在多個(gè)分支,比如中文的多叉樹(shù)的第二層就有三千多個(gè)分支,對(duì)一個(gè)字符串集而言有些分支可能并沒(méi)有用到;而且分支較少的層每次都是為結(jié)點(diǎn)預(yù)分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元,這樣有些分配出去的空間可能并沒(méi)有使用;因此先把多叉樹(shù)結(jié)構(gòu)寫(xiě)入外存,需要讀入內(nèi)存時(shí),釋放多叉樹(shù)中這些空的不用的單元,只把有數(shù)據(jù)的單元按照原來(lái)的結(jié)構(gòu)讀到內(nèi)存中,這樣就大大實(shí)現(xiàn)了字符串集的壓縮;4)在多叉樹(shù)中精確檢索字符串a(chǎn))對(duì)于中文字符串第一步,根據(jù)字符串中的第一個(gè)漢字的GB2312編碼與“阿”的GB2312編碼的差值找到該漢字在多叉樹(shù)中第二層的分支結(jié)點(diǎn);第二步,沿著該分支往下,根據(jù)待檢索的字符串的第二個(gè)漢字找到第三層的分支結(jié)點(diǎn);再?gòu)牡谌龑拥姆种ЫY(jié)點(diǎn)出發(fā),根據(jù)待檢索字符串中第三個(gè)漢字找到第四層的分支結(jié)點(diǎn);依此類(lèi)推,直到該字符串的末尾,末尾所在的結(jié)點(diǎn)記錄了該字符串的編號(hào)id,返回該編號(hào)id號(hào)則完成了字符串的精確檢索;若多叉樹(shù)的分支無(wú)法到達(dá)該字符串的末尾,則證明該字符串不在多叉樹(shù)中;b)對(duì)于英文字符串第一步,根據(jù)字符串中的第一個(gè)字母在字母表中的序號(hào)找到該字母在多叉樹(shù)中第二層的分支結(jié)點(diǎn);第二步,沿著該分支往下,根據(jù)字符串中第二個(gè)字母在字母表中的序號(hào)找到該字母在多叉樹(shù)中第三層的分支結(jié)點(diǎn);依此類(lèi)推,直到字符串的末尾,末尾所在的結(jié)點(diǎn)記錄了該字符串的編號(hào)id,返回該編號(hào)id號(hào)則完成了字符串的精確檢索;若多叉樹(shù)的分支無(wú)法到達(dá)該字符串的末尾,則證明該字符串不在多叉樹(shù)中;5)在多叉樹(shù)中模糊檢索字符串字符串的模糊檢索是指給定字符串的前綴或后綴,在多叉樹(shù)中檢索出所有包含該前綴或后綴的字符串;對(duì)前綴字符串的檢索,采用與精確檢索相同的方式,從多叉樹(shù)的根結(jié)點(diǎn)開(kāi)始逐層找到該字符串前綴所在分支上的結(jié)點(diǎn),直到前綴的末尾,找到從末尾結(jié)點(diǎn)開(kāi)始的所有的下層分支,這些下層分支表示的是該前綴的后續(xù)字符串,該前綴字符串分別與這些下層分支表示的后續(xù)字符串組合即為模糊檢索的結(jié)果;若多叉樹(shù)的分支無(wú)法到達(dá)該前綴字符串的末尾,則檢索失?。粚?duì)后綴字符串的檢索,則反方向從多叉樹(shù)的底層結(jié)點(diǎn)開(kāi)始,向上逐層找到與后綴字符串中的字符相對(duì)應(yīng)的分支結(jié)點(diǎn),這里也是從后綴字符串的末尾字符開(kāi)始往前查找,直到后綴的最前端,找到最前端字符對(duì)應(yīng)結(jié)點(diǎn)的所有上層分支,這些上層分支表示的是該后綴前面的字符串,這些上層分支分別串接該后綴字符串即為模糊檢索的結(jié)果;若向上查找時(shí),多叉樹(shù)的分支無(wú)法到達(dá)該后綴字符串的最前端,則檢索失?。?)從多叉樹(shù)中刪除字符串第一步,按照精確檢索的方法找到待刪除的字符串在多叉樹(shù)中的分支;第二步,若字符串的末尾所在的分支結(jié)點(diǎn)是多叉樹(shù)的底層結(jié)點(diǎn),即該字符串沒(méi)有后續(xù)字符,則刪除末尾結(jié)點(diǎn)中該字符串的編號(hào)id,并釋放末尾結(jié)點(diǎn)占用的存儲(chǔ)空間;若字符串的末尾所在的分支結(jié)點(diǎn)不是多叉樹(shù)的底層結(jié)點(diǎn),即末尾結(jié)點(diǎn)還有下層分支,則僅刪除末尾結(jié)點(diǎn)中該字符串的編號(hào)id,其他不變;刪除成功。
本發(fā)明與背景技術(shù)相比,具有的有益的效果是本發(fā)明是一種適用于大規(guī)模字符串集合環(huán)境下的,用于高效的檢索中英文字符串的方法。
(1)本發(fā)明是一種全新的索引方法,能夠高效地實(shí)現(xiàn)對(duì)中英文字符串的存儲(chǔ)、添加、檢索和刪除,尤其適合在大規(guī)模字符串處理環(huán)境中,字符串的快速查找以及前綴、后綴等各種形式的模糊查找,在時(shí)間和空間效率上都優(yōu)于傳統(tǒng)的Btree索引方法。
(2)本發(fā)明同時(shí)對(duì)多叉樹(shù)的存儲(chǔ)進(jìn)行了分層管理,對(duì)于多叉樹(shù)結(jié)點(diǎn)的內(nèi)存分配采用了靜態(tài)分配和動(dòng)態(tài)分配相結(jié)合的方式,并對(duì)最后生成的多叉樹(shù)結(jié)構(gòu)進(jìn)行了適度的壓縮,有效的節(jié)省了內(nèi)存資源,克服了傳統(tǒng)的檢索字符串方法所存在的檢索效率低、或檢索效率雖高但是過(guò)分消耗內(nèi)存資源、以及不支持模糊查詢(xún)等不足。
圖1是系統(tǒng)的總體結(jié)構(gòu)示意圖;圖2是向多叉樹(shù)中插入了四個(gè)字符串(分詞,互聯(lián)網(wǎng),搜尋,搜索)后,多叉樹(shù)的邏輯示意圖;圖3是向多叉樹(shù)中插入了四個(gè)字符串(分詞,互聯(lián)網(wǎng),搜尋,搜索)后,多叉樹(shù)的內(nèi)部結(jié)構(gòu)示意圖;具體實(shí)施方式
在基于大規(guī)模字符串處理的應(yīng)用系統(tǒng)中,采用本發(fā)明所提供的多叉樹(shù)索引訪(fǎng)問(wèn)方式,可以實(shí)現(xiàn)對(duì)字符串的高效檢索,以搜索引擎中分詞詞典為例,系統(tǒng)的總體結(jié)構(gòu)示意圖如圖1所示,具體的實(shí)施步驟如下1.創(chuàng)建字符串的存儲(chǔ)結(jié)構(gòu),初始化字符串存儲(chǔ)結(jié)構(gòu),分配必要的內(nèi)存空間,以及決定靜態(tài)分配內(nèi)存的層數(shù)和動(dòng)態(tài)分配內(nèi)存的層數(shù)。
2.調(diào)用向多叉樹(shù)中插入字符串的程序,具體過(guò)程如下a)對(duì)于中文字符串第一步,以字符串中的第一個(gè)漢字的GB2312編碼與“阿”的GB2312編碼的差值索引到多叉樹(shù)第二層的分支結(jié)點(diǎn),這個(gè)分支結(jié)點(diǎn)存儲(chǔ)的是其下層結(jié)點(diǎn),也就是字符串的第二個(gè)漢字的信息的指針;第二步,如果第一個(gè)漢字可能的后繼漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,則后繼漢字的GB2312編碼與“阿”的GB2312編碼的差值索引到第三層的分支結(jié)點(diǎn);否則為第一個(gè)漢字結(jié)點(diǎn)預(yù)分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元(這里為了避免每次添加字符串時(shí)都要重新分配,每次分配時(shí)將一次性預(yù)分配16個(gè)下層結(jié)點(diǎn)單元);如果已經(jīng)為該分支結(jié)點(diǎn)分配了存儲(chǔ)下層(第三層)結(jié)點(diǎn)的空間,則給第二個(gè)漢字分配其中的一個(gè)單元;如果上一次分配的16個(gè)單元已經(jīng)用完,則重新再分配16個(gè);第三層結(jié)點(diǎn)單元中存儲(chǔ)了第二個(gè)漢字,和當(dāng)前已添加的字符串的編號(hào)id號(hào)以及第三個(gè)漢字的信息的指針;第三步,同理,如果第二個(gè)漢字可能的后繼漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,則后繼漢字的GB2312編碼與“阿”的GB2312編碼的差值索引到第四層的分支結(jié)點(diǎn);否則給第三層結(jié)點(diǎn)預(yù)分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元,存儲(chǔ)第三個(gè)漢字和當(dāng)前已添加的字符串的編號(hào)id號(hào)以及第四個(gè)漢字的信息的指針;依此類(lèi)推,依次為每一個(gè)結(jié)點(diǎn)分配其下層結(jié)點(diǎn)的存儲(chǔ)空間,直到字符串的末尾,此時(shí)該字符串就添加到多叉樹(shù)中了;b)對(duì)于英文字符串第一步,根據(jù)字符串中的第一個(gè)字母在字母表中的序號(hào)索引到多叉樹(shù)第二層的分支結(jié)點(diǎn),這個(gè)分支結(jié)點(diǎn)存儲(chǔ)的是第三層結(jié)點(diǎn),也就是字符串的第二個(gè)字母的信息的指針;第二步,同理根據(jù)字符串中第二個(gè)字母在字母表中的序號(hào)索引到多叉樹(shù)第三層的分支結(jié)點(diǎn);依此類(lèi)推,直到字符串的末尾,此時(shí)該字符串就添加到多叉樹(shù)中了;如,向多叉樹(shù)中插入字符串“互聯(lián)網(wǎng)”,步驟為(1)用“互”的GB2312編碼減去“阿”的GB2312編碼,若差值為a,則應(yīng)插入到多叉樹(shù)第二層的第(a+1)個(gè)分支,這個(gè)分支結(jié)點(diǎn)中存儲(chǔ)的是“互”的后繼漢字“聯(lián)”的指針,它指向?yàn)闈h字“聯(lián)”所分配的存儲(chǔ)單元。
(2)如果“互”的后繼漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,則用“聯(lián)”的GB2312編碼減去“阿”的GB2312編碼,若差值為b,則“聯(lián)”在多叉樹(shù)第三層的第(b+1)個(gè)分支,這個(gè)分支結(jié)點(diǎn)中存儲(chǔ)的是字符串“互聯(lián)”的編號(hào)id和“聯(lián)”的后繼漢字“網(wǎng)”的指針。如果“互”的后繼漢字的數(shù)目小于不同漢字?jǐn)?shù)目的一半,為“互”分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元,把字符串“互聯(lián)”的編號(hào)id和“聯(lián)”的后繼漢字“網(wǎng)”的指針存到其中一個(gè)下層結(jié)點(diǎn)單元中。
(3)同理,如果“聯(lián)”的后繼漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,則用“網(wǎng)”的GB2312編碼減去“阿”的GB2312編碼,若差值為c,則“聯(lián)”在多叉樹(shù)第三層的第(c+1)個(gè)分支,這個(gè)分支結(jié)點(diǎn)中存儲(chǔ)的是字符串“互聯(lián)網(wǎng)”的編號(hào)id。如果“互”的后繼漢字的數(shù)目小于不同漢字?jǐn)?shù)目的一半,為“聯(lián)”分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元,把字符串“互聯(lián)網(wǎng)”的編號(hào)id存到其中一個(gè)下層結(jié)點(diǎn)單元中。這樣就完成了字符串“互聯(lián)網(wǎng)”的插入。
向多叉樹(shù)中插入(分詞,互聯(lián)網(wǎng),搜索,搜尋)四個(gè)字符串之后,多叉樹(shù)的邏輯示意圖如圖2所示,其中,黑色結(jié)點(diǎn)用于標(biāo)識(shí)從根到此結(jié)點(diǎn)可形成一個(gè)字符串,用于特定的編號(hào)id標(biāo)記它;插入后對(duì)應(yīng)的字符串內(nèi)部存儲(chǔ)結(jié)構(gòu)示意圖如圖3所示。
3.調(diào)用字符串集的壓縮程序,具體過(guò)程如下
于上述插入了(分詞,互聯(lián)網(wǎng),搜索,搜尋)四個(gè)字符串的字符串存儲(chǔ)結(jié)構(gòu),調(diào)用字符串集壓縮程序的作用就是,通過(guò)把多叉樹(shù)后兩層中預(yù)先分配的多余的空指針釋放掉,來(lái)實(shí)現(xiàn)內(nèi)存的壓縮。
4.調(diào)用精確檢索字符串的程序,具體過(guò)程如下a)對(duì)于中文字符串第一步,根據(jù)字符串中的第一個(gè)漢字的GB2312編碼與“阿”的GB2312編碼的差值找到該漢字在多叉樹(shù)中第二層的分支結(jié)點(diǎn);第二步,沿著該分支往下,用二分查找的方法,根據(jù)待檢索的字符串的第二個(gè)漢字找到第三層的分支結(jié)點(diǎn);再?gòu)牡谌龑拥姆种ЫY(jié)點(diǎn)出發(fā),根據(jù)待檢索字符串中第三個(gè)漢字找到第四層的分支結(jié)點(diǎn);依此類(lèi)推,直到該字符串的末尾,末尾所在的結(jié)點(diǎn)記錄了該字符串的編號(hào)id,返回該編號(hào)id號(hào)則完成了字符串的精確檢索;若多叉樹(shù)的分支無(wú)法到達(dá)該字符串的末尾,則證明該字符串不在多叉樹(shù)中;b)對(duì)于英文字符串第一步,根據(jù)字符串中的第一個(gè)字母在字母表中的序號(hào)找到該字母在多叉樹(shù)中第二層的分支結(jié)點(diǎn);第二步,沿著該分支往下,用二分查找的方法,根據(jù)字符串中第二個(gè)字母在字母表中的序號(hào)找到該字母在多叉樹(shù)中第三層的分支結(jié)點(diǎn);依此類(lèi)推,直到字符串的末尾,末尾所在的結(jié)點(diǎn)記錄了該字符串的編號(hào)id,返回該編號(hào)id號(hào)則完成了字符串的精確檢索;若多叉樹(shù)的分支無(wú)法到達(dá)該字符串的末尾,則證明該字符串不在多叉樹(shù)中;如,要在插入了(分詞,互聯(lián)網(wǎng),搜索,搜尋)四個(gè)字符串的多叉樹(shù)中,查找“互聯(lián)網(wǎng)”這個(gè)字符串,步驟為(1)用“互”的GB2312編碼減去“阿”的GB2312編碼,若差值為a,則找到多叉樹(shù)第二層的第(a+1)個(gè)分支結(jié)點(diǎn),這個(gè)分支結(jié)點(diǎn)中存儲(chǔ)了“互”的下層結(jié)點(diǎn)的指針。
(2)在“互”的下層結(jié)點(diǎn)中用二分查找法快速查找“聯(lián)”所在的分支結(jié)點(diǎn),其中存儲(chǔ)了“聯(lián)”的下層結(jié)點(diǎn)的指針。
(3)同理在“聯(lián)”的下層結(jié)點(diǎn)中用二分查找法快速查找“網(wǎng)”所在的結(jié)點(diǎn),返回字符串“互聯(lián)網(wǎng)”的編號(hào)id,查找成功。
這里“互聯(lián)網(wǎng)”這個(gè)字符串的標(biāo)識(shí)號(hào)為2,因?yàn)樗窍蚨嗖鏄?shù)中插入的第二個(gè)字符串,若外部沒(méi)有指定,在標(biāo)識(shí)號(hào)由程序自動(dòng)從1開(kāi)始分配。
5.調(diào)用模糊檢索字符串的程序,具體過(guò)程如下字符串的模糊檢索是指給定字符串的前綴或后綴,在多叉樹(shù)中檢索出所有包含該前綴或后綴的字符串;對(duì)前綴字符串的檢索,采用與精確檢索相同的方式,從多叉樹(shù)的根結(jié)點(diǎn)開(kāi)始逐層找到該字符串前綴所在分支上的結(jié)點(diǎn),直到前綴的末尾,找到從末尾結(jié)點(diǎn)開(kāi)始的所有的下層分支,這些下層分支表示的是該前綴的后續(xù)字符串,該前綴字符串分別與這些下層分支表示的后續(xù)字符串組合即為模糊檢索的結(jié)果;若多叉樹(shù)的分支無(wú)法到達(dá)該前綴字符串的末尾,則檢索失??;對(duì)后綴字符串的檢索,則反方向從多叉樹(shù)的底層結(jié)點(diǎn)開(kāi)始,向上逐層找到與后綴字符串中的字符相對(duì)應(yīng)的分支結(jié)點(diǎn),這里也是從后綴字符串的末尾字符開(kāi)始往前查找,直到后綴的最前端,找到最前端字符對(duì)應(yīng)結(jié)點(diǎn)的所有上層分支,這些上層分支表示的是該后綴前面的字符串,這些上層分支分別串接該后綴字符串即為模糊檢索的結(jié)果;若向上查找時(shí),多叉樹(shù)的分支無(wú)法到達(dá)該后綴字符串的最前端,則檢索失?。蝗?,在插入了(分詞,互聯(lián)網(wǎng),搜索,搜尋)四個(gè)字符串的多叉樹(shù)中進(jìn)行模糊檢索,步驟為(1)假如前綴字符串為“搜”,則先用精確檢索同樣的方法找到“搜”所在的分支結(jié)點(diǎn),以及“搜”所有的下層分支,把“搜”分別與這些分支結(jié)點(diǎn)串接,就得到了“搜索”和“搜尋”兩個(gè)字符串。
(2)假如后綴字符串為“詞”,則從多叉樹(shù)的底層結(jié)點(diǎn)開(kāi)始找到所有包含“詞”的分支,以及“詞”所有的上層分支,把這些分支與“詞”串接就得到了“分詞”這個(gè)字符串。
(3)假如前綴字符串為“互”,后綴字符串為“網(wǎng)”,則先用精確檢索同樣的方法找到“互”所在的分支結(jié)點(diǎn),以及“互”所有的下層分支,在這些下層分支中從底層結(jié)點(diǎn)開(kāi)始,找到所有包含“網(wǎng)”的分支,從“互”所在的結(jié)點(diǎn)出發(fā)到“網(wǎng)”所在的結(jié)點(diǎn)的路徑對(duì)應(yīng)的字符串即為結(jié)果,就找到了“互聯(lián)網(wǎng)”。
第六步進(jìn)行清理工作,調(diào)用從多叉樹(shù)中刪除字符串的程序,具體過(guò)程如下第一步,按照精確檢索的方法找到待刪除的字符串在多叉樹(shù)中的分支;第二步,若字符串的末尾所在的分支結(jié)點(diǎn)是多叉樹(shù)的底層結(jié)點(diǎn),即該字符串沒(méi)有后續(xù)字符,則刪除末尾結(jié)點(diǎn)中該字符串的編號(hào)id,并釋放末尾結(jié)點(diǎn)占用的存儲(chǔ)空間;若字符串的末尾所在的分支結(jié)點(diǎn)不是多叉樹(shù)的底層結(jié)點(diǎn),即末尾結(jié)點(diǎn)還有下層分支,則僅刪除末尾結(jié)點(diǎn)中該字符串的編號(hào)id,其他不變;刪除成功。
如,在插入了(分詞,互聯(lián)網(wǎng),搜索,搜尋)四個(gè)字符串的多叉樹(shù)中,刪除字符串“搜索”的步驟為(1)按照精確檢索的方法在多叉樹(shù)中查找“搜索”,找到末尾結(jié)點(diǎn)“索”;(2)刪除末尾結(jié)點(diǎn)中“搜索”的編號(hào)id,把其占用的內(nèi)存資源完全釋放掉。
權(quán)利要求
1.一種用于檢索字符串的方法,其特征在于1)以多叉樹(shù)的存儲(chǔ)方式來(lái)記錄字符串的字符序列結(jié)構(gòu)信息,同時(shí)對(duì)多叉樹(shù)結(jié)點(diǎn)的內(nèi)存分配進(jìn)行了分層管理用多叉樹(shù)的形式來(lái)存儲(chǔ)字符串,樹(shù)的第一層為根結(jié)點(diǎn),接下來(lái)的每一層依次表示該字符串中的一個(gè)字符,每個(gè)樹(shù)結(jié)點(diǎn)存儲(chǔ)了當(dāng)前字符,從根結(jié)點(diǎn)到該結(jié)點(diǎn)所形成的字符串的編號(hào)id和后繼結(jié)點(diǎn)的指針,該編號(hào)id用于標(biāo)識(shí)一個(gè)唯一的字符串,程序中默認(rèn)從1開(kāi)始,按序分配,或由用戶(hù)指定;對(duì)中文字符串來(lái)說(shuō),多叉樹(shù)的第一層為根結(jié)點(diǎn),第二層則按照字符串第一個(gè)漢字的GB2312編碼來(lái)標(biāo)識(shí),共有三千多個(gè)分支,分別表示三千多個(gè)漢字,最左邊分支的GB2312編碼最小,表示漢字“阿”,其他的漢字就利用它與“阿”的GB2312編碼的差值來(lái)索引;第三層表示字符串中的第二個(gè)漢字,由于漢語(yǔ)詞匯固定的組合和搭配形式,并不是任意兩個(gè)漢字都可以組成一個(gè)詞語(yǔ),每個(gè)漢字后面可能出現(xiàn)的漢字是有限的,而不是漢字的全集;所以從第三層開(kāi)始,如果每個(gè)漢字結(jié)點(diǎn)下一層可能出現(xiàn)的后續(xù)漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,就用后繼漢字與“阿”的GB2312編碼的差值來(lái)索引;否則,如果每個(gè)漢字結(jié)點(diǎn)下一層可能出現(xiàn)的后續(xù)漢字的數(shù)目小于不同漢字?jǐn)?shù)目的一半,就只存儲(chǔ)漢字結(jié)點(diǎn)下一層可能出現(xiàn)的后續(xù)漢字的信息;依此類(lèi)推,這樣就可以大大節(jié)省存儲(chǔ)空間;對(duì)英文字符串來(lái)說(shuō),多叉樹(shù)的第一層也為根結(jié)點(diǎn),第二層表示字符串的第一個(gè)字母,共有26個(gè)分支,分別對(duì)應(yīng)26個(gè)英文字母,由于英文字母的個(gè)數(shù)少,不會(huì)占用很大的存儲(chǔ)空間,因此多叉樹(shù)第二層以下的各層也采用同樣的方式來(lái)依次表示字符串中的各個(gè)字母,即每一層都包括26個(gè)分支;2)將字符串插入到多叉樹(shù)中a)對(duì)于中文字符串第一步,以字符串中的第一個(gè)漢字的GB2312編碼與“阿”的GB2312編碼的差值索引到多叉樹(shù)第二層的分支結(jié)點(diǎn),這個(gè)分支結(jié)點(diǎn)存儲(chǔ)的是其下層結(jié)點(diǎn),也就是字符串的第二個(gè)漢字的信息的指針;第二步,如果第一個(gè)漢字可能的后繼漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,則后繼漢字的GB2312編碼與“阿”的GB2312編碼的差值索引到第三層的分支結(jié)點(diǎn);否則為第一個(gè)漢字結(jié)點(diǎn)預(yù)分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元(這里為了避免每次添加字符串時(shí)都要重新分配,每次分配時(shí)將一次性預(yù)分配16個(gè)下層結(jié)點(diǎn)單元);如果已經(jīng)為該分支結(jié)點(diǎn)分配了存儲(chǔ)下層(第三層)結(jié)點(diǎn)的空間,則給第二個(gè)漢字分配其中的一個(gè)單元;如果上一次分配的16個(gè)單元已經(jīng)用完,則重新再分配16個(gè);第三層結(jié)點(diǎn)單元中存儲(chǔ)了第二個(gè)漢字,和當(dāng)前已添加的字符串的編號(hào)id號(hào)以及第三個(gè)漢字的信息的指針;第三步,同理,如果第二個(gè)漢字可能的后繼漢字的數(shù)目大于等于不同漢字?jǐn)?shù)目的一半,則后繼漢字的GB2312編碼與“阿”的GB2312編碼的差值索引到第四層的分支結(jié)點(diǎn);否則給第三層結(jié)點(diǎn)預(yù)分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元,存儲(chǔ)第三個(gè)漢字和當(dāng)前已添加的字符串的編號(hào)id號(hào)以及第四個(gè)漢字的信息的指針;依此類(lèi)推,依次為每一個(gè)結(jié)點(diǎn)分配其下層結(jié)點(diǎn)的存儲(chǔ)空間,直到字符串的末尾,此時(shí)該字符串就添加到多叉樹(shù)中了;b)對(duì)于英文字符串第一步,根據(jù)字符串中的第一個(gè)字母在字母表中的序號(hào)索引到多叉樹(shù)第二層的分支結(jié)點(diǎn),這個(gè)分支結(jié)點(diǎn)存儲(chǔ)的是第三層結(jié)點(diǎn),也就是字符串的第二個(gè)字母的信息的指針;第二步,同理根據(jù)字符串中第二個(gè)字母在字母表中的序號(hào)索引到多叉樹(shù)第三層的分支結(jié)點(diǎn);依此類(lèi)推,直到字符串的末尾,此時(shí)該字符串就添加到多叉樹(shù)中了;3)字符串集的壓縮由于建立多叉樹(shù)時(shí),有些層可能存在多個(gè)分支,比如中文的多叉樹(shù)的第二層就有三千多個(gè)分支,對(duì)一個(gè)字符串集而言有些分支可能并沒(méi)有用到;而且分支較少的層每次都是為結(jié)點(diǎn)預(yù)分配16個(gè)下層結(jié)點(diǎn)存儲(chǔ)單元,這樣有些分配出去的空間可能并沒(méi)有使用;因此先把多叉樹(shù)寫(xiě)入外存,然后從外存中讀入內(nèi)存時(shí),釋放多叉樹(shù)中這些空的不用的單元,只把有數(shù)據(jù)的單元按照原來(lái)的結(jié)構(gòu)讀到內(nèi)存中,這樣就大大實(shí)現(xiàn)了字符串集的壓縮;4)在多叉樹(shù)中精確檢索字符串a(chǎn))對(duì)于中文字符串第一步,根據(jù)字符串中的第一個(gè)漢字的GB2312編碼與“阿”的GB2312編碼的差值找到該漢字在多叉樹(shù)中第二層的分支結(jié)點(diǎn);第二步,沿著該分支往下,根據(jù)待檢索的字符串的第二個(gè)漢字找到第三層的分支結(jié)點(diǎn);再?gòu)牡谌龑拥姆种ЫY(jié)點(diǎn)出發(fā),根據(jù)待檢索字符串中第三個(gè)漢字找到第四層的分支結(jié)點(diǎn);依此類(lèi)推,直到該字符串的末尾,末尾所在的結(jié)點(diǎn)記錄了該字符串的編號(hào)id,返回該編號(hào)id號(hào)則完成了字符串的精確檢索;若多叉樹(shù)的分支無(wú)法到達(dá)該字符串的末尾,則證明該字符串不在多叉樹(shù)中;b)對(duì)于英文字符串第一步,根據(jù)字符串中的第一個(gè)字母在字母表中的序號(hào)找到該字母在多叉樹(shù)中第二層的分支結(jié)點(diǎn);第二步,沿著該分支往下,根據(jù)字符串中第二個(gè)字母在字母表中的序號(hào)找到該字母在多叉樹(shù)中第三層的分支結(jié)點(diǎn);依此類(lèi)推,直到字符串的末尾,末尾所在的結(jié)點(diǎn)記錄了該字符串的編號(hào)id,返回該編號(hào)id號(hào)則完成了字符串的精確檢索;若多叉樹(shù)的分支無(wú)法到達(dá)該字符串的末尾,則證明該字符串不在多叉樹(shù)中;5)在多叉樹(shù)中模糊檢索字符串字符串的模糊檢索是指給定字符串的前綴或后綴,在多叉樹(shù)中檢索出所有包含該前綴或后綴的字符串;對(duì)前綴字符串的檢索,采用與精確檢索相同的方式,從多叉樹(shù)的根結(jié)點(diǎn)開(kāi)始逐層找到該字符串前綴所在分支上的結(jié)點(diǎn),直到前綴的末尾,找到從末尾結(jié)點(diǎn)開(kāi)始的所有的下層分支,這些下層分支表示的是該前綴的后續(xù)字符串,該前綴字符串分別與這些下層分支表示的后續(xù)字符串組合即為模糊檢索的結(jié)果;若多叉樹(shù)的分支無(wú)法到達(dá)該前綴字符串的末尾,則檢索失敗;對(duì)后綴字符串的檢索,則反方向從多叉樹(shù)的底層結(jié)點(diǎn)開(kāi)始,向上逐層找到與后綴字符串中的字符相對(duì)應(yīng)的分支結(jié)點(diǎn),這里也是從后綴字符串的末尾字符開(kāi)始往前查找,直到后綴的最前端,找到最前端字符對(duì)應(yīng)結(jié)點(diǎn)的所有上層分支,這些上層分支表示的是該后綴前面的字符串,這些上層分支分別串接該后綴字符串即為模糊檢索的結(jié)果;若向上查找時(shí),多叉樹(shù)的分支無(wú)法到達(dá)該后綴字符串的最前端,則檢索失敗;6)從多叉樹(shù)中刪除字符串第一步,按照精確檢索的方法找到待刪除的字符串在多叉樹(shù)中的分支;第二步,若字符串的末尾所在的分支結(jié)點(diǎn)是多叉樹(shù)的底層結(jié)點(diǎn),即該字符串沒(méi)有后續(xù)字符,則刪除末尾結(jié)點(diǎn)中該字符串的編號(hào)id,并釋放末尾結(jié)點(diǎn)占用的存儲(chǔ)空間;若字符串的末尾所在的分支結(jié)點(diǎn)不是多叉樹(shù)的底層結(jié)點(diǎn),即末尾結(jié)點(diǎn)還有下層分支,則僅刪除末尾結(jié)點(diǎn)中該字符串的編號(hào)id,其他不變;刪除成功。
全文摘要
本發(fā)明公開(kāi)了一種用于檢索字符串的方法。相對(duì)于傳統(tǒng)索引技術(shù)如Hash或Btree或AVL-樹(shù)等,本發(fā)明以多叉樹(shù)的存儲(chǔ)方式來(lái)記錄字符串的字符序列結(jié)構(gòu)信息,并在檢索方法中利用了這些信息,能夠高效地實(shí)現(xiàn)對(duì)字符串檢索,尤其適合在大規(guī)模字符串集合環(huán)境下字符串的精確快速查找和前綴、后綴等模糊查找。同時(shí)對(duì)多叉樹(shù)結(jié)點(diǎn)的內(nèi)存分配進(jìn)行了分層管理,并對(duì)最后生成的多叉樹(shù)進(jìn)行了適度的壓縮,有效的節(jié)省了內(nèi)存資源,克服了傳統(tǒng)檢索字符串方法所存在的檢索效率低、或者檢索效率雖高但是過(guò)分消耗內(nèi)存資源、不支持模糊查詢(xún)等不足,是一種既高效又實(shí)用的字符串檢索方法。
文檔編號(hào)G06F17/30GK1889080SQ200610052710
公開(kāi)日2007年1月3日 申請(qǐng)日期2006年7月31日 優(yōu)先權(quán)日2006年7月31日
發(fā)明者陳純, 卜佳俊, 劉康苗, 陳偉, 趙夢(mèng), 潘照明 申請(qǐng)人:浙江大學(xué)