基数和偶数分离

/*
仅用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

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

编程小总结

切面编程:

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

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

    例如:
        要调用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 --;

    以后要在关键位置注释,比较难懂的代码加上功能注释,需要标识位置(调试)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值