问题描述:
这是前缀翻转排序问题,书上的内容这里不详述,给个电子版下载地址
本文源码编译环境: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 }