生活随笔
收集整理的這篇文章主要介紹了
一摞烙饼的排序(搜索树)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前兩個星期就看編程之美的一摞烙餅排序問題,剛開始看其代碼沒看懂什么意思,后來看了人家的博客才知道是怎么回事了,自己寫了一遍其代碼做各種各樣的測試,嚇我一跳,一個剪枝操作竟然省了那么多的時間,想起上一道題的將帥問題,頓時讓我領悟到這編程之美的書籍,題目不但有意思,其代碼真的優雅和美,好了接下來看這個烙餅排序問題。
題目:
星期五的晚上,一幫同事在希格瑪大廈附近的“硬盤酒吧”多喝了幾杯。程序員多喝了幾杯之后談什么呢?自然是算法問題。有個同事說:“我以前在餐館打工,顧客經常點非常多的烙餅。店里的餅大小不一,我習慣在到達顧客飯桌前,把一摞餅按照大小次序擺好——小的在上面,大的在下面。由于我一只手托著盤子,只好用另一只手,一次抓住最上面的幾塊餅,把它們上下顛倒個個兒,反復幾次之后,這摞烙餅就排好序了。我后來想,這實際上是個有趣的排序問題:假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最后大小有序的結果呢?”
你能否寫出一個程序,對于n塊大小不一的烙餅,輸出最優化的翻餅過程呢?
編程之美的代碼:
class CprefixSorting
{
public:CprefixSorting(){mCakecnt=
0;mMaxSwap=
0;};
virtual ~CprefixSorting(){
if(mCakeArray!=NULL)
delete mCakeArray;
if(mReverseCakeArraySwap!=NULL)
delete mReverseCakeArraySwap;
if(mSwapArray!=NULL)
delete mSwapArray;
if(mReverseCakeArray!=NULL)
delete mReverseCakeArray;};
int UpperBound(
int mCakecnt){
return 2*(mCakecnt-
1);}
int LowerBound(
int *reverseCake,
int cakeCnt ){
int t;
int reverseCnt=
0;
for(
int i=
1;i<cakeCnt;i++){t=reverseCake[i]-reverseCake[i-
1];
if(t==
1||t==-
1){}
else{reverseCnt++;}}
return reverseCnt;}
bool IsSorted(
int* reverseCakeArray,
int cakeCnt ){
for(
int i=
1;i<cakeCnt;i++){
if(reverseCakeArray[i-
1]>reverseCakeArray[i]){
return false;}}
return true;}
void Init(
int * cakeArray,
int cakeCnt){assert(cakeArray!=NULL);assert(cakeCnt>
0);mCakecnt=cakeCnt;mCakeArray=
new int[mCakecnt];assert(mCakeArray!=NULL);
for(
int i=
0;i<mCakecnt;i++){mCakeArray[i]=cakeArray[i];}mMaxSwap=UpperBound(mCakecnt);mSwapArray=
new int[mMaxSwap+
1];assert(mSwapArray!=NULL);mReverseCakeArray=
new int[mCakecnt];
for(
int i=
0;i<mCakecnt;i++){mReverseCakeArray[i]=mCakeArray[i];}mReverseCakeArraySwap=
new int[mMaxSwap];}
void Search(
int step){
int lowCnt;mSearch++;lowCnt=LowerBound(mReverseCakeArray,mCakecnt);
if(step+lowCnt>mMaxSwap||step>=mMaxSwap){
return;}
if(IsSorted(mReverseCakeArray,mCakecnt)){
if(step<mMaxSwap){mMaxSwap=step;
for(
int i=
0;i<mCakecnt;i++){mSwapArray[i]=mReverseCakeArraySwap[i];}}
return;}
for(
int i=
1;i<mCakecnt;i++){Reserver(
0,i);mReverseCakeArraySwap[step]=i;Search(step+
1);
Reserver(
0,i);}}
void Reserver(
int begin,
int end){
for(
int i=begin,j=end;i<j;i++,j--){
int t=mReverseCakeArray[i];mReverseCakeArray[i]=mReverseCakeArray[j];mReverseCakeArray[j]=t;}}
void Run(
int *cakeArray,
int cakeCnt){Init(cakeArray,cakeCnt);mSearch=
0;Search(
0);}
void Output(){
for(
int i=
0;i<mMaxSwap;i++){
printf(
"%d ",mSwapArray[i]);}
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
int main()
{CprefixSorting test;
int aa[
3]={
3,
1,
2};test.Run(aa,
3);test.Output();
}
運行結果:
2 1
|Search Times : 19
Total Swap times= 2
剪枝操作的關鍵就是看其上界和下界兩個邊界,如果下界越大,上界越小其運行效率越高,測試:
修改上界值較大(調整更大的上界):
//最大的上界
int UpperBound(int mCakecnt)
{
return 2*mCakecnt;
}
運行結果
2 1
|Search Times : 31
修改下界值較小(調整更小的下界)
lowCnt=-1;
運行結果:
2 1
|Search Times : 31
Total Swap times= 2
從結果可以看出,上界和下界的數值對其所搜次數的影響,這里如果你傳入的數組數目越多,影響會更明顯的,因為這里涉及了一種搜索樹的結構,該樹深度越高,樹的節點就越多,越密集那么消耗的時間的次數就越高,這時利用分支限界法(即巧妙的利用邊界才停止其往下搜索),控制搜索深度,這樣就可以大大的減少時間效率了,如圖:
參考博客:
http://blog.csdn.net/zuiaituantuan/article/details/6056601
總結
以上是生活随笔為你收集整理的一摞烙饼的排序(搜索树)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。