一摞烙餅的排序 搜尋樹

2021-06-30 16:33:36 字數 2882 閱讀 8251

前兩個星期就看程式設計之美的一摞烙餅排序問題,剛開始看其**沒看懂什麼意思,後來看了人家的部落格才知道是怎麼回事了,自己寫了一遍其**做各種各樣的測試,嚇我一跳,乙個剪枝操作竟然省了那麼多的時間,想起上一道題的將帥問題,頓時讓我領悟到這程式設計之美的書籍,題目不但有意思,其**真的優雅和美,好了接下來看這個烙餅排序問題。

題目:

星期五的晚上,一幫同事在希格瑪大廈附近的「硬碟酒吧」多喝了幾杯。程式設計師多喝了幾杯之後談什麼呢?自然是演算法問題。有個同事說:「我以前在餐館打工,顧客經常點非常多的烙餅。店裡的餅大小不一,我習慣在到達顧客飯桌前,把一摞餅按照大小次序擺好——小的在上面,大的在下面。由於我乙隻手托著盤子,只好用另乙隻手,一次抓住最上面的幾塊餅,把它們上下顛倒個個兒,反覆幾次之後,這摞烙餅就排好序了。我後來想,這實際上是個有趣的排序問題:假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最後大小有序的結果呢?」

你能否寫出乙個程式,對於n塊大小不一的烙餅,輸出最優化的翻餅過程呢?

程式設計之美的**:

class cprefixsorting

; //釋放陣列記憶體空間

virtual ~cprefixsorting()

;//最大的上界

int upperbound(int mcakecnt)

//最小的下界

int lowerbound(int *reversecake,int cakecnt )

else

}return reversecnt;

}//判斷烙餅是否排好序

bool issorted(int* reversecakearray,int cakecnt )

}return

true;

}//初始化資訊

void init(int * cakearray,int cakecnt)

//排序的核心函式

void search(int step)

if(issorted(mreversecakearray,mcakecnt))

//遍歷遞迴進行翻轉

for(int i=1;i//翻轉

reserver(0,i);

//儲存當前搜尋值對應翻轉月餅的索引

mreversecakearrayswap[step]=i;

//搜尋下乙個節點

search(step+1);

// printf("step:%d\n",step+1);

// for(int j=0;j//

// printf("\n");

//返回上一層

reserver(0,i);}}

//翻轉烙餅資訊

void reserver(int begin,int end)

}//執行函式介面

void run(int *cakearray,int cakecnt)

void output()

//輸出搜尋次數

printf("\n |search times : %d\n",msearch);

//輸出需翻轉最少的次數

printf("total swap times= %d\n",mmaxswap);

}private:

int * mcakearray;//儲存對應索引烙餅大小資訊陣列

int mcakecnt;//烙餅的個數

int mmaxswap;//烙餅的最大交換次數

int * mreversecakearray;//儲存當前翻轉後對應索引烙餅的大小資訊

int msearch; //當前搜尋次數

int * mreversecakearrayswap;//儲存當前對應搜尋值的被翻轉的烙餅索引

int * mswaparray;//儲存已經完全排好序的所有對應搜尋值得被烙餅索引

};#endif // cprefixsorting_h

int main()

; test.run(aa,3);

test.output();

}

執行結果:2 1

|search times : 19

total swap times= 2

剪枝操作的關鍵就是看其上界和下界兩個邊界,如果下界越大,上界越小其執行效率越高,測試:

修改上界值較大(調整更大的上界):

//最大的上界

int upperbound(int mcakecnt)

執行結果

2 1

|search times : 31

修改下界值較小(調整更小的下界)

lowcnt=-1;

執行結果:

2 1

|search times : 31

total swap times= 2

從結果可以看出,上界和下界的數值對其所搜次數的影響,這裡如果你傳入的陣列數目越多,影響會更明顯的,因為這裡涉及了一種搜尋樹的結構,該樹深度越高,樹的節點就越多,越密集那麼消耗的時間的次數就越高,這時利用分支限界法(即巧妙的利用邊界才停止其往下搜尋),控制搜尋深度,這樣就可以大大的減少時間效率了,如圖:

參考部落格:

一摞烙餅的排序(0621)

每乙個演算法都值得好好地分析 問題 假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最後大小有序的結果呢?這個排序問題非常有意思,首先我們要弄清楚解決問題的關鍵操作 單手每次抓幾塊餅,全部顛倒 每次我們只能選擇最上方的一堆餅,一起翻轉。而不能一張張地直接抽出來,然後進行插入,也不能交換任意兩塊餅子...

1 3 一摞烙餅的排序

一摞亂序擺放的烙餅,每次只能抓取最上面幾塊烙餅並翻轉,多次翻轉後能夠實現烙餅的從小到大 從上往下 的有序擺放。問題分析 這裡我們使用回溯法解決這個問題。直接用回溯法效率是低下的,因此要進行剪枝。這裡的剪枝條件是利用翻轉次數的上界和下界完成的。上界 4,2,1,5,3 5,1,2,4,3 3,4,2,...

1 3 一摞烙餅的排序

假設有n塊大小不一樣的烙餅,那麼最少要翻動幾次,才能達到最終有序的結果。思路 每次找到最大的然後從將最大的以及最大的上面的反轉,這時候最大的在最上面,然後將整個反轉,最大的就在最下面了。然後再對除了最下面的n 1個烙餅進行上述的操作,知道全部的烙餅有序。例如 13524 53124 42135 cl...