您的位置:首页 > 其它

基数和偶数分离

2016-01-15 18:42 351 查看
/*
仅用O(1)的空间,将整数数组按奇偶数分成2部分,数组左边是奇数、右边是偶数。
(要求:给出完整代码,尽量高效,简洁)
*/

/*下面是我的写的代码*/
#include <stdio.h>

#define MAX 10

//交换变量
void swap(int *p, int *q)
{
if (p==NULL || q==NULL)
return;

*p ^= *q;
*q ^= *p;
*p ^= *q;
}

//将数组中基数和偶数分离
void arr_deal(int *arr, int num)
{
int i = 0, j = num-1;

if (NULL == arr || num < 1)
return;

while (i < j)
{
while (arr[i]%2==1 && i<j)
i++;

while (arr[j]%2==0 && i<j)
j--;

if (i < j)
swap(&arr[i], &arr[j]);
}

}

//显示数组中的内容
void display(int *arr, int num)
{
int i;

for (i=0; i<num; i++)
printf("%d ", arr[i]);

printf("\n");

}

//主函数
int main(int argc, char *argv[])
{
int arr[MAX] = {2, 22, 4, 5, 3, 6, 3, 27, 0, 11};

display(arr, MAX);

arr_deal(arr, MAX);

display(arr, MAX);

return 0;
}


标准答案:

#include <stdio.h>
#include <stdlib.h>
#define bool int
#define false 0
#define true 1
void Reorder(int *pData, unsigned int length, bool (*func)(int));
bool isEven(int n);
void ReorderOddEven_1(int *pData, unsigned int length)
{
if(pData == NULL || length == 0)
return;
int *pBegin = pData;
int *pEnd = pData + length - 1;
while(pBegin < pEnd)
{
// 向后移动pBegin,直到它指向偶数
while(pBegin < pEnd && (*pBegin & 0x1) != 0)    //
pBegin ++;
// 向前移动pEnd,直到它指向奇数
while(pBegin < pEnd && (*pEnd & 0x1) == 0)
pEnd --;
if(pBegin < pEnd)
{
int temp = *pBegin;
*pBegin = *pEnd;
*pEnd = temp;
}
}
}
void Reorder(int *pData, unsigned int length, bool
(*func)(int))
{
if(pData == NULL || length == 0)
return;
int *pBegin = pData;
int *pEnd = pData + length - 1;
while(pBegin < pEnd)
{
//向后移动pBegin
while(pBegin < pEnd &&!func(*pBegin))
pBegin ++;
// 向前移动pEnd
while(pBegin < pEnd &&func(*pEnd))
pEnd --;
if(pBegin < pEnd)
{
int temp = *pBegin;
*pBegin = *pEnd;
*pEnd = temp;
}
}
}
bool isEven(int n)
{
return (n & 1) == 0;
}


对于标准答案的总结:


思路:

两个指针,分别从头和从尾遍历数组

精彩的部分:

定义布尔:有利于代码的可读性
#define false 0
#define true 1

将功能封装成函数:
有利于调试,纠错,提高代码的复用

判断参数的有效性:
有利于代码的健壮性

if(pData == NULL || length == 0)
return;

边界的判断:
while(pBegin < pEnd && (*pBegin & 0x1) != 0)

if(pBegin < pEnd)
{
int temp = *pBegin;
*pBegin = *pEnd;
*pEnd = temp;
}

高效性:
对于除法和乘法,采用位运算,提高效率
pBegin & 0x1
(n & 1) == 0;

利用函数指针,实现切面编程,构成框架:
bool (*func)(int)
调用判断奇数和偶数的判断:bool isEven(int n)(原型)

善用指针:(不知道算不算)
int temp = *pBegin;
*pBegin = *pEnd;
*pEnd = temp;

注释:
在关键的位置标识


不足之处:

将int变装成bool:该设计存在问题

#define bool int
改为typedef int bool

函数参数并没有全部做判定
可能传入非法数值


编程小总结

切面编程:

框架的搭建
现在写好的函数可以调用以后写好的函数

函数参数中有调用的函数,但是不确定,用指针代替,等到想用哪个,就在
外面传入,有利于代码的维护和升级

例如:
4000
要调用bool isEven(int n);
但是没有写出来(计划将来写),但是仍然想先调用其功能(预先想好的功能),函数可以这么写
void Reorder(int *pData, unsigned int length, bool (*func)(int));

调用判断奇数和偶数的判断:bool isEven(int n)(原型)

拓展:
对于不确定,可以都考虑指针,具体要传入参数,在外部指定传入即好

位运算:
遇到乘法、除法、求余,都可以使用位运算,提高效率
例如:
x%2 <=> n&1

注意:只是用在偶数中

例如:

// 向后移动pBegin,直到它指向偶数
while(pBegin < pEnd && (*pBegin & 0x1) != 0)    //
pBegin ++;
// 向前移动pEnd,直到它指向奇数
while(pBegin < pEnd && (*pEnd & 0x1) == 0)
pEnd --;

以后要在关键位置注释,比较难懂的代码加上功能注释,需要标识位置(调试)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: