方法一
思路
1、采用两个下标left和right,分别指向数组的首元素和尾元素
2、从left所指元素开始向数组的右边找偶数,找到后停止,接着从right所指元素开始向数组的左边开始找奇数,找到后停止,然后交换left和right所指向的两个元素
3、重复第2步,直到left大于或者等于right的时候停止,此时结束
完整测试代码
#include <stdlib.h>
#include <stdio.h>
//打印数组
void printArry(int* arr, int n)
{
int i = 0;
for (i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
}
//调整数组
void adjustArry(int* arr, int n)
{
int left = 0; //指向数组的首元素
int right = n - 1; //指向数组的尾元素
while (left < right)
{
while (left < right && arr[left] % 2 != 0) //从left所指元素向数组右边查找偶数,找到跳出循环
{
left++; //更新left
}
while (left < right && arr[right] % 2 == 0) //从right所指元素向数组左边查找奇数,找到跳出循环
{
right--; //更新right
}
if (left < right) //只有left小于right的时候才交换
{
//交换两个元素
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
}
}
}
//主函数
int main()
{
int n = 0;
printf("请输入一个正整数:>");
scanf("%d", &n); //获取数组元素个数
int* arr = (int*)malloc(sizeof(int) * n); //开辟数组
int i = 0;
for (i = 0; i < n; i++) //获取数组元素
{
scanf("%d", arr + i);
}
printf("调整数组前:");
printArry(arr, n);
adjustArry(arr, n); //调整数组
printf("\n调整数组后:");
printArry(arr, n);
return 0;
}
方法二
思路
采用快速排序的思想,对数组元素进行一趟划分,将奇数放在前面,偶数放在后面,(如果没有学过快速排序也没有关系,影响不大)具体操作如下:
1、用两个下标left和right开始时分别指向数组的两端,再将数组首元素元素arr[left]保存起来
2、从right指向的元素开始往数组的左边找奇数,找到后将其放在left所指位置,然后再从left指向的位置往数组的右边找偶数,找到后将其放在right所指位置
3、重复2操作,直到left和right相等,再将开始保存的首元素arr[left]放在left和right相等的位置,此时结束
如果对以上步骤有疑惑的建议自行画图推理一遍或许会柳暗花明又一村,下面也有图解:
注:我们发现上述操作中并没有判断首元素arr[left]的奇偶性,最后直接将它放到了left和right相等的位置,是因为它的奇偶性并不影响整个数组的要求,why?
原因是:当left和right相等的时候,此位置左边的元素都已经是奇数了,右边的元素都已经是偶数了,此位置无论是奇数还是偶数都满足要求(如果arr[left]是奇数,则从数组左边往右边看,它是数组中奇数部分的最后一个奇数,之后都是偶数,满足要求,如果是偶数也同理),所以没有判断arr[left]元素奇偶性的必要
核心代码
//调整数组
void adjustArry(int* arr, int n)
{
int left = 0; //开始时,指向数组左端
int right = n - 1; //开始时,指向数组右端
int tmp = arr[left]; //保存数组首元素
while (left < right) //left小于right一直循环
{
while (left < right && (arr[right] % 2 == 0))//从right位置开始往左边找奇数,找到跳出循环
{
right--; //更新right
}
arr[left] = arr[right]; //找到的奇数往前面放
while (left < right && (arr[left] % 2 != 0)) //从left位置开始往右边找偶数,找到跳出循环
{
left++; //更新
}
arr[right] = arr[left]; //找到的偶数往后面放
}
arr[left] = tmp; //将最开始保存的元素归位
}
总结:方法一和方法二有很大的相似之处,都是相当于把数组遍历了一遍,方法一是两边同时向中数组中间逼近,方法二是两边换着向中间逼近,方法二理解起来相对来说比方法一稍微要用力一点,不过还好,一定要多积累,多总结,当不理解的时候一定要自己多动手推理实操一下。