【编程珠玑】第五章 编程小事

一,概述

主要讲解如何保证编程的正确性。在程序中加入断言(assert(断言内容) //如果错误,则终止程序。否则正常执行)。

typdef //声明自定义类型

typedef int size; //声明int 型整数的别名

size array[4];

typedef struct tagNode { char *pItem;  pNode *pNext; } *pNode;

测试结构题大小的程序

#include "stdio.h" typedef struct tagNode { char *pItem; //32位 struct tagNode *pNext;//32位 } *pNode; int main() { printf("%d\n",sizeof(struct tagNode)); return 0; }

二,习题

5)测试、断言优化过程

for (i = 0; i < n - 1; ++i) assert(a[i] < a[i+1]);

如何利用二分的性质来进行处理还是一个问题。

一种办法是:

int bs(int *a, int b, int e, int v) { int *begin = a + b, *end = a + e, *mid; if (!a || b >= e) return -1; while (begin < end) { mid = begin + ((end - begin) >> 1); assert(*begin <= *mid && *mid <= *end); if (*mid > v) end = mid; else if (*mid < v) begin = mid + 1; else return mid - a; } return -1; }

但是这个方法需要多次使用才能检测出来,也就是可能在查找某两个数的时候不会报错,可能在查找别的几个数的时候就报错了。很多时候,这不是一种好选择。

根据第五题的题意,可以写如下代码来减少每次检测的量。

int bs(int *a, int b, int e, int v) { int *begin = a + b, *end = a + e, *mid, i = b; static int *record = 0; if (!a || b >= e) return -1; if (!record || record != a) { while (i < e && a[i] < a[i+1]) ++i; assert(i == e); } while (begin < end) { mid = begin + ((end - begin) >> 1); assert(*begin <= *mid && *mid <= *end); if (*mid > v) end = mid; else if (*mid < v) begin = mid + 1; else return mid - a; } return -1; }

加一个static变量来记录这个数组是否经过检测,来决定以后的检测还需要进行。

当然对于多个数组的检测,可以利用hash来处理,因为一般来说,数组的下标地址都是不一样的。

[html] view plain copy
  1. for(i=0;i<n-1;++i)
  2. assert(a[i]<a[i+1]);

如何利用二分的性质来进行处理还是一个问题。

一种办法是:

  1. intbs(int*a,intb,inte,intv)
  2. {
  3. int*begin=a+b,*end=a+e,*mid;
  4. if(!a||b>=e)return-1;
  5. while(begin<end)
  6. {
  7. mid=begin+((end-begin)>>1);
  8. assert(*begin<=*mid&&*mid<=*end);
  9. if(*mid>v)end=mid;
  10. elseif(*mid<v)begin=mid+1;
  11. elsereturnmid-a;
  12. }
  13. return-1;
  14. }

但是这个方法需要多次使用才能检测出来,也就是可能在查找某两个数的时候不会报错,可能在查找别的几个数的时候就报错了。很多时候,这不是一种好选择。

根据第五题的题意,可以写如下代码来减少每次检测的量。

  1. intbs(int*a,intb,inte,intv)
  2. {
  3. int*begin=a+b,*end=a+e,*mid,i=b;
  4. staticint*record=0;
  5. if(!a||b>=e)return-1;
  6. if(!record||record!=a)
  7. {
  8. while(i<e&&a[i]<a[i+1])++i;
  9. assert(i==e);
  10. }
  11. while(begin<end)
  12. {
  13. mid=begin+((end-begin)>>1);
  14. assert(*begin<=*mid&&*mid<=*end);
  15. if(*mid>v)end=mid;
  16. elseif(*mid<v)begin=mid+1;
  17. elsereturnmid-a;
  18. }
  19. return-1;
  20. }

加一个static变量来记录这个数组是否经过检测,来决定以后的检测还需要进行。

当然对于多个数组的检测,可以利用hash来处理,因为一般来说,数组的下标地址都是不一样的。

9,,serch.c 源程序

#include <stdio.h> #include <stdlib.h> #include <time.h> #define MAXN 1000000 typedef int DataType; DataType x[MAXN]; int n; /* Scaffolding */ int i = -999999; #define assert(v) { if ((v) == 0) printf(" binarysearch bug %d %d\n", i, n); } /* Alg 1: From Programming Pearls, Column 4: raw transliteration */ int binarysearch1(DataType t) { int l, u, m; l = 0; u = n-1; for (;;) { if (l > u) return -1; m = (l + u) / 2; if (x[m] < t) l = m+1; else if (x[m] == t) return m; else /* x[m] > t */ u = m-1; } } /* Alg 2: Make binarysearch1 more c-ish */ int binarysearch2(DataType t) { int l, u, m; l = 0; u = n-1; while (l <= u) { m = (l + u) / 2; if (x[m] < t) l = m+1; else if (x[m] == t) return m; else /* x[m] > t */ u = m-1; } return -1; } /* Alg 3: From PP, Col 8 */ int binarysearch3(DataType t) { int l, u, m; l = -1; u = n; while (l+1 != u) { m = (l + u) / 2; if (x[m] < t) l = m; else u = m; } if (u >= n || x[u] != t) return -1; return u; } /* Alg 4: From PP, Col 9 */ int binarysearch4(DataType t) { int l, p; if (n != 1000) return binarysearch3(t); l = -1; if (x[511] < t) l = 1000 - 512; if (x[l+256] < t) l += 256; if (x[l+128] < t) l += 128; if (x[l+64 ] < t) l += 64; if (x[l+32 ] < t) l += 32; if (x[l+16 ] < t) l += 16; if (x[l+8 ] < t) l += 8; if (x[l+4 ] < t) l += 4; if (x[l+2 ] < t) l += 2; if (x[l+1 ] < t) l += 1; p = l+1; if (p >= n || x[p] != t) return -1; return p; } /* Alg 9: Buggy, from Programming Pearls, Column 5 */ int sorted() { int i; for (i = 0; i < n-1; i++) if (x[i] > x[i+1]) return 0; return 1; } int binarysearch9(DataType t) { int l, u, m; /* int oldsize, size = n+1; */ l = 0; u = n-1; while (l <= u) { /* oldsize = size; size = u - l +1; assert(size < oldsize); */ m = (l + u) / 2; /* printf(" %d %d %d\n", l, m, u); */ if (x[m] < t) l = m; else if (x[m] > t) u = m; else { /* assert(x[m] == t); */ return m; } } /* assert(x[l] > t && x[u] < t); */ return -1; } /* Alg 21: Simple sequential search */ int seqsearch1(DataType t) { int i; for (i = 0; i < n; i++) if (x[i] == t) return i; return -1; } /* Alg 22: Faster sequential search: Sentinel */ int seqsearch2(DataType t) { int i; DataType hold = x[n]; x[n] = t; for (i = 0; ; i++) if (x[i] == t) break; x[n] = hold; if (i == n) return -1; else return i; } /* Alg 23: Faster sequential search: loop unrolling */ int seqsearch3(DataType t) { int i; DataType hold = x[n]; x[n] = t; for (i = 0; ; i+=8) { if (x[i] == t) { break; } if (x[i+1] == t) { i += 1; break; } if (x[i+2] == t) { i += 2; break; } if (x[i+3] == t) { i += 3; break; } if (x[i+4] == t) { i += 4; break; } if (x[i+5] == t) { i += 5; break; } if (x[i+6] == t) { i += 6; break; } if (x[i+7] == t) { i += 7; break; } } x[n] = hold; if (i == n) return -1; else return i; } /* Scaffolding to probe one algorithm */ void probe1() { int i; DataType t; while (scanf("%d %d", &n, &t) != EOF) { for (i = 0; i < n; i++) x[i] = 10*i; printf(" %d\n", binarysearch9(t)); } } /* Torture test one algorithm */ #define s seqsearch3 void test(int maxn) { int i; for (n = 0; n <= maxn; n++) { printf("n=%d\n", n); /* distinct elements (plus one at top) */ for (i = 0; i <= n; i++) x[i] = 10*i; for (i = 0; i < n; i++) { assert(s(10*i) == i); assert(s(10*i - 5) == -1); } assert(s(10*n - 5) == -1); assert(s(10*n) == -1); /* equal elements */ for (i = 0; i < n; i++) x[i] = 10; if (n == 0) { assert(s(10) == -1); } else { assert(0 <= s(10) && s(10) < n); } assert(s(5) == -1); assert(s(15) == -1); } } /* Timing */ int p[MAXN]; void scramble(int n) { int i, j; DataType t; for (i = n-1; i > 0; i--) { j = (RAND_MAX*rand() + rand()) % (i + 1); t = p[i]; p[i] = p[j]; p[j] = t; } } void timedriver() { int i, algnum, numtests, test, start, clicks; while (scanf("%d %d %d", &algnum, &n, &numtests) != EOF) { for (i = 0; i < n; i++) x[i] = i; for (i = 0; i < n; i++) p[i] = i; scramble(n); start = clock(); for (test = 0; test < numtests; test++) { for (i = 0; i < n; i++) { switch (algnum) { case 1: assert(binarysearch1(p[i]) == p[i]); break; case 2: assert(binarysearch2(p[i]) == p[i]); break; case 3: assert(binarysearch3(p[i]) == p[i]); break; case 4: assert(binarysearch4(p[i]) == p[i]); break; case 9: assert(binarysearch9(p[i]) == p[i]); break; case 21: assert(seqsearch1(p[i]) == p[i]); break; case 22: assert(seqsearch2(p[i]) == p[i]); break; case 23: assert(seqsearch3(p[i]) == p[i]); break; } } } clicks = clock() - start; printf("%d\t%d\t%d\t%d\t%g\n", algnum, n, numtests, clicks, 1e9*clicks/((float) CLOCKS_PER_SEC*n*numtests)); } } /* Main */ int main() { /* probe1(); */ /* test(25); */ timedriver(); return 0; }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值