题目:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有的偶数位于数组的后半部分。
方法一:
分析:该方法使用的是容器,准确的来讲不属于数组,因此用方法一来做此题很可能不会得分!
源代码:
#include<iostream>
#include<vector>
using std::cout;
using std::endl;
using std::vector;
using std::swap;
void Method1(vector<int> &vec)
{
if (vec.empty() || vec.size() == 1)
return;
vector<int> vec_odd;
vector<int> vec_even;
for (auto it = vec.begin(); it != vec.end(); it++)
{
if ((*it & 0x1) != 0)//使用位运算代替求余运算,提高效率
vec_odd.push_back(*it);
else
vec_even.push_back(*it);
}
vec.clear();
for (auto it = vec_odd.cbegin(); it != vec_odd.cend(); it++)
vec.push_back(*it);
for (auto it = vec_even.cbegin(); it != vec_even.cend(); it++)
vec.push_back(*it);
}
void Method2(vector<int> &vec)
{
vector<int> vec_odd;
vector<int> vec_even;
for (auto it = vec.begin(); it != vec.end(); it++)
{
if ((*it & 0x1) != 0)
vec_odd.push_back(*it);
else
vec_even.push_back(*it);
}
vec.swap(vec_odd);
for (auto it = vec_even.cbegin(); it != vec_even.cend(); it++)
vec.push_back(*it);
}
void Method3(vector<int> &vec)
{
vector<int> vec_odd;
vector<int> vec_even;
for (auto it = vec.begin(); it != vec.end(); it++)
{
if ((*it & 0x1) != 0)
vec_odd.push_back(*it);
else
vec_even.push_back(*it);
}
vec.assign(vec_odd.cbegin(), vec_odd.cend());
vec.insert(vec.cend(), vec_even.cbegin(), vec_even.cend());
}
void test1()
{
vector<int> vec = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Method1(vec);
for (auto it = vec.cbegin(); it != vec.cend(); it++)
cout << *it << " ";
cout << endl;
}
void test2()
{
vector<int> vec = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Method2(vec);
for (auto it = vec.cbegin(); it != vec.cend(); it++)
cout << *it << " ";
cout << endl;
}
void test3()
{
vector<int> vec = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Method3(vec);
for (auto it = vec.cbegin(); it != vec.cend(); it++)
cout << *it << " ";
cout << endl;
}
int main()
{
test1();
test2();
test3();
system("pause");
return 0;
}
运行结果:
1 3 5 7 9 0 2 4 6 8
1 3 5 7 9 0 2 4 6 8
1 3 5 7 9 0 2 4 6 8
请按任意键继续. . .
方法二:
此方法效率比较低,其思想如下:
如果前一个数是偶数,后一个数数是基数,则将两者进行交换;
如果前一个数是偶数,后一个数也是偶数,则寻找数组中下一个奇数,并将中间所有的偶数看做一个整体与后一个奇数交换位置;
代码如下:
#include<iostream>
using std::cout;
using std::endl;
using std::swap;
void Change(int arr[], int len)
{
//挖坑法
if (arr == NULL || len <= 1)
return;
for (int i = 0, j = 0; i < len - 1 && j < len;)
{
if (((arr[i] & 0x1) == 0) && ((arr[i+1] & 0x1) != 0))//偶数在前,奇数在后
{
swap(arr[i], arr[i+1]);
++i;
}
else if ((arr[i] & 0x1) == 0 && (arr[i+1] & 0x1) == 0)//相邻的两个数都是偶数,则找下一个奇数的位置,然后将所有相邻的偶数看成一个整体向后移动
{
j = i + 1;
while (((arr[j] & 0x1) == 0) )
++j;
if (j < len)
{
for (int k = j; k > i; k--)
swap(arr[k - 1], arr[k]);
}
++i;
}
}
}
int main()
{
int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
cout << endl;
Change(arr, 10);
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
cout << endl;
system("pause");
return 0;
}
运行结果:
0 1 2 3 4 5 6 7 8 9
1 3 5 7 9 0 2 4 6 8
请按任意键继续. . .
方法三:
使用两个指针,第一个指针指向数组的第一个元素,它只能向后移动,第二个指针指向数组的第二个元素,它只能向前移动。在两个指针相遇之前,第一个指针总是在第二个指针前面。如果第一个指针指向的是基数,则向后移动直至指向偶数为止,如果后一个指针指向的是偶数,则向前移动,直至后一个指针指向一个基数为止。然后交换。
源代码如下:
#include<iostream>
using std::cout;
using std::endl;
using std::swap;
void Change3(int arr[], int len)
{
if (arr == NULL || len <= 1)
return;
int *p = arr;
int *q = arr + len - 1;
while (p < q)
{
while ((*p & 0x1) != 0 && p < q)//如果p指向奇数,则向后移动
++p;
while ((*q & 0x1) == 0 && p < q)//如果q指向偶数,则向前移动
--q;
if (p < q)//如果p指向偶数,q指向奇数,则交换
swap(*p, *q);
}
}
int main()
{
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
cout << endl;
Change3(arr, 10);
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
cout << endl;
system("pause");
return 0;
}
运行结果如下:
0 1 2 3 4 5 6 7 8 9
9 1 7 3 5 4 6 2 8 0
请按任意键继续. . .
分析:此种方法效率较高,且容易实现,但是在交换数据之后打乱了原有的整数顺序,而方法一和二维持了原有的数据的顺序。
方法四:
保留逻辑框架,使用指针函数针对不同功能实现不同的算法;
源代码如下:
#include<iostream>
using std::endl;
using std::cout;
using std::swap;
void Change4(int arr[], int len, bool(*func)(int num))
{
if (arr == NULL || len <= 1)
return;
int *p = arr;
int *q = arr + len - 1;
while (p < q)
{
while (!(*func)(*p) && p < q)//如果p指向奇数,则向后移动
++p;
while ((*func)(*q) && p < q)//如果q指向偶数,则向前移动
--q;
if (p < q)//如果p指向偶数,q指向奇数,则交换
swap(*p, *q);
}
}
bool isEven(int num)
{
return (num & 0x1) == 0;
}
int main()
{
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
cout << endl;
Change4(arr, 10, isEven);
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
cout << endl;
system("pause");
return 0;
}
运行结果和方法三一致!
官方源代码:
#include<iostream>
using std::endl;
using std::cout;
using std::swap;
void Change4(int arr[], int len, bool(*func)(int num))
{
if (arr == NULL || len <= 1)
return;
int *p = arr;
int *q = arr + len - 1;
while (p < q)
{
while (!(*func)(*p) && p < q)//如果p指向奇数,则向后移动
++p;
while ((*func)(*q) && p < q)//如果q指向偶数,则向前移动
--q;
if (p < q)//如果p指向偶数,q指向奇数,则交换
swap(*p, *q);
}
}
bool isEven4(int num)
{
return (num & 0x1) == 0;
}
int main4()
{
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
cout << endl;
Change4(arr, 10, isEven4);
for (int i = 0; i < 10; i++)
cout << arr[i] << " ";
cout << endl;
system("pause");
return 0;
}
运行结果:
Test1 begins:
Test for solution 1:
1 2 3 4 5 6 7
1 7 3 5 4 6 2
Test for solution 2:
1 2 3 4 5 6 7
1 7 3 5 4 6 2
Test2 begins:
Test for solution 1:
2 4 6 1 3 5 7
7 5 3 1 6 4 2
Test for solution 2:
2 4 6 1 3 5 7
7 5 3 1 6 4 2
Test3 begins:
Test for solution 1:
1 3 5 7 2 4 6
1 3 5 7 2 4 6
Test for solution 2:
1 3 5 7 2 4 6
1 3 5 7 2 4 6
Test4 begins:
Test for solution 1:
1
1
Test for solution 2:
1
1
Test5 begins:
Test for solution 1:
2
2
Test for solution 2:
2
2
Test6 begins:
Test for solution 1:
Test for solution 2: