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;
}
后记:这个算法来源于排列组合算法,基本的思想就是递归回嗍.可以应用在麻将糊牌算法上.