递归函数汇总(一)

  1.  给你一个二维数组(矩阵)大小不定 里面都是0或1  ,方阵 n*n 解析成一维数组 维数n    算法:先找到全为0 的列 然后把这列放到一维数组的第一个位子 然后在二维数组中把相应的行全部清零 继续.比如 二位数组中第一列全为0 那么就把1(列标号)放入一维数组的第一个位置 然后把二位数组中第一行全部清零 然后再接着找全为0 的列 但是这个时候就不考虑第一列 因为第一列已经排完了
  代码:
typedef unsigned int my_type;
class CArray2D
{
private:
 my_type* m_pData;
 short* m_rowList;//列标号,缓冲用
 int  m_iListCount;
 int  m_iCol;  //行数
 int  m_iRow; //列数
 bool* m_bIsAllZero;
 std::vector<short *> m_vsAllList;
private://判断该列是否全是
 bool _AllIsZero(int iRow);
 void _GetList();
 void _Permute(int s);
public:
 CArray2D(int iCol, int iRow);//行,列
 CArray2D(my_type arr[], size_t iSize);//行,列
 ~CArray2D();
 bool FillAllData(my_type arr[], size_t iSize);
 void SetValue(int iCol/*
        * 第几行
        */, int iRow, /*
        * 第几列
        */my_type value);
 my_type GetValue(int iCol, int iRow);
 //得到所有可能的组合
 void GetAllList();
 //打印所有可能的组合
 void PrintAllList();
 //检验是否是满足条件的数组
 bool IsFitArray();

};

CArray2D::CArray2D(int iCol, int iRow)//行,列
:m_iRow(iRow), m_iCol(iCol)
{
 m_pData = new my_type[iCol*iRow];
 memset(m_pData, 0, iCol*iRow);
 m_rowList = new short[m_iRow*2];
 m_bIsAllZero = new bool[m_iRow];
 memset(m_bIsAllZero, 0, sizeof(m_bIsAllZero[0])*m_iRow);
 m_iListCount = 0;
}
CArray2D::CArray2D(my_type arr[], size_t iSize)
{
 int iTemp = (int)sqrt((float)iSize);
 if(iSize == iTemp*iTemp){
  m_pData = new my_type[iSize];
  m_iCol = iTemp ;
  m_iRow = iTemp;
  m_rowList = new short[m_iRow*2];
  m_bIsAllZero = new bool[m_iRow];
  memset(m_bIsAllZero, 0, sizeof(m_bIsAllZero[0])*m_iRow);
  m_iListCount = 0;
  memcpy(m_pData, arr, iSize*sizeof(arr[0]));
 }else{
  m_iCol = 0;
  m_iRow = 0;
 }
}

CArray2D::~CArray2D()
{
 delete []m_pData;
 m_pData = NULL;
 delete []m_rowList;
 m_rowList = NULL;
 delete []m_bIsAllZero;
 m_bIsAllZero = NULL;
 for(size_t i=0; i<m_vsAllList.size(); ++i){
  delete []m_vsAllList[i];
  m_vsAllList[i] = NULL;
 }
}

bool CArray2D::FillAllData(my_type arr[], size_t iSize)
{
 int iTemp = (int)sqrt((float)iSize);
 if(iSize != iTemp*iTemp || iTemp != m_iCol)
  return false;
 if(!IsFitArray()) return false;
 memcpy(m_pData, arr, iSize*sizeof(arr[0]));
 return true;
}

void CArray2D::SetValue(int iCol/*
        * 第几行
        */, int iRow, /*
        * 第几列
        */my_type value)
{
 m_pData[iCol*m_iRow+iRow] = value;
}
my_type CArray2D::GetValue(int iCol, int iRow)
{
 return m_pData[iCol*m_iRow+iRow];
}

void CArray2D::_GetList()
{
 for(int j=0; j<m_iRow; ++j)
  if(!m_bIsAllZero[j]&&_AllIsZero(j)){
   m_bIsAllZero[j] = true;
   m_rowList[m_iListCount++] = j;
  }
}

void CArray2D::GetAllList()
{
 _GetList();
 _Permute(0);
}

void CArray2D::_Permute(int s)
{
 //功能:求a[s,...,n-1]的全排列
 //用树可以形象的表示这个过程,叶子数与全排列的个数相同
 if(s == m_iListCount)
 {
  //记录这次的顺序
  short * pTemp = new short[m_iListCount];
  memcpy(pTemp, m_rowList, m_iListCount*sizeof(pTemp[0]));
  m_vsAllList.push_back(pTemp);
 }
 else{
  int iLastCount = m_iListCount;
  for( int  i=s;i<iLastCount;++i)      //不能为i=s+1g
  {
   my_type *pTemp = new my_type[m_iRow];
   short t=m_rowList[s];m_rowList[s]=m_rowList[i];m_rowList[i]=t;
   my_type * pp = m_pData+m_rowList[s]*m_iRow;
   memcpy(pTemp, pp, m_iRow*sizeof(m_pData[0]));
   //重新搜索,看是否有新东东需要加入
   memset(pp, 0, m_iRow*sizeof(m_pData[0]));
   _GetList();
   _Permute( s+1);
   //回嗍
   if(m_iListCount != iLastCount){
    for(int j=iLastCount; j<m_iListCount; ++j)
     m_bIsAllZero[m_rowList[j]] = false;
    m_iListCount = iLastCount;
   }
   memcpy(pp, pTemp, m_iRow*sizeof(m_pData[0]));
   delete []pTemp;
   pTemp = NULL;
   t=m_rowList[s];m_rowList[s]=m_rowList[i];m_rowList[i]=t;
  }
 }
}
void CArray2D::PrintAllList()
{
 printf("所有的组合(%d)/n", m_vsAllList.size());
 for(size_t i=0; i<m_vsAllList.size(); ++i){
  for(int j=0; j<m_iRow; ++j)
   printf("%d ", m_vsAllList[i][j]+1);
  printf("/n");
 }
 printf("所有的组合(%d)/n", m_vsAllList.size());
}
//检验是否是满足条件的数组
bool CArray2D::IsFitArray()
{
 if(m_iCol == 0 || m_iRow == 0) return false;
 my_type temparr[100];
 memset(temparr, 0, sizeof(temparr));
 memcpy(temparr, m_pData, m_iCol*m_iRow*sizeof(m_pData[0]));

 my_type *pTempData = new my_type[m_iCol*m_iRow];
 memcpy(pTempData, m_pData, m_iCol*m_iRow*sizeof(pTempData[0]));
 for(;;){
  int iLastCount = m_iListCount;
  for(int j=0; j<m_iRow; ++j)
   if(!m_bIsAllZero[j]&&_AllIsZero(j)){
    m_bIsAllZero[j] = true;
    m_rowList[m_iListCount++] = j;
   }
   //满足条件
   if(m_iListCount == m_iRow)break;
   else if(iLastCount == m_iListCount)
    return false;
   for(int i=iLastCount; i<m_iListCount; ++i)
    memset(m_pData+m_rowList[i]*m_iRow, 0, m_iRow*sizeof(m_pData[0]));
 }
 //还原数据
 memcpy(m_pData, pTempData, m_iCol*m_iRow*sizeof(pTempData[0]));
 m_iListCount = 0;
 memset(m_bIsAllZero, 0, sizeof(m_bIsAllZero[0])*m_iRow);
 delete []pTempData;
 pTempData = NULL;
 return true;
}


bool CArray2D::_AllIsZero(int iRow)
{
 for(int i=0; i<m_iCol; ++i)
  if(m_pData[iRow+m_iRow*i])
   return false;
 return true;
}

  后记:这个算法来源于排列组合算法,基本的思想就是递归回嗍.可以应用在麻将糊牌算法上. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值