题目:
输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。
示例:{4,6,5,7,2,3,1}
输出:{5,7,3,1,4,6,2}
1.冒泡法:
冒泡法的逻辑是:前后两个元素对比,如果前一个是偶数,后一个是奇数,就前后交换,这样进行 元素个数-1趟排查
代码实现:
#include<stdio.h>
void _swap(int* arr, int sz)
{
int i = 0,j=0;
int flag = 0;
for (i = 0;i < sz-1;i++)
{
flag = 0;
for (j = 0;j < sz - 1 - i;j++)//排好的后面的偶数就不用动了
{
if (arr[j] % 2 == 0 && arr[j + 1] % 2 != 0)
{
int tem = 0;
tem = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tem;
flag = 1;
}
}
if (flag == 0)//要是一趟中一个没换,就说明已经排好了
break;
}
}
void _printf(int* arr, int sz)
{
int i = 0;
for (i = 0;i < sz;i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[] = { 1,2,4,5,7,6,8 };
int sz = sizeof(arr) / sizeof(arr[0]);
_swap(arr, sz);
_printf(arr, sz);
}
这里引入了flag变量,为了判断是否在某一趟时数组元素已经排好,排好就跳出,节省了后面步骤
2.二分法:
逻辑:从前后两边分别开始遍历:
左边遍历到偶数停下来,是奇数继续往后走
右边遍历到奇数停下来,是偶数继续往前走
#include<stdio.h>
#include<assert.h>
int* _swap(int* arr, int sz)
{
int left = 0;
int right = sz - 1;
int* ret = arr;
assert(arr != NULL);
while (left < right)
{
while ((left < right) && arr[left] % 2 == 1)
left++;
while ((left < right) && arr[right] % 2 == 0)
right--;
if (left < right)//当前面两个while是因为不满足left<right
//跳出来时,就不能交换了
{
int tem = 0;
tem = arr[left];
arr[left] = arr[right];
arr[right] = tem;
}
}
return ret;
}
void _printf(int* arr, int sz)
{
int i = 0;
for (i = 0;i < sz;i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[]= { 1,5,4,7,9,8,3,2,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
_swap(arr, sz);
_printf(arr, sz);
return 0;
}
细节:
1.没到中间,说明还有没遍历的元素,进循环
2.&&3. 同理,只要left和right中间还有元素,就进循环,继续遍历
4. 如果 2. 和 3.的循环是因为left>=right而跳出的话,这里的条件就会限制交换,不让它俩交换,如果没有这个条件限制,就换错了