题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,偶数位于数组的后半部分。
思路:使用两个指针,分别指向数组的头和尾,在两个指针相遇之前,头指针总是在尾指针的后面。如果头指针指向的数字是偶数,且尾指针指向的数字是奇数,则交换这两个数字。
void ReorderOddEven(int* iArr, int iLen)
{
if (NULL == iArr || iLen <=0){
return ;
}
int *pFirst = iArr;
int *pLast = iArr+iLen-1;
while(pFirst < pLast){
while (pFirst < pLast && (*pFirst & 0x1) != 0){
++pFirst;
}
while (pFirst < pLast && (*pLast & 0x1) == 0){
--pLast;
}
if ( pFirst < pLast){
*pFirst = *pFirst+*pLast;
*pLast = *pFirst-*pLast;
*pFirst = *pFirst-*pLast;
}
}
}
扩展:
如果将数组中的数按照大小分为两部分,所有负数都在非负数的前面,该怎么做?
如果将数组分为两部分,能被3整除的数都在不能被3整除的数的前面,该怎么做?
显然,上面的两个问题,和本文中所提出的问题有很大的相似之处,其基本思路都是将数组分成两个部分,唯一不同就是划分的条件不同,因此我们可以将判断条件独立成单独的函数,而基本的处理思路不变。上述两个问题都可以在ReorderOddEven函数的框架下实现,只要修改判断条件即可,因此我们可以把这个逻辑框架抽取出来而把判断的标准变成一个函数指针。这样就将上述的函数解耦成两部分:① 数组顺序调整,② 判断函数。
void ReorderOddEven1(int* iArr, int iLen, bool (*func)(int))
{
if (NULL == iArr || iLen <=0){
return ;
}
int *pFirst = iArr;
int *pLast = iArr+iLen-1;
while(pFirst < pLast){
while (pFirst < pLast && func(*pFirst)){
++pFirst;
}
while (pFirst < pLast && !func(*pLast)){
--pLast;
}
if ( pFirst < pLast){
*pFirst = *pFirst+*pLast;
*pLast = *pFirst-*pLast;
*pFirst = *pFirst-*pLast;
}
}
}
bool isEven(int iNum)
{
return (iNum & 0x1)!=0;
}
bool isPositive(int iNum)
{
return iNum<0;
}
bool isThree(int iNum)
{
return iNum%3==0;
}
测试代码:
int main()
{
int iArray[] = {1,-2,3,4,5,7,9,8,6};
ReorderOddEven1(iArray, 9, isPositive);
for (int i=0; i<9; i++)
{
printf("%d\t", iArray[i]);
}
printf("\n");
return 0;
}
源码下载: