Chinaunix首页 | 论坛 | 博客
  • 博客访问: 900020
  • 博文数量: 119
  • 博客积分: 2493
  • 博客等级: 大尉
  • 技术积分: 2363
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-03 14:00
文章分类

全部博文(119)

文章存档

2013年(19)

2012年(100)

分类: LINUX

2012-09-16 09:27:11

算法问题:输入一个整数的数组,实现一个函数来调整该数组中数字的顺序,使得所有的
                 奇数位于数组的前半部分,所有的偶数位于数组的后半部分。

该问题在耿国华《数据结构》中有,但讲的很粗糙。而且在面试的时候这个问题也常出现,
上次我去面百度的暑假实习生的时候,百度的一面面试官就问了我这个问题。
----------------------------------------------------------------------------------------------------------------
一、算法问题分析:
           该问题可以用快速排序的思想,快速排序是将一个数组划分为两类,一类是大于区轴
一类是小于区轴,这个地方同样是将数组划分为两类,一类为奇数,一类为偶数。其算法的
实现和快速排序的实现也有很多相似的地方。

----------------------------------------------------------------------------------------------------------------
二、算法的实现。

  1. #define swap(a,b) \
  2.         do {typeof(a) tmp = a;a = b;b = tmp;} while(0)
  3.         
  4. void adjust(int a[],int len)
  5. {
  6.         if (a == NULL || len == 0)
  7.             return ;
  8.         int i = 0, j = len - 1;
  9.         while (i < j) {
  10.                 while (i < j && (a[i] & 0x01)) i++;
  11.                 while (i < j && (a[j] & 0x01) == 0) j--;
  12.                 if (i < j) swap(a[i],a[j]);
  13.         }
  14.         return ;
  15. }
-----------------------------------------------------------------------------------------------------
三、单元测试。
     可以使用随机数进行测试。测试用例的思考要出现在编码前和编码后,编码前是
指导编码,编码后是验证,这样才能将写好的代码交付。

  1. int main(void)
  2. {
  3.         int a[10];
  4.         int i = 0;
  5.         int n = 100;
  6.         
  7.         while (n--) {
  8.         printf("\nbefore adjust:\n");
  9.         for (i=0;i<10;i++) {
  10.                 a[i] = random() % 100;
  11.                 printf("%d ",a[i]);
  12.         }
  13.         adjust(a,10);
  14.         printf("\nafter adjust:\n");        
  15.         for (i=0;i<10;i++) {
  16.                 printf("%d ",a[i]);
  17.         }
  18.         putchar('\n');
  19.         }
  20.         return 0;
  21. }
-----------------------------------------------------------------------------------------------------------------
四、问题的扩展。
 假如问题现在要改为把数组中的数按照大小分为两部分,所有的负数都放在非负数的前面。
 或,把数组中的数分为两部分,能被3整除的数都放在不能被3整除数到前面。

其实,这些问题可以将其抽象下,就是他们的逻辑框架是一样的,将一个数组分为两部分,
只是判定的标准不一样。这样可以将判断的标准通过参数的形式传入到函数中,这种方式
在内核中比比皆是。

  1. bool is_even(int x)
  2. {
  3.         return (x & 0x01) == 1;
  4. }

  5. bool is_minus(int x)
  6. {
  7.         if (x < 0)
  8.             return 1;
  9.         else
  10.             return 0;
  11. }


  12. void adjust(int a[],int len,bool (*judge)(int))
  13. {
  14.         if (a == NULL || len == 0)
  15.             return ;
  16.         int i = 0, j = len - 1;
  17.         while (i < j) {
  18.                 while (i < j && judge(a[i])) i++;
  19.                 while (i < j && !judge(a[j])) j--;
  20.                 if (i < j) swap(a[i],a[j]);
  21.         }
  22.         return ;
  23. }
-------------------------------------------------------------------------------------------------------------
该编码的思想很经典,有让人为之一震的感觉,希望以后能培养出自己抽象问题的能力。

阅读(1758) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~