题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
利用快排的两种实现方法,一种是前后两个指针向中间移动,另外一种是算法导论上快排的划分方法,也是两个指针,但都从头开始。
算法一,前后两个指针
#include <iostream>
#include <algorithm>
using namespace std;
bool isEven(int n)
{
return (n & 1)==0;
}
void Reorder(int *pData, unsigned int length, bool (*func)(int))//两个指针一前一后,实现奇数在前,偶数在后
{
if(pData==NULL || length==0)
return;
int *pBegin=pData;
int *pEnd=pData+length-1;
while(pBegin < pEnd)
{
while(!func(*pBegin))
pBegin++;
while(func(*pEnd))
pEnd--;
swap(*pBegin, *pEnd);
pBegin++;
pEnd--;
}
}
void main()
{
int a[]={1,3,6,4,9,10,13};
Reorder(a, 7, isEven);
for(int i=0; i<7; i++)
cout<<a[i]<<" ";
cout<<endl;
}
算法二,参见算法导论快速排序的数组划分
#include <iostream>
#include <algorithm>
using namespace std;
bool isEven(int n)
{
return (n & 1)==0;
}
void Partition(int *pData, unsigned int length, bool (*func)(int))//算法导论上快排的划分思想,实现奇数在前,偶数在后
{
int i=-1;
for(int j=0; j<length; j++)
{
if(!func(*(pData+j)))
{
i++;
swap(*(pData+i), *(pData+j));
}
}
}
void main()
{
int a[]={1,3,6,4,9,10,13};
Partition(a, 7,isEven);
for(int i=0; i<7; i++)
cout<<a[i]<<" ";
cout<<endl;
}
变形:处理数组实现“奇偶奇偶”相间的格式
利用算法导论快排的数组划分思想,让i(确切的说是i+1)指向需要交换的位置,j从i后一个位置开始遍历,找到第一个符合要求的数与i位置的数进行交换。
#include <iostream>
#include <algorithm>
using namespace std;
bool isEven(int n)
{
return (n & 1)==0;
}
void OddandEven(int *pData, unsigned int length, bool (*func)(int))//参考算法导论上快排的划分思想,实现数组的“奇偶奇偶”相间
{
int i=-1;
bool flag=true;
int j=0;
while(j<length)
{
if( func(j)!=func(*(pData+j)) )
{
if(flag)
i++;
}
else
{
flag=false;
if(func(i+1)!=func(j))
{
i++;
swap(*(pData+i), *(pData+j));
flag=true;
j=i;
}
}
j++;
}
}
void main()
{
int a[]={1,3,6,4,9,10,13};
// Reorder(a, 7, isEven);
// Partition(a, 7,isEven);
OddandEven(a, 7, isEven);
for(int i=0; i<7; i++)
cout<<a[i]<<" ";
cout<<endl;
}