<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Doglog.net &#187; 笔记</title>
	<atom:link href="http://blog.doglog.net/tag/%e7%ac%94%e8%ae%b0/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.doglog.net</link>
	<description>本站点不再更新，请直接访问www.doglog.net</description>
	<lastBuildDate>Sun, 21 Jun 2009 09:13:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Notes of C Programming FAQs (5)</title>
		<link>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-5/</link>
		<comments>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-5/#comments</comments>
		<pubDate>Wed, 13 May 2009 01:14:42 +0000</pubDate>
		<dc:creator>jx</dc:creator>
				<category><![CDATA[C Programming FAQs]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[FAQ]]></category>
		<category><![CDATA[笔记]]></category>

		<guid isPermaLink="false">http://blog.doglog.net/?p=675</guid>
		<description><![CDATA[下面是一些通常的检查要点:
² 未初始化的局部变量
² 整数上溢, 特别是在一些16 比特的机器上, 一些中间计算结果可能上溢, 象a * b / c
² 未定义的求值顺序
² 忽略了外部函数的说明, 特别是返回值不是int 的函数, 或是参数“缩小” 或可变的函数
² 复引用空指针
² malloc/free 的不适当使用: 假设malloc 的内存都被清零、已释放的内存还可用、再次释放已释放内存、malloc 的内部被破坏
² 指针类常规问题
² printf() 格式与参数不符, 特别是用%d 输出long int
² 试图分配的内存大小超出一个unsigned int 类型的范围, 特别是在内存有限的机器上
² 数组边界问题, 特别是暂时的小缓冲, 也许用于sprinf() 来构造一个字符串
² 错误的假设了typedef 的映射类型, 特别是size t
² 浮点问题
² 任何你自己认为聪明的在特定机器上的机器代码生成小技巧
“Segmentation violation”, “Bus error” 和“General protectionfault” 意味着什么？
通常, 这意味着你的程序试图访问不该访问的内存地址, 一般是由于堆栈出错或是不正确的使用指针。可能的原因有: 局部数组溢出(用堆栈分配的自动变量);不小心, 用了空指针、未初始化指针、地址未对齐的指针或其它没有适当分配的指针; malloc 内部被破坏; [...]]]></description>
			<content:encoded><![CDATA[<p>下面是一些通常的检查要点:<br />
² 未初始化的局部变量<br />
² 整数上溢, 特别是在一些16 比特的机器上, 一些中间计算结果可能上溢, 象a * b / c<br />
² 未定义的求值顺序<br />
² 忽略了外部函数的说明, 特别是返回值不是int 的函数, 或是参数“缩小” 或可变的函数<br />
² 复引用空指针<br />
² malloc/free 的不适当使用: 假设malloc 的内存都被清零、已释放的内存还可用、再次释放已释放内存、malloc 的内部被破坏<br />
² 指针类常规问题<br />
² printf() 格式与参数不符, 特别是用%d 输出long int<br />
² 试图分配的内存大小超出一个unsigned int 类型的范围, 特别是在内存有限的机器上<br />
² 数组边界问题, 特别是暂时的小缓冲, 也许用于sprinf() 来构造一个字符串<br />
² 错误的假设了typedef 的映射类型, 特别是size t<br />
² 浮点问题<br />
² 任何你自己认为聪明的在特定机器上的机器代码生成小技巧</p>
<p>“Segmentation violation”, “Bus error” 和“General protectionfault” 意味着什么？<br />
通常, 这意味着你的程序试图访问不该访问的内存地址, 一般是由于堆栈出错或是不正确的使用指针。可能的原因有: 局部数组溢出(用堆栈分配的自动变量);不小心, 用了空指针、未初始化指针、地址未对齐的指针或其它没有适当分配的指针; malloc 内部被破坏; 函数调用参数不匹配, 特别是如果用了指针, 两个可能出错的函数是scanf()和fprintf() (确定他的第一个参数是FILE *)。</p>
<p>“印第安山风格指南” (Indian Hill Style Guide)</p>
<p>用gcc -Wall -pedantic替代lint</p>
<p>怎样显示一个百分比或“转动的短棒” 的进展表示器？<br />
这个简单的事情, 你可以做到相当的可移植。输出字符’\r’ 通常可以得到一个回车而没有换行, 这样你就可以复写当前行。字符’\b’ 代表退格, 通常会使光标左移一格。记住要调用fflush()。</p>
<p>使用数据库来取代平坦文件</p>
<p>怎样抓获或忽略像control-C 这样的键盘中断？<br />
基本步骤是调用signal()：<br />
#include &lt;signal.h&gt;<br />
singal(SIGINT, SIG_IGN);<br />
就可以忽略中断信号, 或者:<br />
extern void func(int);<br />
signal(SIGINT, func);<br />
使程序在收到中断信号时, 调用函数func()。</p>
<p>怎样判断机器的字节顺序是高字节在前还是低字节在前？<br />
有个使用指针的方法：</p>
<pre><code>
int x = 1;
if(*(char *)&#038;x == 1)
    	printf("little-endian\n");
else
    	printf("big-endian\n");
</code></pre>
<p>另外一个可能是用联合。</p>
<p>从其他语言转换到C的工具：p2c, ptoc, f2c</p>
<p>由一个日期, 怎样知道是星期几？<br />
这个由Tomohiko Sakamoto 提供的优雅的代码:</p>
<pre><code>
int dayofweek(int y, int m, int d) /* 0 = Sunday */
{
        static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
        y -= m &lt; 3;
        return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}
</code></pre>
<p>自打印程序：</p>
<pre><code>
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);}
</code></pre>
<p>还有一个有James Hu 发布的改进版：</p>
<pre><code>
#define q(k)main(){return!puts(#k"\nq("#k")");}
q(#define q(k)main(){return!puts(#k"\nq("#k")");})
</code></pre>
<p>什么是“达夫设备” (Duff’s Device)？<br />
这是个很棒的迂回循环展开法, 由Tom Duff 在Lucasfilm 时所设计。它的“传统” 形态, 是用来复制多个字节:</p>
<pre><code>
register n = (count + 7) / 8; /* count > 0 assumed */
switch (count % 8)
{
case 0: do { *to = *from++;
case 7:      *to = *from++;
case 6:      *to = *from++;
case 5:      *to = *from++;
case 4:      *to = *from++;
case 3:      *to = *from++;
case 2:      *to = *from++;
case 1:      *to = *from++;
            	} while (--n &gt; 0);
}
</code></pre>
<p>这里count 个字节从from 指向的数组复制到to 指向的内存地址(这是个内存映射的输出寄存器, 这也是为什么它没有被增加)。它把swtich 语句和复制8 个字节的循环交织在一起, 从而解决了剩余字节的处理问题(当count 不是8 的倍数时)。相信不相信, 象这样的把case 标志放在嵌套在swtich 语句内的模块中是合法的。当他公布这个技巧给C 的开发者和世界时, Duff 注意到C 的swtich 语法, 特别是“跌落” 行为, 一直是被争议的, 而“这段代码在争论中形成了某种论据, 但我不清楚是赞成还是反对”。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes of C Programming FAQs (4)</title>
		<link>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-4/</link>
		<comments>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-4/#comments</comments>
		<pubDate>Wed, 13 May 2009 01:10:54 +0000</pubDate>
		<dc:creator>jx</dc:creator>
				<category><![CDATA[C Programming FAQs]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[FAQ]]></category>
		<category><![CDATA[笔记]]></category>

		<guid isPermaLink="false">http://blog.doglog.net/?p=672</guid>
		<description><![CDATA[\n 在scanf 格式串中不表示等待换行符, 而是读取并放弃所有的空白字符。
在scanf() 转换数字的时候, 它遇到的任何非数字字符都会终止转换并被保留在输入流中。因此, 除非采用了其它的步骤, 那么未预料到的非数字输入会不断“阻塞” scanf(): scanf() 永远都不能越过错误的非数字字符而处理后边的合法数字字符。
通常先用类似fgets() 的函数读入整行, 然后再用sscanf() 或其它技术解释。
要避免溢出问题, 你可以使用限制长度的sprintf() 版本, 即snprintf()。这样使用：snprintf(buf, bufsize, &#8220;You typed \&#8221;%s\&#8221;", answer);
snprintf() 在几个stdio 库中已经提供好几年了, 包括GNU 和4.4bsd。在C99中已经被标准化了。作为一个额外的好处, C99 的snprintf() 提供了预测任意sprintf() 调用所需的缓冲区大小的方法。C99 的snprintf() 返回它可能放到缓冲区的字符数, 而它又可以用0 作为缓冲区大小进行调用。因此nch = snprintf(NULL, 0, fmtstring, /* 其它参数*/ );这样的调用就可以预测出格式串扩展后所需要的字符数。
没有什么标准的办法可以丢弃标准输入流的未读取字符, 即使有, 那也不够,因为未读取字符也可能来自其它的操作系统级的输入缓冲区。
读取二进制数据文件的时候你应该用“rb” 调用fopen(), 确保不会发生文本文件的解释。类似的, 写二进制文件时, 使用“wb”。注意文本/二进制区别只是发生在文件打开时: 一旦文件打开之后, 在其上调用何种I/O 函数无关紧要。
怎样产生标准分布或高斯分布的随机数？
这里有一个由Marsaglia 首创Knuth 推荐的方法:

#include &#60;stdlib.h&#62;
#include &#60;math.h&#62;
double gaussrand()
{
 [...]]]></description>
			<content:encoded><![CDATA[<p>\n 在scanf 格式串中不表示等待换行符, 而是读取并放弃所有的空白字符。</p>
<p>在scanf() 转换数字的时候, 它遇到的任何非数字字符都会终止转换并被保留在输入流中。因此, 除非采用了其它的步骤, 那么未预料到的非数字输入会不断“阻塞” scanf(): scanf() 永远都不能越过错误的非数字字符而处理后边的合法数字字符。</p>
<p>通常先用类似fgets() 的函数读入整行, 然后再用sscanf() 或其它技术解释。</p>
<p>要避免溢出问题, 你可以使用限制长度的sprintf() 版本, 即snprintf()。这样使用：snprintf(buf, bufsize, &#8220;You typed \&#8221;%s\&#8221;", answer);<br />
snprintf() 在几个stdio 库中已经提供好几年了, 包括GNU 和4.4bsd。在C99中已经被标准化了。作为一个额外的好处, C99 的snprintf() 提供了预测任意sprintf() 调用所需的缓冲区大小的方法。C99 的snprintf() 返回它可能放到缓冲区的字符数, 而它又可以用0 作为缓冲区大小进行调用。因此nch = snprintf(NULL, 0, fmtstring, /* 其它参数*/ );这样的调用就可以预测出格式串扩展后所需要的字符数。</p>
<p>没有什么标准的办法可以丢弃标准输入流的未读取字符, 即使有, 那也不够,因为未读取字符也可能来自其它的操作系统级的输入缓冲区。</p>
<p>读取二进制数据文件的时候你应该用“rb” 调用fopen(), 确保不会发生文本文件的解释。类似的, 写二进制文件时, 使用“wb”。注意文本/二进制区别只是发生在文件打开时: 一旦文件打开之后, 在其上调用何种I/O 函数无关紧要。</p>
<p>怎样产生标准分布或高斯分布的随机数？<br />
这里有一个由Marsaglia 首创Knuth 推荐的方法:</p>
<pre><code>
#include &lt;stdlib.h&gt;
#include &lt;math.h&gt;
double gaussrand()
{
    	static double V1, V2, S;
    	static int phase = 0;
    	double X;
    	if(phase == 0) {
    	    	do {
            	double U1 = (double)rand() / RAND_MAX;
            	double U2 = (double)rand() / RAND_MAX;
            	V1 = 2 * U1 - 1;
            	V2 = 2 * U2 - 1;
            	S = V1 * V1 + V2 * V2;
    	    	} while(S &gt;= 1 || S == 0);
    	    	X = V1 * sqrt(-2 * log(S) / S);
    	} else
        	X = V2 * sqrt(-2 * log(S) / S);
    	phase = 1 - phase;
    	return X;
}
</code></pre>
<p>大多数电脑都是用二进制来表示浮点和整数的。在十进制里, 0.1 是个简单、精确的小数, 但是用二进制表示起来却是个循环小数0.0001100110011 . . . 。</p>
<p>“参数默认晋级” 规则适用于在可变参数中的可变动部分: 参数类型为float 的总是晋级(扩展) 到double, char 和short int 晋级到int。所以va arg(arpg, float)是错误的用法。应该总是用va arg(arpg, double)。</p>
<p>程序在执行用之前就崩溃了, 用调试器单步跟进, 在main() 之前就死了。<br />
也许你定义了一个或多个非常大的局部数组(超过上千字节)。许多系统只有固定大小的堆栈, 即使那些自动动态堆栈分配的系统也会因为一次性要分配大段堆栈而失败。<br />
一般对大规模数组, 定义为静态的数组会更好。如果由于递归的原因, 每次都需要一组新的数组, 可以用malloc() 动态申请内存。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes of C Programming FAQs (3)</title>
		<link>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-3/</link>
		<comments>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-3/#comments</comments>
		<pubDate>Wed, 13 May 2009 01:09:07 +0000</pubDate>
		<dc:creator>jx</dc:creator>
				<category><![CDATA[C Programming FAQs]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[FAQ]]></category>
		<category><![CDATA[笔记]]></category>

		<guid isPermaLink="false">http://blog.doglog.net/?p=670</guid>
		<description><![CDATA[一般地说, 使用指针的时候, 你必须总是考虑内存分配, 除非明确知道编译器替你做了此事。
那么返回字符串或其它集合的争取方法是什么呢？
返回指针必须是静态分配的缓冲区, 或者调用者传入的缓冲区, 或者用malloc() 获得的内存, 但不能是局部(自动) 数组。
sizeof(char) 严格为1。
一个常见的bug 是用malloc(strlen(s)) 而不是strlen(s) + 1。
当你调用free() 的时候, 传入指针指向的内存被释放, 但调用函数的指针值可能保持不变, 因为C 的按值传参语义意味着被调函数永远不会永久改变参数的值。
calloc(m, n) 本质上等价于 p = malloc(m * n); memset(p, 0, m * n); 填充的零是全零, 因此不能确保生成有用的空指针值或浮点零值。free() 可以安全地用来释放calloc() 分配的内存。
C语言中的字符常数是int 型, 因此sizeof(’a’) 是sizeof(int),这是另一个与C++ 不同的地方。
如果你认为“if((a == b) == TRUE)” 比“if(a == b)” 好, 为什么就此打住呢？为什么不使用“if(((a == b) == TRUE) == TRUE)” 呢?
如果宏体内的语句都是简单语句, [...]]]></description>
			<content:encoded><![CDATA[<p>一般地说, 使用指针的时候, 你必须总是考虑内存分配, 除非明确知道编译器替你做了此事。</p>
<p>那么返回字符串或其它集合的争取方法是什么呢？<br />
返回指针必须是静态分配的缓冲区, 或者调用者传入的缓冲区, 或者用malloc() 获得的内存, 但不能是局部(自动) 数组。</p>
<p>sizeof(char) 严格为1。</p>
<p>一个常见的bug 是用malloc(strlen(s)) 而不是strlen(s) + 1。</p>
<p>当你调用free() 的时候, 传入指针指向的内存被释放, 但调用函数的指针值可能保持不变, 因为C 的按值传参语义意味着被调函数永远不会永久改变参数的值。</p>
<p>calloc(m, n) 本质上等价于 p = malloc(m * n); memset(p, 0, m * n); 填充的零是全零, 因此不能确保生成有用的空指针值或浮点零值。free() 可以安全地用来释放calloc() 分配的内存。</p>
<p>C语言中的字符常数是int 型, 因此sizeof(’a’) 是sizeof(int),这是另一个与C++ 不同的地方。</p>
<p>如果你认为“if((a == b) == TRUE)” 比“if(a == b)” 好, 为什么就此打住呢？为什么不使用“if(((a == b) == TRUE) == TRUE)” 呢?</p>
<p>如果宏体内的语句都是简单语句, 没有声明或循环, 那么还有一种技术, 就是写一个单独的, 用一个或多个逗号操作符分隔的表达式。这种技术还可以“返回” 一个值。</p>
<p>作为一般规则, 你应该把这些东西放入头(.h) 文件中:<br />
² 宏定义(预处理#defines)<br />
² 结构、联合和枚举声明<br />
² typedef 声明<br />
² 外部函数声明<br />
² 全局变量声明<br />
当声明或定义需要在多个文件中共享时, 尤其需要把它们放入头文件中。特别是, 永远不要把外部函数原型放到.c 文件中。<br />
另一方面, 如果定义或声明为一个.c 文件私有, 则最好留在.c 文件中。</p>
<p>我在文件的第一个声明就遇到奇怪的语法错误, 但是看上去没什么问题。可能你包含的最后一个头文件的最后一行缺一个分号。</p>
<p>C99 引入了对参数个数可变的函数式宏的正式支持。在宏“原型” 的末尾加上符号&#8230; (就像在参数可变的函数定义中), 宏定义中的伪宏__VA_ARGS__ 就会在调用时替换成可变参数。</p>
<p>“const char *p” (也可以写成“char const *p”) 声明了一个指向字符常量的指针, 因此不能改变它所指向的字符; “char * const p” 声明一个指向(可变) 字符的指针常量, 就是说, 你不能修改指针。</p>
<p>在使用符号粘接操作符## 连接两个宏的值(而不是名字) 时也要采用同样的“迂回战术”。</p>
<p>当你希望把宏参数转成字符串时,你可以使用新的预处理操作符# 和字符串常量连接(ANSI 的另一个新功能)</p>
<p>如果源和目的参数有重叠, memmove() 提供有保证的行为。而memcpy()则不能提供这样的保证, 因此可以实现得更加有效率。</p>
<p>保存getchar 的返回值的变量必须是int 型。getchar() 可能返回任何字符值, 包括EOF。如果把getchar 的返回值截为char 型, 则正常的字符可能会被错误的解释为EOF, 或者EOF 可能会被修改(尤其是char 型为无符号的时候), 从而永不出现。</p>
<p>在C 语言中, 只有输入例程试图读并失败以后才能得到文件结束符。换言之,C 的I/O 和Pascal 的不一样。通常你只需要检查输入例程的返回值, 例如, fgets()在遇到文件结束符的时候返回NULL。实际上, 在任何情况下, 都完全没有必要使用feof()。</p>
<p>我如何在printf 的格式串中输出一个’%’？我试过\%, 但是不行。<br />
只需要重复百分号: %%。<br />
\%不行, 因为反斜杠\ 是编译器的转义字符, 而这里我们的问题最终是printf的转义字符。</p>
<p>在printf 中使用%lf 不正确。scanf() 需要%lf,printf 的%f 标识符的确既可以输出浮点数又可以输出双精度数。printf() 的确接受%Lf, 用于输出长双精度数。</p>
<p>对于size t 那样的类型定义, 当我不知道它到底是long 还是其它类型的时候, 我应该使用什么样的printf 格式呢？<br />
把那个值转换为一个已知的长度够大的类型, 然后使用与之对应的printf 格式。例如, 输出某种类型的长度, 你可以使用<br />
printf(&#8220;%lu&#8221;, (unsigned long)sizeof(thetype));</p>
<p>我如何用printf 实现可变的域宽度？就是说, 我想在运行时确定宽度而不是使用%8d？<br />
printf(&#8220;%*d&#8221;, width, x) 就能达到你的要求。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes of C Programming FAQs (2)</title>
		<link>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-2/</link>
		<comments>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-2/#comments</comments>
		<pubDate>Wed, 13 May 2009 01:07:16 +0000</pubDate>
		<dc:creator>jx</dc:creator>
				<category><![CDATA[C Programming FAQs]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[FAQ]]></category>
		<category><![CDATA[笔记]]></category>

		<guid isPermaLink="false">http://blog.doglog.net/?p=667</guid>
		<description><![CDATA[*((condition) ? &#038;a : &#038;b) = complicated_expression;
*p++ 和*(p++) 等价,如果副作用的顺序无关紧要也可以使用++*p。
对函数extern int f(int *);用引用方式传入一个常数。在C99 中, 可以使用“复合常量”:f((int[]){5});
最初, 一个函数指针必须用* 操作符(和一对额外的括弧) “转换为” 一个“真正的” 函数才能调用:
int r, func(), (*fp)() = func;
r = (*fp)();
而函数总是通过指针进行调用的, 所有“真正的” 函数名总是隐式的退化为指针(在表达式中, 正如在初始化时一样。)。这个推论表明无论fp 是函数名和函数的指针
r = fp();
ANSI C 标准实际上接受后边的解释, 这意味着* 操作符不再需要, 尽管依然允许。
execl(&#8220;/bin/sh&#8221;, &#8220;sh&#8221;, &#8220;-c&#8221;, &#8220;date&#8221;, (char *)0);
如果省略最后一个参数的(char *) 转换, 则编译器无从知道这是一个空指针,从而当作一个0 传入。(注意很多Unix 手册在这个例子上都弄错了。)
有两条简单规则你必须遵循:
1. 当你在源码中需要空指针常数时, 用“0” 或“NULL”。
2. 如果在函数调用中“0” 或“NULL” 用作参数, 把它转换成被调函数需要的指针类型
一个图形胜过千言万语。声明
char a[] [...]]]></description>
			<content:encoded><![CDATA[<p>*((condition) ? &#038;a : &#038;b) = complicated_expression;</p>
<p>*p++ 和*(p++) 等价,如果副作用的顺序无关紧要也可以使用++*p。</p>
<p>对函数extern int f(int *);用引用方式传入一个常数。在C99 中, 可以使用“复合常量”:f((int[]){5});</p>
<p>最初, 一个函数指针必须用* 操作符(和一对额外的括弧) “转换为” 一个“真正的” 函数才能调用:<br />
int r, func(), (*fp)() = func;<br />
r = (*fp)();<br />
而函数总是通过指针进行调用的, 所有“真正的” 函数名总是隐式的退化为指针(在表达式中, 正如在初始化时一样。)。这个推论表明无论fp 是函数名和函数的指针<br />
r = fp();<br />
ANSI C 标准实际上接受后边的解释, 这意味着* 操作符不再需要, 尽管依然允许。</p>
<p>execl(&#8220;/bin/sh&#8221;, &#8220;sh&#8221;, &#8220;-c&#8221;, &#8220;date&#8221;, (char *)0);<br />
如果省略最后一个参数的(char *) 转换, 则编译器无从知道这是一个空指针,从而当作一个0 传入。(注意很多Unix 手册在这个例子上都弄错了。)</p>
<p>有两条简单规则你必须遵循:<br />
1. 当你在源码中需要空指针常数时, 用“0” 或“NULL”。<br />
2. 如果在函数调用中“0” 或“NULL” 用作参数, 把它转换成被调函数需要的指针类型</p>
<p>一个图形胜过千言万语。声明<br />
char a[] = &#8220;hello&#8221;;<br />
char *p = &#8220;world&#8221;;<br />
将会初始化下图所示的数据结果:</p>
<pre><code>
   +---+---+---+---+---+---+
a: | h | e | l | l | o |\0 |
   +---+---+---+---+---+---+
   +-----+     +---+---+---+---+---+---+
p: |  *======&gt; | w | o | r | l | d |\0 |
   +-----+     +---+---+---+---+---+---+
</code></pre>
<p>说数组和指针“等价”不表示它们相同, 甚至也不能互换。它的意思是说数组和指针的算法定义可以用指针方便的访问数组或者模拟数组。</p>
<p>一个T 的数组类型的左值如果出现在表达式中会蜕变为一个指向数组第一个成员的指针(除了三种例外情况); 结果指针的类型是T 的指针。</p>
<p>一旦数组出现在表达式中, 编译器会隐式地生成一个指向数组第一个成员地指针, 就像程序员写出了&#038;a[0] 一样。例外的情况是, 数组为sizeof 或&#038;操作符的操作数, 或者为字符数组的字符串初始值。</p>
<p>C99引入了变长数组(VLA),局部数组的大小可以用变量或其它表达式设置, 可能也包括函数参数。</p>
<p>如果你向函数传递二位数组:<br />
int array[NROWS][NCOLUMNS];<br />
f(array);<br />
那么函数的声明必须匹配:<br />
void f(int a[][NCOLUMNS])<br />
{ &#8230; }<br />
或者<br />
void f(int (*ap)[NCOLUMNS]) /* ap 是个数组指针*/<br />
{ &#8230; }</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes of C Programming FAQs (1)</title>
		<link>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-1/</link>
		<comments>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-1/#comments</comments>
		<pubDate>Wed, 13 May 2009 00:59:01 +0000</pubDate>
		<dc:creator>jx</dc:creator>
				<category><![CDATA[C Programming FAQs]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[FAQ]]></category>
		<category><![CDATA[笔记]]></category>

		<guid isPermaLink="false">http://blog.doglog.net/?p=653</guid>
		<description><![CDATA[尽管字符类型(尤其是无符号字符型) 可以当成“小” 整型使用, 但由于不可预知的符号扩展和代码增大有时这样做可能得不偿失。
定义是分配空间并赋初值(如果有) 的声明。
永远不要把外部函数的原型放到.c 文件中: 通常它与定义的一致性不能得到检查, 而矛盾的原型比不用还糟糕。
在extern int f();和int f();之间并没有实质的区别。
使用cdecl 程序, 它可以把英文翻译成C 或者把C 翻译成英文
一本好的C 语言书都会解释如何“从内到外” 解释和理解这样复杂的C 语言声明(“模拟声明使用”)。
在范围内没有声明就调用(可能是第一次调用在函数的定义之前) 的函数被认为返回整型(int) (且没有任何参数类型信息), 如果函数在后边声明或定义成其它类型就会导致矛盾。所有函数(非整型函数一定要) 必须在调用之前声明。
calloc() 获得的内存为全零, 但这对指针和浮点值不一定有用
以下的初始化有什么区别？char a[] = &#8220;string literal&#8221;; char *p = &#8220;string literal&#8221;; 当我向p[i] 赋值的时候, 我的程序崩溃了。
字符串常量有两种稍有区别的用法。用作数组初始值(如同在char a[] 的声明中), 它指明该数组中字符的初始值。其它情况下, 它会转化为一个无名的静态字符数组, 可能会存储在只读内存中, 这就是造成它不一定能被修改。在表达式环境中, 数组通常被立即转化为一个指针, 因此第二个声明把p 初始化成指向无名数组的第一个元素。
int (*fp)() = func;
这样声明结构的代码: struct name { int namelen; charnamestr[1];}; 然后又使用一些内存分配技巧使namestr [...]]]></description>
			<content:encoded><![CDATA[<p>尽管字符类型(尤其是无符号字符型) 可以当成“小” 整型使用, 但由于不可预知的符号扩展和代码增大有时这样做可能得不偿失。</p>
<p>定义是分配空间并赋初值(如果有) 的声明。</p>
<p>永远不要把外部函数的原型放到.c 文件中: 通常它与定义的一致性不能得到检查, 而矛盾的原型比不用还糟糕。</p>
<p>在extern int f();和int f();之间并没有实质的区别。</p>
<p>使用cdecl 程序, 它可以把英文翻译成C 或者把C 翻译成英文</p>
<p>一本好的C 语言书都会解释如何“从内到外” 解释和理解这样复杂的C 语言声明(“模拟声明使用”)。</p>
<p>在范围内没有声明就调用(可能是第一次调用在函数的定义之前) 的函数被认为返回整型(int) (且没有任何参数类型信息), 如果函数在后边声明或定义成其它类型就会导致矛盾。所有函数(非整型函数一定要) 必须在调用之前声明。</p>
<p>calloc() 获得的内存为全零, 但这对指针和浮点值不一定有用</p>
<p>以下的初始化有什么区别？char a[] = &#8220;string literal&#8221;; char *p = &#8220;string literal&#8221;; 当我向p[i] 赋值的时候, 我的程序崩溃了。<br />
字符串常量有两种稍有区别的用法。用作数组初始值(如同在char a[] 的声明中), 它指明该数组中字符的初始值。其它情况下, 它会转化为一个无名的静态字符数组, 可能会存储在只读内存中, 这就是造成它不一定能被修改。在表达式环境中, 数组通常被立即转化为一个指针, 因此第二个声明把p 初始化成指向无名数组的第一个元素。</p>
<p>int (*fp)() = func;</p>
<p>这样声明结构的代码: struct name { int namelen; charnamestr[1];}; 然后又使用一些内存分配技巧使namestr 数组用起来好像有多个元素。这种技术十分普遍。这些“亲密” 结构都必须小心使用, 因为只有程序员知道它的大小, 而编译器却一无所知。<br />
C99 引入了“灵活数组域” 概念, 允许结构的最后一个域省略数组大小。这为类似问题提供了一个圆满的解决方案。</p>
<p>如何向接受结构参数的函数传入常数值？<br />
传统的C 没有办法生成匿名结构值; 你必须使用临时结构变量或一个小的结构生成函数。<br />
C99 标准引入了“复合常量” (compound literals); 复合常量的一种形式就可以允许结构常量。例如, 向假想plotpoint() 函数传入一个坐标对常数, 可以调用plotpoint((struct point){1, 2});<br />
与“指定初始值” (designated initializers) (C99 的另一个功能) 结合, 也可以用成员名称确定成员值:plotpoint((struct point){.x=1, .y=2});</p>
<p>如何确定域在结构中的字节偏移？<br />
ANSI C 在&lt;stddef.h&gt; 中定义了offsetof() 宏, 用offsetof(struct s, f) 可以计算出域f 在结构s 中的偏移量。如果出于某种原因, 你需要自己实现这个功能, 可以使用下边这样的代码:<br />
#define offsetof(type, f) ((size_t)<br />
((char *)&#038;((type *)0)-&gt;f &#8211; (char *)(type *)0))<br />
这种实现不是100% 的可移植; 某些编译器可能会合法地拒绝接受。</p>
<p>a[i] = i++; 不能工作</p>
<p>表达式: a ˆ= b ˆ= a ˆ= b不具有可移植性。它试图在序列点之间两次修改变量a, 而这是无定义的。</p>
<p>如果一个表达式和程序变得未定义, 则它的所有方面都会变成未定义。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.doglog.net/2009/05/notes-of-c-programming-faqs-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes of UNIX SYSTEMS Programming (1)</title>
		<link>http://blog.doglog.net/2009/05/notes-of-unix-systems-programming-1/</link>
		<comments>http://blog.doglog.net/2009/05/notes-of-unix-systems-programming-1/#comments</comments>
		<pubDate>Thu, 07 May 2009 07:39:56 +0000</pubDate>
		<dc:creator>jx</dc:creator>
				<category><![CDATA[UNIX SYSTEMS Programming]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[笔记]]></category>

		<guid isPermaLink="false">http://blog.doglog.net/?p=613</guid>
		<description><![CDATA[(from Chapter 1 to Chapter 2, except for the Exercises)
(Example 1.5) The following code segment does not have a buffer overflow.
char buf[80];
printf(&#8220;Enter your first name:&#8221;);
scanf(&#8220;%79s&#8221;, buf);
(Program 1.1) print address of pointers using %p:
int x;
printf(&#8220;&#38;x : %pn&#8221;, (void *) &#38;x);
Static variables can make a program unsafe for threaded execution. In other words, they are not thread-safe.
External [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>(from <em>Chapter 1</em> to <em>Chapter 2</em>, except for the <em>Exercise</em>s)</p></blockquote>
<p><em>(Example 1.5)</em> The following code segment does not have a buffer overflow.</p>
<blockquote><p><em>char</em> buf[80];<br />
printf(&#8220;Enter your first name:&#8221;);<br />
scanf(&#8220;%79s&#8221;, buf);</p></blockquote>
<p><em>(Program 1.1)</em> print address of pointers using %p:</p>
<blockquote><p><em>int</em> x;<br />
printf(&#8220;&amp;x : %pn&#8221;, (<em>void</em> *) &amp;x);</p></blockquote>
<p>Static variables can make a program unsafe for threaded execution. In other words, they are not thread-safe.</p>
<p>External static variables also make code more difficult to debug because successive invocations of a function that references a static variable may behave in unexpected ways.</p>
<p>For these reasons, avoid using static variables except under controlled circumstances.</p>
<p>A common mapping divides the program image into equal-sized pieces, called <em>page</em>s.</p>
<p>Standard approaches to handling errors in UNIX programs include the following.</p>
<ul>
<li>Print out an error message and exit the program (only in <em>main</em>).</li>
<li>Return -1 or <em>NULL</em>, and set an error indicator such as <em>errno</em>.</li>
<li>Return an error code.</li>
</ul>
<p>Guidelines for implementing functions: <em>(partial)</em></p>
<ul>
<li>Do not <em>exit</em> from functions.</li>
<li>Do not use <em>static</em> variables or dynamic memory allocation if automatic allocation will do just as well.</li>
<li>Analyze the consequences of interruptions by signals.</li>
<li>Carefully consider how the entire program terminates.</li>
</ul>
<p>In writing general library programs, you should avoid imposing unnecessary a priori limitations on sizes.</p>
<p>When using malloc or a related call, analyze whether to free the memory if an error occurs or when the function returns.</p>
<p><em>(using the C library function strtok to split a string into tokens)</em> The first call to <em>strtok</em> is different from subsequent calls. On the first call, pass the address of the string to parse as the first argument. On subsequent calls for parsing the same string, pass a <em>NULL</em>.</p>
<p><em>strtok</em> is not thread-safe<br />
<em>char</em> *strtok_r(<em>char</em> *restrict s, <em>const</em> <em>char</em> *restrict sep, <em>char</em> **restrict lasts);</p>
<p>Static variables are commonly used in the C implementation of a data structure as an object. The data structure and all the functions that access it are placed in a single source file, and the data structure is defined outside any function. The data structure has the <em>static</em> attribute, giving it internal linkage: it is private to that source file. <em>[...]</em> You can often make an object thread-safe by placing locking mechanisms in its access functions without affecting outside callers.</p>
<p><em>(Program 2.8)</em> use <em>fgets</em> instead of <em>gets</em> to prevent a buffer overrun on input.</p>
<p><em>[ISO C]</em> <em>extern</em> <em>char</em> **environ;</p>
<p>Be careful about calling <em>getenv</em> more than once without copying the first return string into a buffer. Some implementations of <em>getenv</em> use a static buffer for the return strings and overwrite the buffer on each call.</p>
<p><em>[ISO C]</em> <em>int</em> atexit(<em>void</em> (*func)(<em>void</em>));</p>
<p>The C <em>exit</em> function calls user-defined <em>exit</em> handlers that were registered by <em>atexit</em> in the reverse order of registration. After calling the user-defined handlers, <em>exit</em> flushes any open streams that have unwritten buffered data and then closes all open streams. Finally, <em>exit</em> removes all temporary files that were created by <em>tmpfile()</em> and then terminates control. Using the <em>return</em> statement from <em>main</em> has the same effect as calling <em>exit</em> with the corresponding status. Reaching the end of <em>main</em> has the same effect as calling <em>exit(0)</em>.</p>
<p>An abnormal termination may produce a core dump, and user-installed <em>exit</em> handlers are not called.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.doglog.net/2009/05/notes-of-unix-systems-programming-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《离散数学》6000字缩写笔记</title>
		<link>http://blog.doglog.net/2009/04/discrete-mathematics-in-6000-words/</link>
		<comments>http://blog.doglog.net/2009/04/discrete-mathematics-in-6000-words/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 13:32:23 +0000</pubDate>
		<dc:creator>jx</dc:creator>
				<category><![CDATA[阅读笔记]]></category>
		<category><![CDATA[离散数学]]></category>
		<category><![CDATA[笔记]]></category>
		<category><![CDATA[缩写]]></category>

		<guid isPermaLink="false">http://blog.doglog.net/?p=435</guid>
		<description><![CDATA[Discrete Mathematics (Fourth Edition)

离散数学（第四版）

6000字缩写笔记
1、PERT图与关键路径
2、后续子集算法：找0/1串最右边的0，如果有，把它置为1，后面的都置为0，否则算法终止。
3、Augusta Ada Byron 1815-1852
4、union intersection disjoint difference complement
5、集合S上的关系R可以具备下列特殊性质中的任何一个：
（1）如果对于S中的任意元素x，x R x为真，则称R是自反的（reflexive）
（2）如果只要x R y为真，y R x就为真，则称R是对称的（symmetric）
（3）如果只要x R y和y R z都为真，x R z都为真，则称R是传递的（transitive）
6、自反、对称和传递的关系称为等价关系（equivalence relation）
7、如果R是S上的等价关系，x∈S，则S中与x相关联的元素的集合称为包含x的等价类（equivalence class），记为[x]，所以[x] = {y∈S : y R x}
8、n = q m + r，q为商（quotient），r为余数（remainder）
9、模m的同余关系 congruence modulo m
10、Zm中：[x] + [y] = [x + y]，[x] [y] = [x y]，[x]y = [xy]
11、部分序，极大、极小元
12、哈斯图（Hasse Diagram），由下而上观察，图中所有的线段都看作是指向上方的
13、数学归纳法常用来验证算法
14、循环不变式：loop invariant
15、《算术》（Arithmetica）
16、两图同构，对应顶的度数首先相等
17、Leonhard Euler
18、多重图G中，包含G中所有的边恰好一次，并且第一个顶点和最后一个顶点不相同的通路称为欧拉通路（Euler path），起点和终点相同的称为欧拉回路（Euler [...]]]></description>
			<content:encoded><![CDATA[<p class="western" style="text-align: center;"><span style="font-size: small;"><strong>Discrete Mathematics (Fourth Edition)</strong></span></p>
<div></div>
<p class="western" style="text-align: center;"><span style="font-size: small;"><strong><span style="font-family: 宋体,SimSun;">离散数学（第四版）</span></strong></span></p>
<div style="text-align: center;"></div>
<p class="western" style="text-align: center;"><span style="font-size: small;"><strong>6000<span style="font-family: 宋体,SimSun;">字缩写笔记</span></strong></span></p>
<p class="western"><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">PERT</span><span style="font-family: 宋体,SimSun; font-size: small;">图与关键路径</span></p>
<p class="western"><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">、后续子集算法：找</span><span style="font-size: small;">0/1</span><span style="font-family: 宋体,SimSun; font-size: small;">串最右边的</span><span style="font-size: small;">0</span><span style="font-family: 宋体,SimSun; font-size: small;">，如果有，把它置为</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">，后面的都置为</span><span style="font-size: small;">0</span><span style="font-family: 宋体,SimSun; font-size: small;">，否则算法终止。</span></p>
<p class="western"><span style="font-size: small;">3</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Augusta Ada Byron 1815-1852</span></p>
<p class="western"><span style="font-size: small;">4</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">union intersection disjoint difference complement</span></p>
<p class="western"><span style="font-size: small;">5</span><span style="font-family: 宋体,SimSun; font-size: small;">、集合</span><span style="font-size: small;">S</span><span style="font-family: 宋体,SimSun; font-size: small;">上的关系</span><span style="font-size: small;">R</span><span style="font-family: 宋体,SimSun; font-size: small;">可以具备下列特殊性质中的任何一个：</span></p>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">）如果对于</span><span style="font-size: small;">S</span><span style="font-family: 宋体,SimSun; font-size: small;">中的任意元素</span><span style="font-size: small;">x</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">x R x</span><span style="font-family: 宋体,SimSun; font-size: small;">为真，则称</span><span style="font-size: small;">R</span><span style="font-family: 宋体,SimSun; font-size: small;">是自反的（</span><span style="font-size: small;">reflexive</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">）如果只要</span><span style="font-size: small;">x R y</span><span style="font-family: 宋体,SimSun; font-size: small;">为真，</span><span style="font-size: small;">y R x</span><span style="font-family: 宋体,SimSun; font-size: small;">就为真，则称</span><span style="font-size: small;">R</span><span style="font-family: 宋体,SimSun; font-size: small;">是对称的（</span><span style="font-size: small;">symmetric</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">3</span><span style="font-family: 宋体,SimSun; font-size: small;">）如果只要</span><span style="font-size: small;">x R y</span><span style="font-family: 宋体,SimSun; font-size: small;">和</span><span style="font-size: small;">y R z</span><span style="font-family: 宋体,SimSun; font-size: small;">都为真，</span><span style="font-size: small;">x R z</span><span style="font-family: 宋体,SimSun; font-size: small;">都为真，则称</span><span style="font-size: small;">R</span><span style="font-family: 宋体,SimSun; font-size: small;">是传递的（</span><span style="font-size: small;">transitive</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-size: small;">6</span><span style="font-family: 宋体,SimSun; font-size: small;">、自反、对称和传递的关系称为等价关系（</span><span style="font-size: small;">equivalence relation</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-size: small;">7</span><span style="font-family: 宋体,SimSun; font-size: small;">、如果</span><span style="font-size: small;">R</span><span style="font-family: 宋体,SimSun; font-size: small;">是</span><span style="font-size: small;">S</span><span style="font-family: 宋体,SimSun; font-size: small;">上的等价关系，</span><span style="font-size: small;">x∈S</span><span style="font-family: 宋体,SimSun; font-size: small;">，则</span><span style="font-size: small;">S</span><span style="font-family: 宋体,SimSun; font-size: small;">中与</span><span style="font-size: small;">x</span><span style="font-family: 宋体,SimSun; font-size: small;">相关联的元素的集合称为包含</span><span style="font-size: small;">x</span><span style="font-family: 宋体,SimSun; font-size: small;">的等价类（</span><span style="font-size: small;">equivalence class</span><span style="font-family: 宋体,SimSun; font-size: small;">），记为</span><span style="font-size: small;">[x]</span><span style="font-family: 宋体,SimSun; font-size: small;">，所以</span><span style="font-size: small;">[x] = {y∈S : y R x}</span></p>
<p class="western"><span style="font-size: small;">8</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">n = q m + r</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">q</span><span style="font-family: 宋体,SimSun; font-size: small;">为商（</span><span style="font-size: small;">quotient</span><span style="font-family: 宋体,SimSun; font-size: small;">），</span><span style="font-size: small;">r</span><span style="font-family: 宋体,SimSun; font-size: small;">为余数（</span><span style="font-size: small;">remainder</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-size: small;">9</span><span style="font-family: 宋体,SimSun; font-size: small;">、模</span><span style="font-size: small;">m</span><span style="font-family: 宋体,SimSun; font-size: small;">的同余关系 </span><span style="font-size: small;">congruence modulo m</span></p>
<p class="western"><span style="font-size: small;">10</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Z<sub>m</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">中：</span><span style="font-size: small;">[x] + [y] = [x + y]</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">[x] [y] = [x y]</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">[x]y = [xy]</span></p>
<p class="western"><span style="font-size: small;">11</span><span style="font-family: 宋体,SimSun; font-size: small;">、部分序，极大、极小元</span></p>
<p class="western"><span style="font-size: small;">12</span><span style="font-family: 宋体,SimSun; font-size: small;">、哈斯图（</span><span style="font-size: small;">Hasse Diagram</span><span style="font-family: 宋体,SimSun; font-size: small;">），由下而上观察，图中所有的线段都看作是指向上方的</span></p>
<p class="western"><span style="font-size: small;">13</span><span style="font-family: 宋体,SimSun; font-size: small;">、数学归纳法常用来验证算法</span></p>
<p class="western"><span style="font-size: small;">14</span><span style="font-family: 宋体,SimSun; font-size: small;">、循环不变式：</span><span style="font-size: small;">loop invariant</span></p>
<p class="western"><span style="font-size: small;">15</span><span style="font-family: 宋体,SimSun; font-size: small;">、《算术》（</span><span style="font-size: small;">Arithmetica</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-size: small;">16</span><span style="font-family: 宋体,SimSun; font-size: small;">、两图同构，对应顶的度数首先相等</span></p>
<p class="western"><span style="font-size: small;">17</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Leonhard Euler</span></p>
<p class="western"><span style="font-size: small;">18</span><span style="font-family: 宋体,SimSun; font-size: small;">、多重图</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">中，包含</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">中所有的边恰好一次，并且第一个顶点和最后一个顶点不相同的通路称为欧拉通路（</span><span style="font-size: small;">Euler path</span><span style="font-family: 宋体,SimSun; font-size: small;">），起点和终点相同的称为欧拉回路（</span><span style="font-size: small;">Euler circuit</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-size: small;">19</span><span style="font-family: 宋体,SimSun; font-size: small;">、求欧拉回路算法（</span><span style="font-size: small;">O(n<sup>2</sup>)</span><span style="font-family: 宋体,SimSun; font-size: small;">）：算法运行在各顶度数均为偶数的连通多重图</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">上</span></p>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">）令</span><span style="font-size: small;">E</span><span style="font-family: 宋体,SimSun; font-size: small;">是</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">的边集，选一个顶</span><span style="font-size: small;">U</span><span style="font-family: 宋体,SimSun; font-size: small;">，令通路</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">仅由</span><span style="font-size: small;">U</span><span style="font-family: 宋体,SimSun; font-size: small;">组成</span></p>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span><span style="font-size: small;">while E</span><span style="font-family: 宋体,SimSun; font-size: small;">非空（扩充通路）</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-family: 宋体,SimSun; font-size: small;">令</span><span style="font-size: small;">V</span><span style="font-family: 宋体,SimSun; font-size: small;">是</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">中的顶，它与</span><span style="font-size: small;">E</span><span style="font-family: 宋体,SimSun; font-size: small;">中某边关联，令通路</span><span style="font-size: small;">P</span><span style="font-family: 宋体,SimSun; font-size: small;">恰好包含</span><span style="font-size: small;">V</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-family: 宋体,SimSun; font-size: small;">令</span><span style="font-size: small;">W = V</span><span style="font-family: 宋体,SimSun; font-size: small;">（扩充</span><span style="font-size: small;">P</span><span style="font-family: 宋体,SimSun; font-size: small;">使它成为一条从</span><span style="font-size: small;">V</span><span style="font-family: 宋体,SimSun; font-size: small;">到</span><span style="font-size: small;">V</span><span style="font-family: 宋体,SimSun; font-size: small;">的通路）</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-size: small;"> while E</span><span style="font-family: 宋体,SimSun; font-size: small;">中有邻接</span><span style="font-size: small;">W</span><span style="font-family: 宋体,SimSun; font-size: small;">的边</span><span style="font-size: small;">e</span></p>
<p class="western" style="margin-left: 120px;"><span style="font-family: 宋体,SimSun; font-size: small;">从</span><span style="font-size: small;">E</span><span style="font-family: 宋体,SimSun; font-size: small;">中删去</span><span style="font-size: small;">e</span><span style="font-family: 宋体,SimSun; font-size: small;">，用邻接</span><span style="font-size: small;">e</span><span style="font-family: 宋体,SimSun; font-size: small;">的另一顶替换</span><span style="font-size: small;">W</span></p>
<p class="western" style="margin-left: 120px;"><span style="font-family: 宋体,SimSun; font-size: small;">将边</span><span style="font-size: small;">e</span><span style="font-family: 宋体,SimSun; font-size: small;">和顶</span><span style="font-size: small;">W</span><span style="font-family: 宋体,SimSun; font-size: small;">添加到通路</span><span style="font-size: small;">P</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-size: small;"> endwhile</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-family: 宋体,SimSun; font-size: small;">扩充</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">：用通路</span><span style="font-size: small;">P</span><span style="font-family: 宋体,SimSun; font-size: small;">替换</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">中出现的任意的某一个</span><span style="font-size: small;">V</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-size: small;">endwhile</span></p>
<p class="western" style="margin-left: 80px;">
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">3</span><span style="font-family: 宋体,SimSun; font-size: small;">）通路</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">是一条欧拉回路</span></p>
<p class="western"><span style="font-size: small;">20</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Hamilton path</span><span style="font-family: 宋体,SimSun; font-size: small;">是包含每个顶仅一次的通路，</span><span style="font-size: small;">Hamilton cycle</span><span style="font-family: 宋体,SimSun; font-size: small;">是包含每个顶仅一次的回路</span></p>
<p class="western"><span style="font-size: small;">21</span><span style="font-family: 宋体,SimSun; font-size: small;">、定理（</span><span style="font-size: small;">Ore</span><span style="font-family: 宋体,SimSun; font-size: small;">性质）：</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">n&gt;2</span><span style="font-family: 宋体,SimSun; font-size: small;">）阶图</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">若对任意不相邻顶</span><span style="font-size: small;">U</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">V</span><span style="font-family: 宋体,SimSun; font-size: small;">有</span><span style="font-size: small;">deg(U) + deg(V) ≥ n</span><span style="font-family: 宋体,SimSun; font-size: small;">则</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">有</span><span style="font-size: small;">H-</span><span style="font-family: 宋体,SimSun; font-size: small;">回路</span></p>
<p class="western"><span style="font-size: small;">22</span><span style="font-family: 宋体,SimSun; font-size: small;">、格雷码（</span><span style="font-size: small;">Gray code</span><span style="font-family: 宋体,SimSun; font-size: small;">）应用：确定圆盘旋转的位置（减少错误）</span></p>
<p class="western"><span style="font-size: small;">23</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">BFS</span><span style="font-family: 宋体,SimSun; font-size: small;">算法至多是</span><span style="font-size: small;">n<sup>2</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">阶的</span></p>
<p class="western"><span style="font-size: small;">24</span><span style="font-family: 宋体,SimSun; font-size: small;">、定理（通路的数目）：图</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">各顶标为</span><span style="font-size: small;">V<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">V<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">V<sub>n</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，邻接矩阵为</span><span style="font-size: small;">A</span><span style="font-family: 宋体,SimSun; font-size: small;">，从</span><span style="font-size: small;">V<sub>i</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">到</span><span style="font-size: small;">V<sub>j</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">的长度为</span><span style="font-size: small;">m</span><span style="font-family: 宋体,SimSun; font-size: small;">的通路的数目是</span><span style="font-size: small;">A<sup>m</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">的</span><span style="font-size: small;">(i, j)</span><span style="font-family: 宋体,SimSun; font-size: small;">元素</span></p>
<p class="western"><span style="font-size: small;">25</span><span style="font-family: 宋体,SimSun; font-size: small;">、定理</span><span style="font-size: small;">24</span><span style="font-family: 宋体,SimSun; font-size: small;">易用数学归纳法证明</span></p>
<p class="western"><span style="font-size: small;">26</span><span style="font-family: 宋体,SimSun; font-size: small;">、着色一个图（</span><span style="font-size: small;">color a graph</span><span style="font-family: 宋体,SimSun; font-size: small;">）是指给每个顶点指定一种颜色，使得相邻的顶点有不同的颜色</span></p>
<p class="western"><span style="font-size: small;">27</span><span style="font-family: 宋体,SimSun; font-size: small;">、当可用</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">种颜色，但不能用更少的颜色给一个图着色时，称该图具有色数（</span><span style="font-size: small;">chromatic number</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span><span style="font-size: small;">n</span></p>
<p class="western"><span style="font-size: small;">28</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">K<sub>n</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">的色数是</span><span style="font-size: small;">n</span></p>
<p class="western"><span style="font-size: small;">29</span><span style="font-family: 宋体,SimSun; font-size: small;">、定理（下界）：图</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">可用两种颜色着色当且仅当</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">不包含长度为奇数的回路</span></p>
<p class="western"><span style="font-size: small;">30</span><span style="font-family: 宋体,SimSun; font-size: small;">、定理（上界）：图</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">的色数不会超过</span><span style="font-size: small;">G</span><span style="font-family: 宋体,SimSun; font-size: small;">中顶点的最大度数加</span><span style="font-size: small;">1</span></p>
<p class="western"><span style="font-size: small;">31</span><span style="font-family: 宋体,SimSun; font-size: small;">、【练习】证明：“色数是</span><span style="font-size: small;">3”</span><span style="font-family: 宋体,SimSun; font-size: small;">是图的同构不变量</span></p>
<p class="western"><span style="font-size: small;">32</span><span style="font-family: 宋体,SimSun; font-size: small;">、每条</span><span style="font-size: small;">U-V</span><span style="font-family: 宋体,SimSun; font-size: small;">有向通路都包含一条</span><span style="font-size: small;">U-V</span><span style="font-family: 宋体,SimSun; font-size: small;">简单有向通路</span></p>
<p class="western"><span style="font-size: small;">33</span><span style="font-family: 宋体,SimSun; font-size: small;">、有向欧拉回路的应用（无线电通信中的旋转磁鼓的位置）：序列</span><span style="font-size: small;">01110100</span></p>
<p class="western"><span style="font-size: small;">34</span><span style="font-family: 宋体,SimSun; font-size: small;">、有向</span><span style="font-size: small;">H-</span><span style="font-family: 宋体,SimSun; font-size: small;">回路（通路）与循环体育比赛</span></p>
<p class="western"><span style="font-size: small;">35</span><span style="font-family: 宋体,SimSun; font-size: small;">、竞赛有向图（</span><span style="font-size: small;">tournament directed graph</span><span style="font-family: 宋体,SimSun; font-size: small;">）；采用完全图</span><span style="font-size: small;">K<sub>n</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">并给每边一个方向</span></p>
<p class="western"><span style="font-size: small;">36</span><span style="font-family: 宋体,SimSun; font-size: small;">、寻找一个所有队的排名与为竞赛图寻找一条有向</span><span style="font-size: small;">H-</span><span style="font-family: 宋体,SimSun; font-size: small;">通路是等同的</span></p>
<p class="western"><span style="font-size: small;">37</span><span style="font-family: 宋体,SimSun; font-size: small;">、欧拉公式（</span><span style="font-size: small;">1752</span><span style="font-family: 宋体,SimSun; font-size: small;">）：</span><span style="font-size: small;">f – e + v = 2</span></p>
<p class="western"><span style="font-size: small;">38</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">1847</span><span style="font-family: 宋体,SimSun; font-size: small;">年，</span><span style="font-size: small;">Gustav Kirchhoff</span><span style="font-family: 宋体,SimSun; font-size: small;">在他的关于电网的工作中首次用到树。后来，</span><span style="font-size: small;">Arthur Cayley</span><span style="font-family: 宋体,SimSun; font-size: small;">在化学研究中使用了树</span></p>
<p class="western"><span style="font-size: small;">39</span><span style="font-family: 宋体,SimSun; font-size: small;">、设</span><span style="font-size: small;">U</span><span style="font-family: 宋体,SimSun; font-size: small;">和</span><span style="font-size: small;">V</span><span style="font-family: 宋体,SimSun; font-size: small;">是树中的顶点，那么从</span><span style="font-size: small;">U</span><span style="font-family: 宋体,SimSun; font-size: small;">到</span><span style="font-size: small;">V</span><span style="font-family: 宋体,SimSun; font-size: small;">恰好有一条简单通路</span></p>
<p class="western"><span style="font-size: small;">40</span><span style="font-family: 宋体,SimSun; font-size: small;">、在一棵顶点数超过一的树</span><span style="font-size: small;">T</span><span style="font-family: 宋体,SimSun; font-size: small;">中，至少有两个度为</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">的顶点</span></p>
<p class="western"><span style="font-size: small;">41</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Prufer</span><span style="font-family: 宋体,SimSun; font-size: small;">算法：</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">本算法为一棵具有</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">个有标记的顶点的树构造一个数的序列</span><span style="font-size: small;">a<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">a<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">a<sub>n-2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，其中</span><span style="font-size: small;">n≥3</span><span style="font-family: 宋体,SimSun; font-size: small;">，且顶点上的标记分别为</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">n</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">步骤</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">（初始化）</span></p>
<ol style="margin-left: 40px;">
<li>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">令</span><span style="font-size: small;">T</span><span style="font-family: 宋体,SimSun; font-size: small;">是给定的树</span></p>
</li>
<li>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">令</span><span style="font-size: small;">k = k + 1</span></p>
</li>
</ol>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">步骤</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">（选择</span><span style="font-size: small;">a<sub>k</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-size: small;"> while T</span><span style="font-family: 宋体,SimSun; font-size: small;">的顶点多于两个</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-family: 宋体,SimSun; font-size: small;">步骤</span><span style="font-size: small;">2.1</span><span style="font-family: 宋体,SimSun; font-size: small;">（寻找一个度为</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">的顶点）</span></p>
<p class="western" style="margin-left: 120px;"><span style="font-family: 宋体,SimSun; font-size: small;">从</span><span style="font-size: small;">T</span><span style="font-family: 宋体,SimSun; font-size: small;">中找出顶点</span><span style="font-size: small;">X</span><span style="font-family: 宋体,SimSun; font-size: small;">，其度为</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">且具有最小的标记</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-family: 宋体,SimSun; font-size: small;">步骤</span><span style="font-size: small;">2.2</span><span style="font-family: 宋体,SimSun; font-size: small;">（构造一棵新的树）</span></p>
<ol style="margin-left: 80px;">
<li>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">找出</span><span style="font-size: small;">X</span><span style="font-family: 宋体,SimSun; font-size: small;">上的边</span><span style="font-size: small;">e</span><span style="font-family: 宋体,SimSun; font-size: small;">，令</span><span style="font-size: small;">W</span><span style="font-family: 宋体,SimSun; font-size: small;">表示</span><span style="font-size: small;">e</span><span style="font-family: 宋体,SimSun; font-size: small;">的另一个顶点</span></p>
</li>
<li>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">置</span><span style="font-size: small;">a<sub>k</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">为</span><span style="font-size: small;">W</span><span style="font-family: 宋体,SimSun; font-size: small;">上的标记</span></p>
</li>
<li>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">从</span><span style="font-size: small;">T</span><span style="font-family: 宋体,SimSun; font-size: small;">中删去边</span><span style="font-size: small;">e</span><span style="font-family: 宋体,SimSun; font-size: small;">和顶点</span><span style="font-size: small;">X</span><span style="font-family: 宋体,SimSun; font-size: small;">，形成一棵新的树</span><span style="font-size: small;">Tʹ</span></p>
</li>
</ol>
<p class="western" style="margin-left: 80px;"><span style="font-family: 宋体,SimSun; font-size: small;">步骤</span><span style="font-size: small;">2.3</span><span style="font-family: 宋体,SimSun; font-size: small;">（改变</span><span style="font-size: small;">T</span><span style="font-family: 宋体,SimSun; font-size: small;">和</span><span style="font-size: small;">k</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<ol style="margin-left: 80px;">
<li>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">令</span><span style="font-size: small;">T = Tʹ</span></p>
</li>
<li>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">令</span><span style="font-size: small;">k = k + 1</span></p>
</li>
</ol>
<p class="western" style="margin-left: 40px;"><span style="font-size: small;"> endwhile</span></p>
<p class="western"><span style="font-size: small;">42</span><span style="font-family: 宋体,SimSun; font-size: small;">、可以如下从</span><span style="font-size: small;">n-2</span><span style="font-family: 宋体,SimSun; font-size: small;">个数的序列</span><span style="font-size: small;">L</span><span style="font-family: 宋体,SimSun; font-size: small;">构造出一棵树，序列</span><span style="font-size: small;">L</span><span style="font-family: 宋体,SimSun; font-size: small;">中的数来自</span><span style="font-size: small;">N = {1, 2, …, n}</span><span style="font-family: 宋体,SimSun; font-size: small;">（假定树中顶点标记为</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">）。</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">从</span><span style="font-size: small;">N</span><span style="font-family: 宋体,SimSun; font-size: small;">中选出不在</span><span style="font-size: small;">L</span><span style="font-family: 宋体,SimSun; font-size: small;">中的最小的数</span><span style="font-size: small;">k</span><span style="font-family: 宋体,SimSun; font-size: small;">，在这个数和序列</span><span style="font-size: small;">L</span><span style="font-family: 宋体,SimSun; font-size: small;">中的第一个数之间构造一条边。</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">然后从</span><span style="font-size: small;">L</span><span style="font-family: 宋体,SimSun; font-size: small;">中删去第一个数，从</span><span style="font-size: small;">N</span><span style="font-family: 宋体,SimSun; font-size: small;">中山区</span><span style="font-size: small;">k</span><span style="font-family: 宋体,SimSun; font-size: small;">，并重复这个过程。</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">当</span><span style="font-size: small;">L</span><span style="font-family: 宋体,SimSun; font-size: small;">中的数被用完时，构造一条边连接</span><span style="font-size: small;">N</span><span style="font-family: 宋体,SimSun; font-size: small;">中剩下的两个数。</span></p>
<p class="western"><span style="font-size: small;">43</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Prufer</span><span style="font-family: 宋体,SimSun; font-size: small;">算法在有</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">个标记为</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">的顶点的树和产生的序列之间建立了一个一一对应。</span></p>
<p class="western"><span style="font-size: small;">44</span><span style="font-family: 宋体,SimSun; font-size: small;">、（续</span><span style="font-size: small;">43</span><span style="font-family: 宋体,SimSun; font-size: small;">）具有顶点</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">n&gt;1</span><span style="font-family: 宋体,SimSun; font-size: small;">）的不同的树有</span><span style="font-size: small;">n<sup>n-2</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">棵</span></p>
<p class="western"><span style="font-size: small;">45</span><span style="font-family: 宋体,SimSun; font-size: small;">、一个图可能会有多棵生成树</span></p>
<p class="western"><span style="font-size: small;">46</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">BFS</span><span style="font-family: 宋体,SimSun; font-size: small;">构造出的生成树称为最短通路树（</span><span style="font-size: small;">shortest path tree</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-size: small;">47</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Prim</span><span style="font-family: 宋体,SimSun; font-size: small;">算法用来构造一棵最小生成树（</span><span style="font-size: small;">minimum spanning tree</span><span style="font-family: 宋体,SimSun; font-size: small;">）：每次选择离已得到的树最近的顶点加入树中并相应地连一条边</span></p>
<p class="western"><span style="font-size: small;">48</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Kruskal</span><span style="font-family: 宋体,SimSun; font-size: small;">算法每次选择一条权最小的边，如果不构成回路则加入树中，最终也得到一棵最小生成树</span></p>
<p class="western"><span style="font-size: small;">49</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Prim</span><span style="font-family: 宋体,SimSun; font-size: small;">与</span><span style="font-size: small;">Kruskal</span><span style="font-family: 宋体,SimSun; font-size: small;">同样都可以求解最大生成树（</span><span style="font-size: small;">maximum spanning tree</span><span style="font-family: 宋体,SimSun; font-size: small;">），只需把“最小”改为“最大”即可</span></p>
<p class="western"><span style="font-size: small;">50</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">DFS</span><span style="font-family: 宋体,SimSun; font-size: small;">构造出的树</span><span style="font-size: small;">T</span><span style="font-family: 宋体,SimSun; font-size: small;">称为深度优先搜索树（</span><span style="font-size: small;">depth-first search tree</span><span style="font-family: 宋体,SimSun; font-size: small;">）。</span><span style="font-size: small;">DFS</span><span style="font-family: 宋体,SimSun; font-size: small;">的阶至多是</span><span style="font-size: small;">n<sup>2</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">的。</span></p>
<p class="western"><span style="font-size: small;">51</span><span style="font-family: 宋体,SimSun; font-size: small;">、（续</span><span style="font-size: small;">50</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span><span style="font-size: small;">T</span><span style="font-family: 宋体,SimSun; font-size: small;">中的边称为树边（</span><span style="font-size: small;">tree edge</span><span style="font-family: 宋体,SimSun; font-size: small;">），其他边称为后向边（</span><span style="font-size: small;">back edge</span><span style="font-family: 宋体,SimSun; font-size: small;">）。对顶点所作的标记称为深度优先搜索编码。</span></p>
<p class="western"><span style="font-size: small;">52</span><span style="font-family: 宋体,SimSun; font-size: small;">、根树（</span><span style="font-size: small;">rooted tree</span><span style="font-family: 宋体,SimSun; font-size: small;">）是一个有向图</span><span style="font-size: small;">T</span><span style="font-family: 宋体,SimSun; font-size: small;">，它满足两个条件：</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">一是当忽略</span><span style="font-size: small;">T</span><span style="font-family: 宋体,SimSun; font-size: small;">中的边的方向时，所得到的无向图是一棵树；</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">二是存在一个惟一的顶点</span><span style="font-size: small;">R</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">R</span><span style="font-family: 宋体,SimSun; font-size: small;">的入度为零，其他任何顶点的入度都为一。顶点</span><span style="font-size: small;">R</span><span style="font-family: 宋体,SimSun; font-size: small;">称为根树的根（</span><span style="font-size: small;">root</span><span style="font-family: 宋体,SimSun; font-size: small;">）。</span></p>
<p class="western"><span style="font-size: small;">53</span><span style="font-family: 宋体,SimSun; font-size: small;">、画根树时将遵循如下惯例：根画在顶端，并省略有向边上的箭头，把边的方向理解为都是向下的。</span></p>
<p class="western"><span style="font-size: small;">54</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Catalan</span><span style="font-family: 宋体,SimSun; font-size: small;">数：有</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">个顶点的二叉树的数目是</span><span style="font-size: small;">(2n)! / [n! (n+1)!]</span></p>
<p class="western"><span style="font-size: small;">55</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Fibonacci Tree</span><span style="font-family: 宋体,SimSun; font-size: small;">：</span><span style="font-size: small;">T<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">T<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">都只有一个顶点；对于</span><span style="font-size: small;">n≥3</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">T<sub>n</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">是一棵树，其根的左子树是</span><span style="font-size: small;">T<sub>n-1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，右子树是</span><span style="font-size: small;">T<sub>n-2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">。</span></p>
<p class="western"><span style="font-size: small;">56</span><span style="font-family: 宋体,SimSun; font-size: small;">、【练习】（续</span><span style="font-size: small;">55</span><span style="font-family: 宋体,SimSun; font-size: small;">）给出</span><span style="font-size: small;">T<sub>n</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">的顶点数的公式并证明</span></p>
<p class="western"><span style="font-size: small;">57</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">David A. Huffman</span><span style="font-family: 宋体,SimSun; font-size: small;">最优二叉树（</span><span style="font-size: small;">optimal binary tree</span><span style="font-family: 宋体,SimSun; font-size: small;">）算法：每次选标记最小的两个根合并成一棵新的树，新树根的标记为这两个根标记之和</span></p>
<p class="western"><span style="font-size: small;">58</span><span style="font-family: 宋体,SimSun; font-size: small;">、（续</span><span style="font-size: small;">57</span><span style="font-family: 宋体,SimSun; font-size: small;">）可利用此算法找到合并多个有序列表的最优模式，顶点的权是对应的列表的项数</span></p>
<p class="western"><span style="font-size: small;">59</span><span style="font-family: 宋体,SimSun; font-size: small;">、一个列表的二叉搜索树是一棵这样的二叉树：二叉树的每个顶点都被列表的一个元素标记，使得：</span></p>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">）没有两个顶点有相同的标记</span></p>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">）如果顶点</span><span style="font-size: small;">U</span><span style="font-family: 宋体,SimSun; font-size: small;">属于顶点</span><span style="font-size: small;">V</span><span style="font-family: 宋体,SimSun; font-size: small;">的左子树，那么</span><span style="font-size: small;">U≤V</span></p>
<p class="western"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">3</span><span style="font-family: 宋体,SimSun; font-size: small;">）如果顶点</span><span style="font-size: small;">W</span><span style="font-family: 宋体,SimSun; font-size: small;">属于顶点</span><span style="font-size: small;">V</span><span style="font-family: 宋体,SimSun; font-size: small;">的右子树，那么</span><span style="font-size: small;">V≥W</span></p>
<p class="western"><span style="font-size: small;">60</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">S<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">S<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">S<sub>n</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">的一个相异代表系（</span><span style="font-size: small;">system of distinct representatives</span><span style="font-family: 宋体,SimSun; font-size: small;">）是指这样的一个序列：</span><span style="font-size: small;">x<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">x<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">x<sub>n</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，其中，</span><span style="font-size: small;">x<sub>i</sub>∈S<sub>i</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">i = 1, 2, …, n</span><span style="font-family: 宋体,SimSun; font-size: small;">），并且各个元素</span><span style="font-size: small;">x<sub>i</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">都互不相同</span></p>
<p class="western"><span style="font-size: small;">61</span><span style="font-family: 宋体,SimSun; font-size: small;">、霍尔定理（</span><span style="font-size: small;">Phillip Hall</span><span style="font-family: 宋体,SimSun; font-size: small;">）：有限集合序列</span><span style="font-size: small;">S<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">S<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">S<sub>n</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">有相异代表系当且仅当对</span><span style="font-size: small;">{1, 2, …, n}</span><span style="font-family: 宋体,SimSun; font-size: small;">的任意子集</span><span style="font-size: small;">I</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">S<sub>i</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">i∈I</span><span style="font-family: 宋体,SimSun; font-size: small;">）的并集所包含的元素至少与集合</span><span style="font-size: small;">I</span><span style="font-family: 宋体,SimSun; font-size: small;">所包含的元素个数相同</span></p>
<p class="western"><span style="font-size: small;">62</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">61</span><span style="font-family: 宋体,SimSun; font-size: small;">中所述条件称为霍尔条件（</span><span style="font-size: small;">Hall’s condition</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-size: small;">63</span><span style="font-family: 宋体,SimSun; font-size: small;">、【练习】对于</span><span style="font-size: small;">r≤n</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">r×n</span><span style="font-family: 宋体,SimSun; font-size: small;">的拉丁矩形（</span><span style="font-size: small;">Latin rectangle</span><span style="font-family: 宋体,SimSun; font-size: small;">）是这样的</span><span style="font-size: small;">r×n</span><span style="font-family: 宋体,SimSun; font-size: small;">的矩阵：这个矩阵的元素是数</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">中的数，而且任何一行或一列中都不会有一个数出现多次。</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">一个</span><span style="font-size: small;">n×n</span><span style="font-family: 宋体,SimSun; font-size: small;">的拉丁矩形称为一个拉丁方（</span><span style="font-size: small;">Latin square</span><span style="font-family: 宋体,SimSun; font-size: small;">）。证明：如果</span><span style="font-size: small;">r&lt;n</span><span style="font-family: 宋体,SimSun; font-size: small;">，那么一定可以附加</span><span style="font-size: small;">n-r</span><span style="font-family: 宋体,SimSun; font-size: small;">行到一个</span><span style="font-size: small;">r×n</span><span style="font-family: 宋体,SimSun; font-size: small;">的拉丁矩形，以形成一个拉丁方。（提示：应用霍尔定理）</span></p>
<p class="western"><span style="font-size: small;">64</span><span style="font-family: 宋体,SimSun; font-size: small;">、偶图（二分图）：</span><span style="font-size: small;">bipartite</span></p>
<p class="western"><span style="font-size: small;">65</span><span style="font-family: 宋体,SimSun; font-size: small;">、图的一个匹配（</span><span style="font-size: small;">matching</span><span style="font-family: 宋体,SimSun; font-size: small;">）是这样的一个边的集合</span><span style="font-size: small;">M</span><span style="font-family: 宋体,SimSun; font-size: small;">，图中没有一个顶点与</span><span style="font-size: small;">M</span><span style="font-family: 宋体,SimSun; font-size: small;">中的多条边关联。</span></p>
<p class="western"><span style="font-size: small;">66</span><span style="font-family: 宋体,SimSun; font-size: small;">、偶图的</span><span style="font-size: small;">0-1</span><span style="font-family: 宋体,SimSun; font-size: small;">矩阵；矩阵的一排（</span><span style="font-size: small;">line</span><span style="font-family: 宋体,SimSun; font-size: small;">）是指矩阵的一行或一列。</span></p>
<p class="western"><span style="font-size: small;">67</span><span style="font-family: 宋体,SimSun; font-size: small;">、设</span><span style="font-size: small;">A</span><span style="font-family: 宋体,SimSun; font-size: small;">是一个矩阵，如果其中没有两个元素在同一排上，则称</span><span style="font-size: small;">A</span><span style="font-family: 宋体,SimSun; font-size: small;">的元素的集合是独立的（</span><span style="font-size: small;">independent</span><span style="font-family: 宋体,SimSun; font-size: small;">）。</span></p>
<p class="western"><span style="font-size: small;">68</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">A</span><span style="font-family: 宋体,SimSun; font-size: small;">中</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">的独立集是</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">的最大独立集（</span><span style="font-size: small;">maximum independent set</span><span style="font-family: 宋体,SimSun; font-size: small;">），如果</span><span style="font-size: small;">A</span><span style="font-family: 宋体,SimSun; font-size: small;">中没有包含更多</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">的</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">的独立集。</span></p>
<p class="western"><span style="font-size: small;">69</span><span style="font-family: 宋体,SimSun; font-size: small;">、在偶图中寻找一个最大匹配与在一个</span><span style="font-size: small;">0-1</span><span style="font-family: 宋体,SimSun; font-size: small;">矩阵中寻找一个</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">的最大独立集是等价的。</span></p>
<p class="western"><span style="font-size: small;">70</span><span style="font-family: 宋体,SimSun; font-size: small;">、图的一个覆盖（</span><span style="font-size: small;">covering</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">是指一个顶点的集合，它使每条边至少与</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">中的一个顶点关联。</span></p>
<p class="western"><span style="font-size: small;">71</span><span style="font-family: 宋体,SimSun; font-size: small;">、称</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">是一个最小覆盖（</span><span style="font-size: small;">minimum covering</span><span style="font-family: 宋体,SimSun; font-size: small;">），如果没有包含顶点更少的该图的覆盖。</span></p>
<p class="western"><span style="font-size: small;">72</span><span style="font-family: 宋体,SimSun; font-size: small;">、定理：设一个图有一个匹配</span><span style="font-size: small;">M</span><span style="font-family: 宋体,SimSun; font-size: small;">和一个覆盖</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">，那么</span><span style="font-size: small;">|M|≤|C|</span><span style="font-family: 宋体,SimSun; font-size: small;">。此外，如果</span><span style="font-size: small;">|M|=|C|</span><span style="font-family: 宋体,SimSun; font-size: small;">，那么</span><span style="font-size: small;">M</span><span style="font-family: 宋体,SimSun; font-size: small;">是一个最大匹配，</span><span style="font-size: small;">C</span><span style="font-family: 宋体,SimSun; font-size: small;">是一个最小覆盖。</span></p>
<p class="western"><span style="font-size: small;">73</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Dénes König</span><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">1931</span><span style="font-family: 宋体,SimSun; font-size: small;">）：在</span><span style="font-size: small;">0-1</span><span style="font-family: 宋体,SimSun; font-size: small;">矩阵中，</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">的最大独立集和最小覆盖包含相同个数的元素。等价地，在偶图中，最大匹配和最小覆盖包含相同个数的元素。</span></p>
<p class="western"><span style="font-size: small;">74</span><span style="font-family: 宋体,SimSun; font-size: small;">、（书中关于匹配算法和网络流的内容讲述不清错误连篇所以没有作笔记，以后会单独写相关内容，敬请关注）</span></p>
<p class="western"><span style="font-size: small;">75</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Pascal’s triangle</span><span style="font-family: 宋体,SimSun; font-size: small;">；西方称为帕斯卡三角形，国内原称杨辉三角形，现多称为贾宪三角形。</span></p>
<p class="western"><span style="font-size: small;">76</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">C(n, r) = C(n-1, r-1) + C(n-1, r)</span></p>
<p class="western"><span style="font-size: small;">77</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">r C(n, r) = n C(n-1, r-1)</span></p>
<p class="western"><span style="font-size: small;">78</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">C(k, 0) + C(k+1, 1) + … + C(k+r, r) = C(k+r+1, r)</span></p>
<p class="western"><span style="font-size: small;">79</span><span style="font-family: 宋体,SimSun; font-size: small;">、曲棍球棒公式：</span><span style="font-size: small;">C(r, r) + C(r+1, r) + … + C(n, r) = C(n+1, r+1)</span></p>
<p class="western"><span style="font-size: small;">80</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">p</span><span style="font-family: 宋体,SimSun; font-size: small;">为素数，</span><span style="font-size: small;">r</span><span style="font-family: 宋体,SimSun; font-size: small;">为整数，</span><span style="font-size: small;">1≤r≤p-1</span><span style="font-family: 宋体,SimSun; font-size: small;">，则</span><span style="font-size: small;">C(p, r)</span><span style="font-family: 宋体,SimSun; font-size: small;">可以被</span><span style="font-size: small;">p</span><span style="font-family: 宋体,SimSun; font-size: small;">整除</span></p>
<p class="western"><span style="font-size: small;">81</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">C(n, m)×C(m, k) = C(n, k)×C(n-k, m-k) (k≤m≤n)</span></p>
<p class="western"><span style="font-size: small;">82</span><span style="font-family: 宋体,SimSun; font-size: small;">、有</span><span style="font-size: small;">r</span><span style="font-family: 宋体,SimSun; font-size: small;">个对象要选择，每个对象有</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">种选择方式：</span></p>
<table style="height: 88px;" border="1" cellspacing="0" cellpadding="8" width="528" bordercolor="#000000">
<tbody>
<tr valign="top">
<td width="71">
<p class="western" align="center"><span style="font-family: 宋体,SimSun; font-size: small;"><strong>条件</strong></span></p>
</td>
<td width="131">
<p class="western" align="center"><span style="font-family: 宋体,SimSun; font-size: small;"><strong>排列（有序列表）数</strong></span></p>
</td>
<td width="131">
<p class="western" align="center"><span style="font-family: 宋体,SimSun; font-size: small;"><strong>组合（无序列表）数</strong></span></p>
</td>
</tr>
<tr valign="top">
<td width="71">
<p class="western" align="center"><span style="font-family: 宋体,SimSun; font-size: small;">不允许重复</span></p>
</td>
<td width="131">
<p class="western" align="center"><span style="font-size: small;">P(n, r)</span></p>
</td>
<td width="131">
<p class="western" align="center"><span style="font-size: small;">C(n, r)</span></p>
</td>
</tr>
<tr valign="top">
<td width="71">
<p class="western" align="center"><span style="font-family: 宋体,SimSun; font-size: small;">允许重复</span></p>
</td>
<td width="131">
<p class="western" align="center"><span style="font-size: small;">n<sup>r</sup></span></p>
</td>
<td width="131">
<p class="western" align="center"><span style="font-size: small;">C(n+r-1, r)</span></p>
</td>
</tr>
</tbody>
</table>
<p class="western"><span style="font-size: small;">83</span><span style="font-family: 宋体,SimSun; font-size: small;">、容斥原理：对任意有限集合</span><span style="font-size: small;">A<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">A<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">A<sub>r</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，对</span><span style="font-size: small;">1sr</span><span style="font-family: 宋体,SimSun; font-size: small;">，定义</span><span style="font-size: small;">n<sub>s</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">如下：</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">从</span><span style="font-size: small;">A<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">A<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，…，</span><span style="font-size: small;">A<sub>r</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">中不重复地选择</span><span style="font-size: small;">s</span><span style="font-family: 宋体,SimSun; font-size: small;">个集合并计算其交集的大小，对所有可能的选择，定义</span><span style="font-size: small;">n<sub>s</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">为这些值的和，那么</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-size: small;">|A<sub>1</sub>∪A<sub>2</sub>∪…∪A<sub>r</sub>| = n<sub>1</sub> – n<sub>2</sub> + n<sub>3</sub> – n<sub>4</sub> + … + (-1)<sup>r-1</sup> n<sub>r</sub></span></p>
<p class="western"><span style="font-size: small;">84</span><span style="font-family: 宋体,SimSun; font-size: small;">、第二类</span><span style="font-size: small;">Stirling</span><span style="font-family: 宋体,SimSun; font-size: small;">数：把</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">个不同的球放到</span><span style="font-size: small;">m</span><span style="font-family: 宋体,SimSun; font-size: small;">个相同的盒中，没有空盒的放法总数记为</span><span style="font-size: small;">S<sub>2</sub>(n, m)</span></p>
<p class="western"><span style="font-size: small;">85</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">S<sub>2</sub>(n+1, m) = S<sub>2</sub>(n, m-1) + m×S<sub>2</sub>(n, m)</span></p>
<p class="western"><span style="font-size: small;">86</span><span style="font-family: 宋体,SimSun; font-size: small;">、对于大正整数</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">有</span><span style="font-size: small;">Stirling</span><span style="font-family: 宋体,SimSun; font-size: small;">近似公式：</span><span style="font-size: small;">n!</span><span style="font-family: 宋体,SimSun; font-size: small;">～</span><span style="font-size: small;">(n/е)<sup>n</sup> (2πn)<sup>1/2</sup></span></p>
<p class="western"><span style="font-size: small;">87</span><span style="font-family: 宋体,SimSun; font-size: small;">、错排数递推式：</span><span style="font-size: small;">D<sub>n</sub> = (n-1) (D<sub>n-2</sub> + D<sub>n-1</sub>)</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">n≥3</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">D<sub>1</sub> = 0</span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">D<sub>2</sub> = 1</span></p>
<p class="western"><span style="font-size: small;">88</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Eugene Charles Catalan (1814 – 1894)</span></p>
<p class="western"><span style="font-size: small;">89</span><span style="font-family: 宋体,SimSun; font-size: small;">、在表达式</span><span style="font-size: small;">x<sub>1</sub>x<sub>2</sub>…x<sub>n+1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">中插入</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">对圆括号，以把各因子组合成</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">对数的乘积，插入这</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">对括号的方法数是</span><span style="font-size: small;">C<sub>n</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，称作</span><span style="font-size: small;">Catalan</span><span style="font-family: 宋体,SimSun; font-size: small;">数。</span></p>
<p class="western"><span style="font-size: small;">90</span><span style="font-family: 宋体,SimSun; font-size: small;">、（续</span><span style="font-size: small;">89</span><span style="font-family: 宋体,SimSun; font-size: small;">）另一种表述基于栈的排列生成。</span></p>
<p class="western"><span style="font-size: small;">91</span><span style="font-family: 宋体,SimSun; font-size: small;">、离散动态系统（</span><span style="font-size: small;">discrete dynamical systems</span><span style="font-family: 宋体,SimSun; font-size: small;">）是微分方程的离散替代物，微分方程用于研究连续时间框架下的变化。</span></p>
<p class="western"><span style="font-size: small;">92</span><span style="font-family: 宋体,SimSun; font-size: small;">、一阶常系数线性差分方程（</span><span style="font-size: small;">first-order linear difference equation with constant coefficients</span><span style="font-family: 宋体,SimSun; font-size: small;">）：</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">初始值为</span><span style="font-size: small;">S<sub>0</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">的一阶常系数线性差分方程</span><span style="font-size: small;">S<sub>n</sub> = a S<sub>n-1</sub> + b</span><span style="font-family: 宋体,SimSun; font-size: small;">的通项满足：</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-size: small;"> S<sub>n</sub> = a<sup>n</sup> (S<sub>0</sub> + c) – c </span><span style="font-family: 宋体,SimSun; font-size: small;">（当</span><span style="font-size: small;">a ≠ 1</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">或</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-size: small;"> S<sub>n</sub> = S<sub>0</sub> + n b </span><span style="font-family: 宋体,SimSun; font-size: small;">（当</span><span style="font-size: small;">a = 1</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">其中</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-size: small;"> c = b / (a – 1)</span></p>
<p class="western"><span style="font-size: small;">93</span><span style="font-family: 宋体,SimSun; font-size: small;">、考虑二阶常系数线性齐次差分方程（</span><span style="font-size: small;">second-order homogeneous linear difference equation with constant coefficients</span><span style="font-family: 宋体,SimSun; font-size: small;">）：</span></p>
<p class="western" style="margin-left: 80px;"><span style="font-size: small;">S<sub>n</sub> = a S<sub>n-1</sub> + b S<sub>n-2</sub> (n≥2)</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">初值为</span><span style="font-size: small;">S<sub>0</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">和</span><span style="font-size: small;">S<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">。设</span><span style="font-size: small;">r<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">和</span><span style="font-size: small;">r<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">表示方程</span><span style="font-size: small;">x<sup>2</sup> = a x + b</span><span style="font-family: 宋体,SimSun; font-size: small;">的根，那么，</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">）如果</span><span style="font-size: small;">r<sub>1</sub> ≠ r<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，则存在常数</span><span style="font-size: small;">c<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">和</span><span style="font-size: small;">c<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，使</span><span style="font-size: small;">S<sub>n</sub> = c<sub>1</sub> r<sub>1</sub><sup>n</sup> + c<sub>2</sub> r<sub>2</sub><sup>n</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">n = 0, 1, 2, …</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">2</span><span style="font-family: 宋体,SimSun; font-size: small;">）如果</span><span style="font-size: small;">r<sub>1</sub> = r<sub>2</sub> = r</span><span style="font-family: 宋体,SimSun; font-size: small;">，则存在常数</span><span style="font-size: small;">c<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">和</span><span style="font-size: small;">c<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，使</span><span style="font-size: small;">S<sub>n</sub> = (c<sub>1</sub> + n c<sub>2</sub>) r<sup>n</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">n = 0, 1, 2, …</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">方程</span><span style="font-size: small;">x<sup>2</sup> = a x + b</span><span style="font-family: 宋体,SimSun; font-size: small;">称为递推关系</span><span style="font-size: small;">S<sub>n</sub> = a S<sub>n-1</sub> + b S<sub>n-2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">的辅助方程（</span><span style="font-size: small;">auxiliary equation</span><span style="font-family: 宋体,SimSun; font-size: small;">）。</span></p>
<p class="western"><span style="font-size: small;">94</span><span style="font-family: 宋体,SimSun; font-size: small;">、从信息论的观点说明比较排序算法的效率（一个关于下界的说明）：</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">在任何比较排序算法中都要比较各对元素，有些比较不会提供新的信息（如已知</span><span style="font-size: small;">a<sub>1</sub>≤a<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">和</span><span style="font-size: small;">a<sub>2</sub>≤a<sub>3</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">那么比较</span><span style="font-size: small;">a<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">和</span><span style="font-size: small;">a<sub>3</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">是没有意义的）。</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">但不管怎样进行</span><span style="font-size: small;">k</span><span style="font-family: 宋体,SimSun; font-size: small;">次比较，可能得到的信息至多有</span><span style="font-size: small;">2<sup>k</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">种不同的模式。</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">结论是：通过</span><span style="font-size: small;">k</span><span style="font-family: 宋体,SimSun; font-size: small;">次比较，最多能区分</span><span style="font-size: small;">2<sup>k</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">种不同的顺序。</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">如果要对列表排序，就必须获得足够的信息，以从其元素</span><span style="font-size: small;">n!</span><span style="font-family: 宋体,SimSun; font-size: small;">种可能的不同排列序列中辨别出该列表来。</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">因此，要对该列表排序，至少要做</span><span style="font-size: small;">k</span><span style="font-family: 宋体,SimSun; font-size: small;">次比较，这里，</span><span style="font-size: small;">2<sup>k</sup>≥n!</span><span style="font-family: 宋体,SimSun; font-size: small;">。可以证明</span><span style="font-size: small;">n!≥n<sup>n/2</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">，于是，</span></p>
<p class="western" style="margin-left: 120px;"><span style="font-size: small;">2<sup>k</sup>≥n<sup>n/2</sup></span></p>
<p class="western" style="margin-left: 120px;"><span style="font-size: small;">log<sub>2</sub>(2<sup>k</sup>)≥log<sub>2</sub>(n<sup>n/2</sup>)</span></p>
<p class="western" style="margin-left: 120px;"><span style="font-size: small;">k≥(n/2) log<sub>2</sub>n</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">由此，任何比较排序算法的复杂性都至少是</span><span style="font-size: small;">c n log<sub>2</sub>n</span><span style="font-family: 宋体,SimSun; font-size: small;">，其中，</span><span style="font-size: small;">c</span><span style="font-family: 宋体,SimSun; font-size: small;">为常数。</span></p>
<p class="western"><span style="font-size: small;">95</span><span style="font-family: 宋体,SimSun; font-size: small;">、一般地考虑一个无限数列</span><span style="font-size: small;">a<sub>0</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">a<sub>1</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，</span><span style="font-size: small;">a<sub>2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">，…</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">其中，对某个整数</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">，有</span><span style="font-size: small;">a<sub>n+1</sub> = a<sub>n+2</sub> = … = 0</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">我们称多项式</span><span style="font-size: small;">a<sub>0</sub> + a<sub>1</sub> x + a<sub>2</sub> x<sup>2</sup> + a<sub>3</sub> x<sup>3</sup> + … + a<sub>n</sub> x<sup>n</sup></span><span style="font-family: 宋体,SimSun; font-size: small;">是该序列的生成函数（</span><span style="font-size: small;">generating function</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-size: small;">96</span><span style="font-family: 宋体,SimSun; font-size: small;">、形如</span><span style="font-size: small;">a<sub>0</sub> + a<sub>1</sub> x + a<sub>2</sub> x<sup>2</sup> + a<sub>3</sub> x<sup>3</sup> + …</span><span style="font-family: 宋体,SimSun; font-size: small;">的表达式称为形式幂级数（</span><span style="font-size: small;">formal power series</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">其中，允许无限多个系数</span><span style="font-size: small;">a<sub>r</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">不为零。</span></p>
<p class="western"><span style="font-size: small;">97</span><span style="font-family: 宋体,SimSun; font-size: small;">、假设</span><span style="font-size: small;">G = a<sub>0</sub> + a<sub>1</sub> x + a<sub>2</sub> x<sup>2</sup> + a<sub>3</sub> x<sup>3</sup> + …</span><span style="font-family: 宋体,SimSun; font-size: small;">，这里</span><span style="font-size: small;">a<sub>0</sub> ≠ 0</span><span style="font-family: 宋体,SimSun; font-size: small;">。则存在惟一的生成函数</span><span style="font-size: small;">H</span><span style="font-family: 宋体,SimSun; font-size: small;">，使得</span><span style="font-size: small;">G H = 1</span><span style="font-family: 宋体,SimSun; font-size: small;">。</span></p>
<p class="western"><span style="font-size: small;">98</span><span style="font-family: 宋体,SimSun; font-size: small;">、卢卡斯序列（</span><span style="font-size: small;">Lucas sequence</span><span style="font-family: 宋体,SimSun; font-size: small;">）：</span><span style="font-size: small;">L<sub>n</sub> = p</span><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">n = 1</span><span style="font-family: 宋体,SimSun; font-size: small;">）或</span><span style="font-size: small;">L<sub>n</sub> = q</span><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">n = 2</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span><span style="font-size: small;">L<sub>n</sub> = L<sub>n-1</sub> + L<sub>n-2</sub></span><span style="font-family: 宋体,SimSun; font-size: small;">（</span><span style="font-size: small;">n ≥ 3</span><span style="font-family: 宋体,SimSun; font-size: small;">）。</span></p>
<p class="western"><span style="font-size: small;">99</span><span style="font-family: 宋体,SimSun; font-size: small;">、（关于逻辑电路和状态机的内容讲得很烂所以略过，以后有机会给大家写一篇好的</span><span style="font-size: small;">~</span><span style="font-family: 宋体,SimSun; font-size: small;">）</span></p>
<p class="western"><span style="font-size: small;">100</span><span style="font-family: 宋体,SimSun; font-size: small;">、</span><span style="font-size: small;">Collatz</span><span style="font-family: 宋体,SimSun; font-size: small;">序列：根据正整数</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">是偶数还是奇数，分别用</span><span style="font-size: small;">n/2</span><span style="font-family: 宋体,SimSun; font-size: small;">或</span><span style="font-size: small;">3n+1</span><span style="font-family: 宋体,SimSun; font-size: small;">替换它，并重复这个过程。</span></p>
<p class="western" style="margin-left: 40px;"><span style="font-family: 宋体,SimSun; font-size: small;">人们猜测但尚未证明：无论从哪个整数</span><span style="font-size: small;">n</span><span style="font-family: 宋体,SimSun; font-size: small;">开始，最终都将到达</span><span style="font-size: small;">1</span><span style="font-family: 宋体,SimSun; font-size: small;">。</span></p>
<p class="western" style="text-align: left;"><span style="font-size: small;"><strong><span style="font-family: 宋体,SimSun;">（本文完；未经许可，不得转载）</span></strong></span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.doglog.net/2009/04/discrete-mathematics-in-6000-words/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
