#define MAXSIZE 100
typedef int datatype;
typedef struct{
datatype a[MAXSIZE];
int size;
}sequence_list;
1.双指针法
使用两个指针i
和j
,分别从数组的前端和后端开始遍历。如果i
指向偶数且j
指向奇数,则交换这两个元素。如果i
指向奇数,则i
前进(向右移动)。如果j
指向偶数,则j
后退(向左移动)。当i >= j
时,遍历结束。只需遍历一次数组,因此时间复杂度为O(n),其中n是数组中元素的个数。
void partion(sequence_list *L)
{
int i=0,j=L->size-1,temp;
while(i<j){
if(L->a[i]%2==0&&L->a[j]%2==1){
temp=L->a[i];
L->a[i]=L->a[j];
L->a[j]=temp;
i++;
j--;
}
else if(L->a[i]%2==1){
i++;
}
else if(L->a[j]%2==0){
j--;
}
}
}
2.额外空间法:
这种方法的时间复杂度也是O(n),但空间复杂度增加到O(n),因为需要额外的空间来存储奇数和偶数。
void partion_extra_space(sequence_list *L)
{
int *temp = (int*)malloc(sizeof(int) * L->size);
int oddIndex = 0, evenIndex = L->size - 1;
// 遍历原数组,分别将奇数和偶数放入暂存数组的两端
for (int i = 0; i < L->size; i++) {
if (L->a[i] % 2 == 1) {
temp[oddIndex++] = L->a[i];
} else {
temp[evenIndex--] = L->a[i];
}
}
// 将暂存数组中的元素复制回原数组
for (int i = 0; i < L->size; i++) {
L->a[i] = temp[i];
}
free(temp); // 释放暂存数组
}
3.单指针法:
使用一个指针记录当前存放奇数的位置。遍历数组,每次发现一个奇数,就将其与当前指针指向的元素交换,并将指针向前移动。这种方法也是原地修改数组,时间复杂度为O(n)。
void partion(sequence_list *L)
{
int k = 0; // k用于记录下一个奇数应该存放的位置
for (int i = 0; i < L->size; i++)
{
if (L->a[i] % 2 == 1) // 如果当前元素是奇数
{
if (i != k) // 如果当前奇数不在它应该在的位置
{
// 交换L->a[i]和L->a[k]
int temp = L->a[k];
L->a[k] = L->a[i];
L->a[i] = temp;
}
k++; // 更新下一个奇数应该存放的位置
}
}
}
4.计数法:
首先遍历一次数组,计算奇数的数量。然后再次遍历数组,使用两个变量分别作为奇数和偶数的索引,在原数组内部重新排列奇偶数。奇数部分的索引从0开始,偶数部分的索引从奇数数量开始。这样可以原地修改数组,但需要遍历两次数组,时间复杂度为O(2n)。
void partion_count(sequence_list *L)
{
int oddCount = 0;
// 计算奇数的个数
for (int i = 0; i < L->size; i++) {
if (L->a[i] % 2 == 1) {
oddCount++;
}
}
int *temp = (int*)malloc(sizeof(int) * L->size);
int oddIndex = 0, evenIndex = oddCount;
// 将奇数和偶数分别放到暂存数组中
for (int i = 0; i < L->size; i++) {
if (L->a[i] % 2 == 1) {
temp[oddIndex++] = L->a[i];
} else {
temp[evenIndex++] = L->a[i];
}
}
// 将暂存数组中的元素复制回原数组
for (int i = 0; i < L->size; i++) {
L->a[i] = temp[i];
}
free(temp); // 释放暂存数组
}
5.冒泡变种法:
类似冒泡排序的方式,遍历数组,相邻元素对比,每次发现一个偶数在奇数前面,就交换它们的位置。这样,每一轮遍历都会将一个偶数“冒泡”到数组的末尾。但这种方法的时间复杂度较高,为O(n^2)。
void partion_bubble_var(sequence_list *L)
{
for (int i = 0; i < L->size - 1; i++) {
for (int j = 0; j < L->size - i - 1; j++) {
if (L->a[j] % 2 == 0 && L->a[j + 1] % 2 == 1) {
// 交换位置
int temp = L->a[j];
L->a[j] = L->a[j + 1];
L->a[j + 1] = temp;
}
}
}
}