问题描述:

编程之美1.3 一摞烙饼的排序

这是前缀翻转排序问题,书上的内容这里不详述,给个电子版下载地址

本文源码编译环境:codeblock with gcc

书上给的源码有点小错误,编译通不过,这里是修改过后的原始代码:

  1 /****************************************************************/
  2 //
  3 // 烙饼排序实现
  4 //
  5 /****************************************************************/
  6 #include <cstdio>
  7 #include<cassert>
  8 class CPrefixSorting
  9 {
 10 public:
 11 
 12     CPrefixSorting()    
 13     {
 14         m_nCakeCnt = 0;
 15         m_nMaxSwap = 0;
 16         m_CakeArray = NULL;
 17         m_SwapArray = NULL;
 18         m_ReverseCakeArray = NULL;
 19         m_ReverseCakeArraySwap = NULL;
 20     }
 21 
 22     ~CPrefixSorting()
 23     {printf("1");
 24         if( m_CakeArray != NULL )
 25         {
 26             delete []m_CakeArray;  
 27         }
 28         if( m_SwapArray != NULL )
 29         {
 30             delete []m_SwapArray;  
 31         }
 32         if( m_ReverseCakeArray != NULL )
 33         {
 34             delete []m_ReverseCakeArray;  
 35         }
 36         if( m_ReverseCakeArraySwap != NULL )
 37         {
 38             delete []m_ReverseCakeArraySwap;  
 39         }
 40         printf("2");
 41     }
 42 
 43     //
 44     // 计算烙饼翻转信息
 45     // @param
 46     // pCakeArray    存储烙饼索引数组
 47     // nCakeCnt    烙饼个数
 48     //
 49     void Run(int* pCakeArray, int nCakeCnt)
 50     {
 51         Init(pCakeArray, nCakeCnt);
 52 
 53         m_nSearch = 0;
 54         Search(0);
 55     }
 56 
 57     //
 58     // 输出烙饼具体翻转的次数
 59     //
 60     void Output()
 61     {
 62         for(int i = 0; i < m_nMaxSwap; i++)
 63         {
 64             printf("%d ", m_SwapArray[i]);
 65         }
 66 
 67         printf("\n |Search Times| : %d\n", m_nSearch);
 68         printf("Total Swap times = %d\n", m_nMaxSwap);
 69     }
 70 
 71 private:
 72 
 73     //
 74     // 初始化数组信息
 75     // @param
 76     // pCakeArray    存储烙饼索引数组
 77     // nCakeCnt    烙饼个数
 78     //
 79     void Init(int* pCakeArray, int nCakeCnt)
 80     {
 81         assert(pCakeArray != NULL);
 82         assert(nCakeCnt > 0);
 83 
 84         m_nCakeCnt = nCakeCnt;
 85 
 86         // 初始化烙饼数组
 87         m_CakeArray = new int[m_nCakeCnt]; 
 88         assert(m_CakeArray != NULL);
 89         for(int i = 0; i < m_nCakeCnt; i++)
 90         {
 91             m_CakeArray[i] = pCakeArray[i];
 92         }
 93 
 94         // 设置最多交换次数信息
 95         m_nMaxSwap = UpBound(m_nCakeCnt);
 96 
 97         // 初始化交换结果数组 
 98         m_SwapArray = new int[m_nMaxSwap + 1];
 99         assert(m_SwapArray != NULL);
100 
101         // 初始化中间交换结果信息
102         m_ReverseCakeArray = new int[m_nCakeCnt];
103         for(int i = 0; i < m_nCakeCnt; i++)
104         {
105             m_ReverseCakeArray[i] = m_CakeArray[i];
106         }
107         m_ReverseCakeArraySwap = new int[m_nMaxSwap + 1];
108     }
109 
110 
111     //
112     // 寻找当前翻转的上界
113     //
114     //
115     int UpBound(int nCakeCnt)
116     {
117         return nCakeCnt*2;
118     }
119 
120     //
121     // 寻找当前翻转的下界
122     //
123     //
124     int LowerBound(int* pCakeArray, int nCakeCnt)
125     {
126         int t, ret = 0;
127 
128         // 根据当前数组的排序信息情况来判断最少需要交换多少次
129         for(int i = 1; i < nCakeCnt; i++)
130         {
131             // 判断位置相邻的两个烙饼,是否为尺寸排序上相邻的
132             t = pCakeArray[i] - pCakeArray[i-1];
133             if((t == 1) || (t == -1))
134             {
135             } 
136             else
137             {
138                 ret++;
139             }
140         }
141         return ret;
142     }
143 
144     // 排序的主函数
145     void Search(int step)
146     {
147         int i, nEstimate;
148 
149         m_nSearch++;
150 
151         // 估算这次搜索所需要的最小交换次数
152         nEstimate = LowerBound(m_ReverseCakeArray, m_nCakeCnt);
153         if(step + nEstimate > m_nMaxSwap)
154             return;
155 
156         // 如果已经排好序,即翻转完成,输出结果
157         if(IsSorted(m_ReverseCakeArray, m_nCakeCnt))
158         {
159             if(step < m_nMaxSwap)
160             { 
161                 m_nMaxSwap = step;
162                 for(i = 0; i < m_nMaxSwap; i++)
163                     m_SwapArray[i] = m_ReverseCakeArraySwap[i];
164             }
165             return;
166         }
167 
168         // 递归进行翻转
169         for(i = 1; i < m_nCakeCnt; i++)
170         {
171             Revert(0, i);
172             m_ReverseCakeArraySwap[step] = i;
173             Search(step + 1);
174             Revert(0, i);
175         }
176     }
177     //
178     // true : 已经排好序
179     // false : 未排序
180     //
181     bool IsSorted(int* pCakeArray, int nCakeCnt)
182     {
183         for(int i = 1; i < nCakeCnt; i++)
184         {
185             if(pCakeArray[i-1] > pCakeArray[i])
186             {
187                 return false;
188             }
189         }
190         return true;
191     }
192 
193     //
194     // 翻转烙饼信息
195     //    
196     void Revert(int nBegin, int nEnd)
197     {
198         assert(nEnd > nBegin);
199         int i, j, t;
200 
201         // 翻转烙饼信息
202         for(i = nBegin, j = nEnd; i < j; i++, j--)
203         {
204             t = m_ReverseCakeArray[i]; 
205             m_ReverseCakeArray[i] = m_ReverseCakeArray[j];
206             m_ReverseCakeArray[j] = t;
207         }
208     }
209 
210 private:
211 
212     int* m_CakeArray;    // 烙饼信息数组
213     int m_nCakeCnt;    // 烙饼个数
214     int m_nMaxSwap;    // 最多交换次数。根据前面的推断,这里最多为
215     // m_nCakeCnt * 2 
216     int* m_SwapArray;    // 交换结果数组
217 
218     int* m_ReverseCakeArray;    // 当前翻转烙饼信息数组
219     int* m_ReverseCakeArraySwap;    // 当前翻转烙饼交换结果数组
220     int m_nSearch;    // 当前搜索次数信息
221 };
222 
223 
224 int main()
225 {
226     CPrefixSorting a;
227     int cakeArry[] = {3,2,1,6,5,4,9,8,7,0};
228     a.Run(cakeArry, sizeof(cakeArry) / sizeof(int));
229     a.Output();
230     printf("\n");
231     CPrefixSorting b;
232     int cakeArry1[] = {12,3,2,1,11,6,5,10,4,9,8,7,0};
233     b.Run(cakeArry1, sizeof(cakeArry1) / sizeof(int));
234     b.Output();
235     printf("\n");
236     CPrefixSorting c;
237     int cakeArry2[] = {2,0,1};
238     c.Run(cakeArry2, sizeof(cakeArry2) / sizeof(int));
239     c.Output();
240     return 0;
241 }
原始代码

相关文章: