C语言学习笔记20260614-数组奇偶数调整3种方法
功能需求
输入一个整数数组,调整该数组的顺序使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
方法一:原地交换法(双指针)
算法思路
使用双指针技术,左指针从数组开头向右移动,右指针从数组末尾向左移动:
•左指针寻找偶数(需要移动到后半部分的元素)
•右指针寻找奇数(需要移动到前半部分的元素)
•当找到需要交换的元素对时,进行交换操作
代码实现
c
void Change_arr(int arr[], int n)
{
int left = 0;
int right = n - 1;
while (left < right)
{
// 左指针向右移动,跳过奇数(不需要移动的元素)
while (left < right && arr[left] % 2 != 0)
{
left++;
}
// 右指针向左移动,跳过偶数(不需要移动的元素)
while (left < right && arr[right] % 2 == 0)
{
right--;
}
// 交换奇偶元素
if (left < right)
{
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
}
算法特点
• 优点:空间效率高,只需要常数额外空间
• 缺点:相对复杂,需要仔细处理边界条件
• 稳定性:不稳定,会改变相同类型元素的相对顺序
方法二:额外数组分离存储
算法思路
使用一个临时数组,分两步存储:
- 第一次遍历:将所有奇数按原顺序存入临时数组
- 第二次遍历:将所有偶数按原顺序存入临时数组
- 将临时数组内容复制回原数组
代码实现
c
void Change_arr(int arr[], int n)
{
int temp[100]; // 临时数组,存放结果
int idx = 0;
// 第一步:先存所有奇数
for (int i = 0; i < n; i++)
{
if (arr[i] % 2 == 1)
{
temp[idx++] = arr[i];
}
}
// 第二步:再存所有偶数
for (int i = 0; i < n; i++)
{
if (arr[i] % 2 == 0)
{
temp[idx++] = arr[i];
}
}
// 把临时数组数据拷贝回原数组
for (int i = 0; i < n; i++)
{
arr[i] = temp[i];
}
}
算法特点
• 优点:逻辑清晰,易于理解和实现
• 缺点:需要额外的数组空间
• 稳定性:稳定,保持了相同类型元素的相对顺序
方法三:冒泡相邻交换法
算法思路
类似于冒泡排序的思想,通过相邻元素的比较和交换:
• 遍历数组,比较相邻的两个元素
• 如果前一个是偶数,后一个是奇数,则交换它们
• 这样奇数会逐渐"冒泡"到数组的前面
代码实现
c
void Change_arr(int arr[], int n)
{
// 外层循环控制遍历轮数
for (int i = 0; i < n; i++)
{
// 内层相邻两两对比
for (int j = 0; j < n - 1 - i; j++)
{
// 前偶数、后奇数,交换位置
if (arr[j] % 2 == 0 && arr[j + 1] % 2 == 1)
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
算法特点
• 优点:实现简单,逻辑直观
• 缺点:时间复杂度较高,效率较低
• 稳定性:稳定,但效率不如方法二
完整测试代码
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
// 方法1:原地交换
void Change_arr_method1(int arr[], int n)
{
int left = 0;
int right = n - 1;
while (left < right)
{
while (left < right && arr[left] % 2 != 0)
{
left++;
}
while (left < right && arr[right] % 2 == 0)
{
right--;
}
if (left < right)
{
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
}
// 方法2:额外数组
void Change_arr_method2(int arr[], int n)
{
int temp[100];
int idx = 0;
for (int i = 0; i < n; i++)
{
if (arr[i] % 2 == 1)
{
temp[idx++] = arr[i];
}
}
for (int i = 0; i < n; i++)
{
if (arr[i] % 2 == 0)
{
temp[idx++] = arr[i];
}
}
for (int i = 0; i < n; i++)
{
arr[i] = temp[i];
}
}
// 方法3:冒泡交换
void Change_arr_method3(int arr[], int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
if (arr[j] % 2 == 0 && arr[j + 1] % 2 == 1)
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr3[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("原数组: ");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
printf("\n");
Change_arr_method1(arr1, 10);
printf("方法1结果: ");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
printf("\n");
Change_arr_method2(arr2, 10);
printf("方法2结果: ");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
printf("\n");
Change_arr_method3(arr3, 10);
printf("方法3结果: ");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr3[i]);
}
printf("\n");
return 0;
}