国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

Dancing Link在數(shù)獨(dú)求解中的應(yīng)用

2019-09-09 05:50:32柯建平陳昱宇
消費(fèi)導(dǎo)刊 2019年33期
關(guān)鍵詞:鏈表十字指針

柯建平 陳昱宇

泉州市兒童醫(yī)院

“數(shù)獨(dú)”(sudoku)一詞來自日語,意思是“單獨(dú)的數(shù)字”或“只出現(xiàn)一次的數(shù)字?!备爬▉碚f,它就是一種填數(shù)字游戲。數(shù)獨(dú)作為人類的一種經(jīng)典的益智游戲,它的計(jì)算機(jī)解決對(duì)于人們對(duì)計(jì)算機(jī)能做什么,可以做到怎樣有很大的啟發(fā)意義,本文從搜索的角度,也是最基本的一種方法,但是對(duì)其程序?qū)崿F(xiàn)的一個(gè)較大的優(yōu)化,使用Dancing Link 技術(shù),十字鏈表的使用和啟發(fā)式的搜索方法,大大提高了程序的運(yùn)行效率。

雙向鏈表又叫雙鏈表,是鏈表的一種。雙向鏈表的存儲(chǔ)結(jié)構(gòu)往往是有一個(gè)空的結(jié)點(diǎn)來表示頭指針。然后每一個(gè)結(jié)點(diǎn)有一個(gè)直接前驅(qū)值域和一個(gè)直接后驅(qū)值域。

如果是十字鏈表的話,結(jié)點(diǎn)中指針的值域會(huì)變成四個(gè)。在單向鏈表中刪除一個(gè)結(jié)點(diǎn)是非常麻煩,而且低效的。雙向鏈表有著優(yōu)美的結(jié)構(gòu),可以方便的刪除任意一個(gè)結(jié)點(diǎn)。公式如下:L[R[x]] = L[x]; R[L[x]] = R[x];其中x指的是編號(hào),LR來記錄左右方向的雙向鏈表。

這邊用的靜態(tài)數(shù)組的實(shí)現(xiàn)方式,同指針其實(shí)是一樣的,如果你實(shí)現(xiàn)過雙向鏈表的話,那你一定會(huì)覺得很熟悉。雙向鏈表的結(jié)點(diǎn)恢復(fù),請(qǐng)看公式如下:L[R[x]] = x; R[L[x]]= x; 其中x指的是編號(hào),LR來記錄左右方向的雙向鏈表[4]。

Dancing Links的核心思想就是對(duì)于稀疏矩陣采用雙向十字鏈表存儲(chǔ)的搜索[5]。對(duì)于雙向鏈表結(jié)點(diǎn)刪除和恢復(fù)操作,大家在平時(shí)只想怎樣刪除,而從沒想過把刪除掉的結(jié)點(diǎn)恢復(fù)。有些人可能覺得這是不好的,如果沒有把分配出去的內(nèi)存刪除掉,很容易造成內(nèi)存泄漏。但這里,我們卻需要這樣做。我們?cè)阪湵碇袆h除結(jié)點(diǎn),只做標(biāo)記,不做真正的清空內(nèi)存操作。這樣我們后來便可以用(2) 進(jìn)行恢復(fù)操作了。(2)才是Dancing Links的核心.接下來我們來看一個(gè)經(jīng)典的搜索問題,精確覆蓋問題:

給定一個(gè)由0和1組成的矩陣,是否能找到一個(gè)行的集合,使得集合中每一列都恰好包含一個(gè)1?例如,下面這個(gè)矩陣

圖1-1 矩陣

就包含了這樣一個(gè)集合(第1,4,5行)。我們把列想象成全集的一些元素,而行看作全集的一些子集;或者我們可以把行想象成全集的一些元素,而把列看作全集的一些子集;那么這個(gè)問題就是要求尋找一批元素,它們與每個(gè)子集恰好有一個(gè)交點(diǎn)。這是一個(gè)NP問題。自然,作為首選的算法就是回溯了。下面給出算法過程:

上述代碼和普通的搜索本質(zhì)上是相同的,但看上去不太一樣我在下面將會(huì)給出源碼。這段代碼的算法框架已經(jīng)固定了 ,幾乎沒有可優(yōu)化的余地,就算用非遞歸來優(yōu)化也不會(huì)得到多少的效率提升,反而會(huì)使編碼復(fù)雜度和出錯(cuò)率大大增加。如何去實(shí)現(xiàn)代碼行(1) (2) (3) (4) 是優(yōu)化的關(guān)鍵,也是Dancing Links發(fā)揮其作用的地方。我們可以直觀的去想到一個(gè)簡(jiǎn)單的方法:

Step (1):把矩陣進(jìn)行掃描,選出未做刪除標(biāo)記的列中元素個(gè)數(shù)最少的。

Step (2): 對(duì)當(dāng)前列和行做標(biāo)記,標(biāo)記其已經(jīng)刪除。

Step (3): 同Step (2)

Step (4): 把相應(yīng)的標(biāo)記刪除。

Step (5): 同Step (4)

然而,這個(gè)方法很明顯是非常低效的,做標(biāo)記是快速的。但是相應(yīng)的帶來的問題,是查找的時(shí)候會(huì)變得非常慢。復(fù)雜度始終是O(n)(n為矩陣大小)。在step (1) (2) (3) (4)(5) 中我們都用到了查找操作,所以我們不能忽視查找的復(fù)雜度。在這個(gè)實(shí)現(xiàn)方式中,把查找的效率提升多少,整個(gè)程序便可提升多少。

下面我們來細(xì)細(xì)展開Dancing Links的雙向十字鏈表。

由于經(jīng)常要用到2級(jí)指針,如果用真正的指針實(shí)現(xiàn)的話代碼可讀性很差,代碼也不好看,所以我用靜態(tài)數(shù)組實(shí)現(xiàn),這樣既可方便的建立矩陣,也可以加快運(yùn)行速度。對(duì)每一個(gè)對(duì)象,記錄如下幾個(gè)信息:

L[x], R[x], U[x], D[x], C[x];

雙向十字鏈表用LRUD來記錄,LR來記錄左右方向的雙向鏈表,UD來記錄上下方向的雙向鏈表。 head 指向總的頭指針,head通過LR來貫穿的列指針頭。 每一列都有列指針頭。C[x]是指向其列指針頭的地址。行指針頭可有可無,在我的實(shí)現(xiàn)中沒有顯示的表示出來。在某些題目中,加個(gè)行指針頭還是很有必要的。

另外,開兩個(gè)數(shù)組cnt[x], ans[x];cnt[x]記錄列鏈表中結(jié)點(diǎn)的總數(shù)。ans[x]用來記錄搜索結(jié)果。

本設(shè)計(jì)主要研究Dancing Links算法與實(shí)現(xiàn)。本文設(shè)計(jì)了精確覆蓋模型的建立模型建立并編程實(shí)現(xiàn),通過暴力搜索算法的比較,得出Dancing Links搜索時(shí)間上的明顯的優(yōu)勢(shì)。Dancing Links與暴力搜索的搜索時(shí)間相差在100倍以上。

猜你喜歡
鏈表十字指針
張竹君與中國(guó)赤十字會(huì)
文史春秋(2022年4期)2022-06-16 07:12:52
十字棋
基于二進(jìn)制鏈表的粗糙集屬性約簡(jiǎn)
偷指針的人
跟麥咭學(xué)編程
2018車企進(jìn)階十字訣
汽車觀察(2018年12期)2018-12-26 01:05:24
基于鏈表多分支路徑樹的云存儲(chǔ)數(shù)據(jù)完整性驗(yàn)證機(jī)制
巧用十字相乘法解題
為什么表的指針都按照順時(shí)針方向轉(zhuǎn)動(dòng)
基于改進(jìn)Hough變換和BP網(wǎng)絡(luò)的指針儀表識(shí)別
韩城市| 宜良县| 中江县| 呼伦贝尔市| 商都县| 万安县| 噶尔县| 龙山县| 屏山县| 遂平县| 龙口市| 宜兰市| 江门市| 准格尔旗| 宜川县| 永丰县| 彭阳县| 慈溪市| 万载县| 黎平县| 定边县| 静宁县| 涞源县| 平度市| 措美县| 名山县| 荥阳市| 新密市| 龙海市| 泰顺县| 疏附县| 湘潭县| 石台县| 乐亭县| 万州区| 烟台市| 营山县| 邢台市| 永清县| 吉林市| 岳西县|