编程之美 - 1.3 翻烙饼 书中代码可运行版 ,看懂了没自己写

/****************************************************************/
//
// 烙饼排序实现
//
/****************************************************************/
#include "stdio.h"
#include <assert.h>
#include <stdlib.h>
using namespace std;


//#define assert assert;
class CPrefixSorting
{
private:


int* m_CakeArray; // 烙饼信息数组
int m_nCakeCnt; // 烙饼个数
int m_nMaxSwap; // 最多交换次数。根据前面的推断,这里最多为
// m_nCakeCnt * 2 
int* m_SwapArray; // 交换结果数组


int* m_ReverseCakeArray; // 当前翻转烙饼信息数组
int* m_ReverseCakeArraySwap; // 当前翻转烙饼交换结果数组
int m_nSearch; // 当前搜索次数信息


public:


CPrefixSorting()
{
m_nCakeCnt = 0;
m_nMaxSwap = 0;
}


~CPrefixSorting()
{
if (m_CakeArray != NULL)
{
delete m_CakeArray;
}
if (m_SwapArray != NULL)
{
delete m_SwapArray;
}
if (m_ReverseCakeArray != NULL)
{
delete m_ReverseCakeArray;
}
if (m_ReverseCakeArraySwap != NULL)
{
delete m_ReverseCakeArraySwap;
}
}


//
// 计算烙饼翻转信息
// @param
// pCakeArray 存储烙饼索引数组
// nCakeCnt 烙饼个数
//
void Run(int* pCakeArray, int nCakeCnt)
{
Init(pCakeArray, nCakeCnt);


m_nSearch = 0;
Search(0);
}


//
// 输出烙饼具体翻转的次数
//
void Output()
{
for (int i = 0; i < m_nMaxSwap; i++)
{
/*printf("%d ", m_arrSwap[i]);*/  // 这个是错了吗
printf("%d ", m_SwapArray[i]); // 这行是修改的代码
}


printf("\n |Search Times| : %d\n", m_nSearch);
printf("Total Swap times = %d\n", m_nMaxSwap);
}


private:


//
// 初始化数组信息
// @param
// pCakeArray 存储烙饼索引数组
// nCakeCnt 烙饼个数
//
void Init(int* pCakeArray, int nCakeCnt)
{
assert(pCakeArray != NULL);
assert(nCakeCnt > 0);


m_nCakeCnt = nCakeCnt;


// 初始化烙饼数组
m_CakeArray = new int[m_nCakeCnt];
assert(m_CakeArray != NULL);
for (int i = 0; i < m_nCakeCnt; i++)
{
m_CakeArray[i] = pCakeArray[i];
}


// 设置最多交换次数信息
m_nMaxSwap = UpBound(m_nCakeCnt);


// 初始化交换结果数组 
m_SwapArray = new int[m_nMaxSwap + 1];
assert(m_SwapArray != NULL);


// 初始化中间交换结果信息
m_ReverseCakeArray = new int[m_nCakeCnt];
for (int i = 0; i < m_nCakeCnt; i++)
{
m_ReverseCakeArray[i] = m_CakeArray[i];
}
m_ReverseCakeArraySwap = new int[m_nMaxSwap];
}




//
// 寻找当前翻转的上界
//
//
int UpBound(int nCakeCnt)
{
return nCakeCnt * 2;
}


//
// 寻找当前翻转的下界
//
//
int LowerBound(int* pCakeArray, int nCakeCnt)
{
int t, ret = 0;


// 根据当前数组的排序信息情况来判断最少需要交换多少次
for (int i = 1; i < nCakeCnt; i++)
{
// 判断位置相邻的两个烙饼,是否为尺寸排序上相邻的
t = pCakeArray[i] - pCakeArray[i - 1];
if ((t == 1) || (t == -1))
{
}
else
{
ret++;
}
}
return ret;
}


// 排序的主函数
void Search(int step)
{
int i, nEstimate;


m_nSearch++;


// 估算这次搜索所需要的最小交换次数
nEstimate = LowerBound(m_ReverseCakeArray, m_nCakeCnt);
if (step + nEstimate > m_nMaxSwap)
return;


// 如果已经排好序,即翻转完成,输出结果   
//这如何保证是最优的呢   这里是打印出所有的优于蛮力算法的结果么
if (IsSorted(m_ReverseCakeArray, m_nCakeCnt))
{
if (step < m_nMaxSwap) //每找到一个较优解,更新maxstep和步骤数组
{
m_nMaxSwap = step;
for (i = 0; i < m_nMaxSwap; i++)
/*m_arrSwap[i] = m_ReverseCakeArraySwap[i];*/
m_SwapArray[i] = m_ReverseCakeArraySwap[i];
}
return;
}


// 递归进行翻转
for (i = 1; i < m_nCakeCnt; i++)
{
Revert(0, i);
m_ReverseCakeArraySwap[step] = i;  
       // 这个数组被复用了,如果煎饼排序完成,则总会输出正确结果
Search(step + 1);
Revert(0, i);        //翻回来了
}
}
//
// true : 已经排好序
// false : 未排序
//
bool IsSorted(int* pCakeArray, int nCakeCnt)
{
for (int i = 1; i < nCakeCnt; i++)
{
if (pCakeArray[i - 1] > pCakeArray[i])
{
return false;
}
}
return true;
}


//
// 翻转烙饼信息
//    
void Revert(int nBegin, int nEnd)
{
assert(nEnd > nBegin);
int i, j, t;


// 翻转烙饼信息
for (i = nBegin, j = nEnd; i < j; i++, j--)
{
t = m_ReverseCakeArray[i];
m_ReverseCakeArray[i] = m_ReverseCakeArray[j];
m_ReverseCakeArray[j] = t;
}
}




};




int main()
{
CPrefixSorting ps;
int iCakeCount = 10;
int pCake[10] = { 5,3,9,2,7,10,4,8,1,6 };
for (int i = 0; i < 6; i++)
printf("%d  ", pCake[i]);
printf("\n");
ps.Run(pCake, 6);
ps.Output();
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值