练习3:调整奇数偶数顺序
调整数组使奇数全部都位于偶数前面。
题目:
输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。
思路1:(冒泡排序的思想)
设计两个函数:
Adjust函数用来调整数组的顺序,
Print函数用来打印调整后的数组,
调整数组顺序可以使用冒泡排序的思想,利用双重循环,每次将相邻的两个数进行判断,如果前面一个是偶数并且后面一个是奇数,就把它们进行交换。
1.外层循环实现趟数,每一趟移动一个奇数,定义变量sz计算出数组元素的个数,最极端的情况就是只有一个偶数,但它在所有奇数的前面,此时需要移动(sz-1)个奇数到偶数的前面,一趟只能移动一个奇数,所以最多需要移到sz-1趟。
2.内存循环开始两个相邻的数进行判断,如果偶数在奇数的前面,将在奇数前面的偶数和这个奇数交换位置,否则就指向第二个数和后面一个数,直到找到最后两个数,如果还是奇数在偶数的前面,说明调整已经完成了,可以输出结果了。
3.因为无论数组是什么样子的,外层循环都会执行sz-1次,如果只循环一次就达到了目的,剩下循环sz-2次都是浪费时间,会使得代码效率十分的低。为了提高程序的效率,我们可以在两层循环之间定义一个标志位flag=1,假设最开始数组已经是全部的奇数在偶数前面了,如果进入内层循环,发现有偶数在奇数的前面,那么说明肯定还没调整完,把flag的值改为0,每次出内部循环后再次进行判断,如果flag还是1,说明这一趟下来没有偶数在奇数前面,达到了目的,直接跳出外层循环,输出结果。
代码如下:
#include <stdio.h>
void Adjust(int arr[], int sz) //调整数组的顺序
{
int i = 0;
for (i = 0; i < sz; i++) //外层循环,用来实现趟数
{
int j = 0;
int flag = 1; //标志位
for (j = 0; j < sz-1-i; j++)
{
if ((arr[j] % 2 == 0) && (arr[j + 1] % 2 != 0)) //如果arr[j]是偶数并且arr[j+1]是奇数,就进行交换
{
int tmp=arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag=0;
}
}
if (flag == 1)
{
break;
}
}
}
void Print(int arr[], int sz) //打印调整后的数组
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
Adjust(arr, sz);
Print(arr, sz);
return 0;
}
思路2:(对称找奇偶数)
- 给定两个下标left和right,left放在数组的起始位置,right放在数组中最后一个元素的位置
- 循环进行操作
a.如果left和right表示的区间[left, right]有效(left<right),进行b开始找数,否则结束循环.
b.left从前往后找,找到一个偶数后停止,此时left前面的数都肯定是奇数
c.right从后往前找,找到一个奇数后停止,此时right后面的数都肯定是偶数
d.如果left和right都找到了对应的数,则把这两个数交换,继续a的循环。
每次找数都要满足left<right,因为left和right最多分别找半个数组,left找左半边的数组元素,right找数组右半边的数组元素,当left=right的时候,说明数组全部都已经找完了,没必要再找下去了。
代码如下:
#include <stdio.h>
void swap_arr(int* arr,int sz)
{
int left = 0;
int right = sz - 1;
int tmp = 0;
while (left < right)
{
//从左往右找,满足条件说明它是奇数,不用交换了,接着往右直到找到偶数或者不满足left<right跳出循环。
while (left < right && arr[left] % 2 == 1)
{
left++;
}
while (left < right && arr[right] % 2 == 0)
{
right--;
}
// 如果偶数和奇数都找到,交换这两个数的位置,然后继续找
if (left < right)
{
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
}
}
}
void print_arr(int* arr, int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
swap_arr(arr,sz);
print_arr(arr, sz);
return 0;
}
可以发现两种思路的不同,会导致输出结果的不同,但是都满足条件,满足奇数都在偶数的前面,如果我们想要所有的奇数和偶数分别按照升序/降序来排序,可以再写一个排序函数,并调用它来实现。