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

一,概述

        主要讲解如何保证编程的正确性。在程序中加入断言(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]);  

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

一种办法是:

[cpp]  view plain copy
  1. int bs(int *a, int b, int e, int v)  
  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.         else if (*mid < v) begin = mid + 1;  
  11.         else return mid - a;  
  12.     }  
  13.     return -1;  
  14. }  

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

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

[cpp]  view plain copy
  1. int bs(int *a, int b, int e, int v)  
  2. {  
  3.     int *begin = a + b, *end = a + e, *mid, i = b;  
  4.     static int *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.   
  12.     while (begin < end)  
  13.     {  
  14.         mid = begin + ((end - begin) >> 1);  
  15.         assert(*begin <= *mid && *mid <= *end);  
  16.         if (*mid > v) end = mid;  
  17.         else if (*mid < v) begin = mid + 1;  
  18.         else return mid - a;  
  19.     }  
  20.     return -1;  
  21. }  

加一个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;
}


你可能感兴趣的:(Algorithm,编程,struct,测试,search,float)