<?xml version="1.0" encoding="utf-8"?><rss version="2.0">
<channel>
<title><![CDATA[编程驿站]]></title>
<link>http://blog.pfan.cn/lingdlz</link>
<description>编程爱好者博客</description>
<language>zh-cn</language>
			<item>
		<title><![CDATA[软件界的传奇—Anders&nbsp;Hejlsberg]]></title>
		<link>http://blog.pfan.cn/lingdlz/36606.html</link>
		<description><![CDATA[软件界的传奇—Anders Hejlsberg
&nbsp;





&nbsp;&nbsp;&nbsp;&nbsp; Anders虽然没有显赫的学历，无法获得Turning Awards。但Anders的实力和贡献绝不输于任何一位Turning Awards获得者。&nbsp;&nbsp;&nbsp; 对于成千上万的使用Borland Turbo Pascal和Delphi进行编程的软件开发者来说，Anders Hejlsberg，这位丹麦的软件大师让他
们肃然起敬，是他创制了上述两个备受欢迎的软件开发工具。&nbsp;&nbsp; 作为Turbo Pascal、VisualJ++、Delphi、C#的缔造者，.NET的领军人物，Borland的创始人之一，Microsoft的灵魂人物，Anders
在一定程度上影响着全球软件业的发展。英雄落难&nbsp;&nbsp;&nbsp; Anders首次跃上软件业界舞台是源于他在80年代早期为MS-DOS和CP/M写的一个Pascal编译器。不久一个叫做Borland的年轻公司雇
佣了他并且买下了他的编译器，从那以后这个编译器就作为Turbo Pascal在市场上推广。&nbsp;&nbsp;&nbsp; 在Borland，Anders继续开发Turbo Pacal并且在后来领导一个团队设计了Turbo Pascal的替代品、开发工具史上的奇迹:Delphi语
言。&nbsp;&nbsp;&nbsp; Philippe Kahn和Anders都为Borland做出了重大的贡献，同时两人之间还有着深厚的感情。在Borland工作时，对于Anders任何想
法和计划，Philippe Kahn都是不遗余力地支持。也正是这个重要的支持力量，才有随后极为成功的Borland Pascal以及Delphi的问
世。&nbsp;&nbsp;&nbsp; 但是在Philippe Kahn离开Borland之后，Anders再也没有了这股来自最亲密战友的强力支援。1997年，Borland新的CEO Delbert Yocam在掌握大权后，整个公司开始走向第二个重要的转变，Delbert对于Borland产品的开发和趋
势也有了不同于Philippe Kahn的看法。&nbsp;&nbsp;&nbsp; 当]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-07-09 11:00:00</pubDate>
		</item>
				<item>
		<title><![CDATA[lz77压缩算法]]></title>
		<link>http://blog.pfan.cn/lingdlz/36573.html</link>
		<description><![CDATA[第五章&nbsp;聪明的以色列人(上)：LZ77&nbsp;第四章&nbsp;第六章&nbsp;&nbsp;全新的思路&nbsp;&nbsp;我们在第三和第四章中讨论的压缩模型都是基于对信息中单个字符出现频率的统计&nbsp;而设计的，直到&nbsp;70&nbsp;年代末期，这种思路在数据压缩领域一直占据着统治地位。在&nbsp;我们今天看来，这种情形在某种程度上显得有些可笑，但事情就是这样，一旦某项&nbsp;技术在某一领域形成了惯例，人们就很难创造出在思路上与其大相径庭的哪怕是更&nbsp;简单更实用的技术来。&nbsp;&nbsp;我们敬佩那两个在数据压缩领域做出了杰出贡献的以色列人，因为正是他们打破了&nbsp;&nbsp;Huffman&nbsp;编码一统天下的格局，带给了我们既高效又简便的“字典模型”。至今&nbsp;，几乎我们日常使用的所有通用压缩工具，象&nbsp;ARJ，PKZip，WinZip，LHArc，RAR&nbsp;，GZip，ACE，ZOO，TurboZip，Compress，JAR……甚至许多硬件如网络设备中内&nbsp;置的压缩算法，无一例外，都可以最终归结为这两个以色列人的杰出贡献。&nbsp;&nbsp;说起来，字典模型的思路相当简单，我们日常生活中就经常在使用这种压缩思想。&nbsp;我们常常跟人说“奥运会”、“IBM”、“TCP”之类的词汇，说者和听者都明白它&nbsp;们指的是“奥林匹克运动会”、“国际商业机器公司”和“传输控制协议”，这实&nbsp;际就是信息的压缩。我们之所以可以顺利使用这种压缩方式而不产生语义上的误解&nbsp;，是因为在说者和听者的心中都有一个事先定义好的缩略语字典，我们在对信息进&nbsp;行压缩（说）和解压缩（听）的过程中都对字典进行了查询操作。字典压缩模型正&nbsp;是基于这一思路设计实现的。&nbsp;&nbsp;最简单的情况是，我们拥有一本预先定义好的字典。例如，我们要对一篇中文文章&nbsp;进行压缩，我们手中已经有一本《现代汉语词典》。那么，我们扫描要压缩的文章&nbsp;，并对其中的句子进行分词操作，对每一个独立的词语，我们在《现代汉语词典》&nbsp;查找它的出现位置，如果找到，我们就输出页码和该词在该页中的序号，如果没有&nbsp;找到，我们就输出一个新词。这就是静态字典模型]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-07-08 10:36:00</pubDate>
		</item>
				<item>
		<title><![CDATA[GDB&nbsp;调试]]></title>
		<link>http://blog.pfan.cn/lingdlz/36444.html</link>
		<description><![CDATA[如何用GDB调试
2007年06月01日 星期五 下午 06:38





GDB概述GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许，各位比较喜欢那种图形界面方式的，像VC、BCB等IDE的调试，但如果你是在 UNIX平台下做软件，你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长，尺有所短”就是这个道理。
一般来说，GDB主要帮忙你完成下面四个方面的功能：
1、启动你的程序，可以按照你的自定义的要求随心所欲的运行程序。2、可让被调试的程序在你所指定的调置的断点处停住。（断点可以是条件表达式）3、当程序被停住时，可以检查此时你的程序中所发生的事。4、动态的改变你程序的执行环境。
从上面看来，GDB和一般的调试工具没有什么两样，基本上也是完成这些功能，不过在细节上，你会发现GDB这个调试工具的强大，大家可能比较习惯了图形化的调试工具，但有时候，命令行的调试工具却有着图形化工具所不能完成的功能。梦颐且灰豢蠢础?/p&gt; 
一个调试示例源程序：tst.c1 #include &lt;stdio.h&gt;23 int func(int n)4 {5 int sum=0,i;6 for(i=0; i&lt;n; i++)7 {8 sum+=i;9 }10 return sum;11 }121314 main()15 {16 int i;17 long result = 0;18 for(i=1; i&lt;=100; i++)19 {20 result += i;21 }2223 printf("result[1-100] = %d \n", result );24 printf("result[1-250] = %d \n", func(250) );25 }
编译生成执行文件：（Linux下）hchen/test&gt; cc -g tst.c -o tst
使用GDB调试：
hchen/test&gt; gdb tst &lt;---------- 启动GDBGNU gdb 5.1.1Copyright 2002 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Publ]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-07-03 15:10:00</pubDate>
		</item>
				<item>
		<title><![CDATA[范式哈夫曼编码]]></title>
		<link>http://blog.pfan.cn/lingdlz/36436.html</link>
		<description><![CDATA[&nbsp;范式哈夫曼编码
1 概念介绍
哈夫曼编码是一种最优的前缀编码技术，然而其存在的不足却制约了它的直接应用。首先，其解码时间为O(lavg), 其中lavg为码字的平均长度；其次，更为最重要的是，解码器需要知道哈夫曼编码树的结构，因而编码器必须为解码器保存或传输哈夫曼编码树。对于小量数据的压缩而言，这是很大的开销。因而，应用哈夫曼编码的关键是如何降低哈夫曼编码树的存储空间。Faller[1973]提出的自适应哈夫曼编码技术使哈夫曼编码树的存储空间降为零，即在使用某种约定的情况下，解码器能动态地重构出和编码器同步的哈夫曼编码树，而不需要任何附加数据。这样做的代价便是时间开销的增大。另一种技术是编码器和解码器使用事先约定的编码树，这种方法只能针对特定数据使用，不具备通用性。另外一种，也是最为常用的方法，便是范式哈夫曼编码。现在流行的很多压缩方法都使用了范式哈夫曼编码技术，如GZIB、ZLIB、PNG、JPEG、MPEG等。范式哈夫曼编码最早由Schwartz[1964]提出，它是哈夫曼编码的一个子集。其中心思想是：使用某些强制的约定，仅通过很少的数据便能重构出哈夫曼编码树的结构。其中一种很重要的约定是数字序列属性(numerical sequence property)，它要求相同长度的码字是连续整数的二进制描述。例如，假设码字长度为4的最小值为0010，那么其它长度为4的码字必为0011, 0100, 0101, ...；另一个约定：为了尽可能的利用编码空间，长度为i第一个码字f(i)能从长度为i-1的最后一个码字得出, 即: f(i) = 2(f(i-1)+1)。假定长度为4的最后一个码字为1001，那么长度为5的第一个码字便为10100。最后一个约定：码字长度最小的第一个编码从0开始。通过上述约定，解码器能根据每个码字的长度恢复出整棵哈夫曼编码树的结构。
2 码字构造
假设有如下的码长序列：&nbsp;符号：a b c d e&nbsp; f&nbsp; g h&nbsp; i &nbsp;j&nbsp; k ... u&nbsp;&nbsp;码长：3 4 4 4 4 4 4 4 4 5 5 ... 5使用count[i]表示长度为i的码字的数目，first[i]表示长度为i的第一个码字的整数值。根据约定3，即first[3] = 0可得到符号]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-07-03 10:43:00</pubDate>
		</item>
				<item>
		<title><![CDATA[用&nbsp;GDB&nbsp;调试程序]]></title>
		<link>http://blog.pfan.cn/lingdlz/36420.html</link>
		<description><![CDATA[用GDB调试程序


说明 
从CSDN的网站上找到的GDB使用说明。 原文标题：用GDB调试程序
作者：haoel （QQ是：753640，MSN是： haoel@hotmail.com）
关键字：gdb 调试 c c++ gun
这篇文章非常好，所以转载了下来，作为收藏。

topGDB概述GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许
，各位比较喜欢那种图形界面方式的，像VC、BCB等IDE的调试，但如
果你是在 UNIX平台下做软件，你会发现GDB这个调试工具有比VC、
BCB的图形化调试器更强大的功能。所谓“寸有所长，尺有所短”就
是这个道理。

一般来说，GDB主要帮忙你完成下面四个方面的功能：

1、启动你的程序，可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。（断点可以是条件表达式）
3、当程序被停住时，可以检查此时你的程序中所发生的事。
4、动态的改变你程序的执行环境。

从上面看来，GDB和一般的调试工具没有什么两样，基本上也是完成
这些功能，不过在细节上，你会发现GDB这个调试工具的强大，大家
可能比较习惯了图形化的调试工具，但有时候，命令行的调试工具却
有着图形化工具所不能完成的功能。让我们一一看来。

top一个调试示例源程序：tst.c
1 #include &lt;stdio.h&gt;
2
3 int func(int n)
4 {
5 int sum=0,i;
6 for(i=0; i&lt;n; i++)
7 {
8 sum+=i;
9 }
10 return sum;
11 }
12
13
14 main()
15 {
16 int i;
17 long result = 0;
18 for(i=1; i&lt;=100; i++)
19 {
20 result += i;
21 }
22
23 printf("result[1-100] = %d \n", result );
24 printf("result[1-250] = %d \n", func(250) );
25 }

编译生成执行文件：（Linux下）
hchen/test&gt;]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-07-02 14:08:00</pubDate>
		</item>
				<item>
		<title><![CDATA[Picking&nbsp;Coins]]></title>
		<link>http://blog.pfan.cn/lingdlz/34665.html</link>
		<description><![CDATA[Picking&nbsp;Coins 

Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB 





Problem description

A pack of coins have been divided into piles, each pile has some number Ni (1 &lt;= Ni &lt;= 25) of coins. All the piles have been placed in an area of R rows(1 &lt;= R &lt;= 100) and C columns (1 &lt;= C &lt;= 100).Given a starting location, you have to make your way out of the area and gather as many coins as you can. From the position (r,c) you can only move to (r-1,c+1), (r, c+1), or (r+1,c+1) and endup your way at any edge of the area. If there exist more than one path that can gather the maximum number of coins, make your path the shortest.

Input

There will be only one testcase in the input file, the first line contains Two space-separated integers, respectively R and C, then followed R lines, Each line contains C space-separated integers in the obvious order, the last few lines each contains two integer which indicate the starting location.]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-04-28 12:31:00</pubDate>
		</item>
				<item>
		<title><![CDATA[练手题]]></title>
		<link>http://blog.pfan.cn/lingdlz/34651.html</link>
		<description><![CDATA[Don't&nbsp;ask&nbsp;woman&nbsp;about&nbsp;her&nbsp;age 

Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB 





Problem description

Mrs Little likes digits most of all. Every year she tries to make the best number of the year. She tryes to become more and more intelligent and every year studies a new digit. And the number she makes is written in numeric system which base equals to her age. To make her life more beautiful she writes only numbers that are divisible by her age minus one. Mrs Little wants to hold her age in secret.You are given a number consisting of digits 0, …, 9 and latin letters A, …, Z, where A equals 10, B equals 11 etc. Your task is to find the minimal number k satisfying the following condition: the given number, written in k-based system is divisible by k&#8722;1. 

Input

Input consists of one string containing no more than 106 digits or uppercase latin letters. 

Output

Output file should contain the only number k, or]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-04-27 20:33:00</pubDate>
		</item>
				<item>
		<title><![CDATA[ati2avxx.exe&nbsp;病毒清除]]></title>
		<link>http://blog.pfan.cn/lingdlz/34315.html</link>
		<description><![CDATA[今天帮一同学解决电脑故障, 之后知道是中了 ati2avxx.exe 病毒以下是自己总结的一些资料, 为中了该毒的网友提供参考, 不保证适合于所有版本的 ati2avxx.exe.
ati2avxx.exe 病毒是我所见比较厉害的病毒
症状: 中毒后隐藏文件完全不可见, 软件无法安装, 另外还有可能无法打开网页&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 杀毒软件无法运行, 系统缓慢, 无法进入安全模式等等. 
以上症状不敢确定有没有,因为我自己没有中过该病毒,但是如果在进程管理器里可以看到该病毒进程而且无法删除的话基本就是中了该病毒. 中过之后,即使重装系统如果没有全盘格式化磁盘(估计谁都不想发这么大的代价)只要打开磁盘,在进程管理器里就又会出现该病毒. 的确是一顽固的生命力强大的病毒, 目前的杀毒软件好像无法对付.
解决方法: 
一, 全盘格式化后重装系统 (不推荐)
二, 这个方法是自己无意中发现的,不保证适合所有版本的 ati2avxx.exe&nbsp;&nbsp; a, 打开任务管理器, 结束 explorer.exe 进程&nbsp;&nbsp; b, 结束 ati2avxx.exe, 如果还没结束而 explorer.exe 进程又运行的话&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 转到 a, 总之先结束 explorer.exe 进程, 之后结束 ati2avxx.exe&nbsp;&nbsp; c, 经过 a,b后 ati2avxx.exe 应该不会再运行了, 在任务管理器里点&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文件-&gt;(新建任务)运行, 输入 cmd 打开命令提示符, 进入 system32 目录&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 输入 attrib -h -s -r -a ati2avxx.exe &nbsp;&nbsp; d, 切换到任务管理器, 点 文件-&gt;(新建任务)运行, 点浏览进入 system32&nbsp;&nbsp;&nbsp;&nbsp; 这时我们可以看到 ati2avxx.exe 文件, 彻底删除该文件(shift+delete)&nbsp;&nbsp;&nbsp;&nbsp; 新建一目录取名为 ati2avxx.]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-04-19 09:00:00</pubDate>
		</item>
				<item>
		<title><![CDATA[VMware访问Windows宿主机的共享文件]]></title>
		<link>http://blog.pfan.cn/lingdlz/34281.html</link>
		<description><![CDATA[VMware访问Windows宿主机的共享文件( 转载 )
&nbsp;&nbsp;&nbsp; 虚拟机的使用，的确给Linux的学习者提供了很大的方便。不过在Linux学习过程中，当涉及到应用软件的使用时，虽然可以直接从网上下载程序包或源码，但用惯了迅雷，对Linux中的下载速度简直无法忍受，且原有的很多资源本应该可以直接使用，没有必要重新下载。因而在两个系统中共享信息成为亟待解决的问题。 

&nbsp;&nbsp;&nbsp;&nbsp;在网上搜索了大量相关信息，介绍两个系统间信息共享的不少，但是提供虚拟机host-guest机不同系统之间资源共享解决方案的不多。在朋友的帮助下，经过多次尝试和摸索，终于有了一些搜获。现提供一套包括局域网配置在内的较为详细的解决方案，供初学者参考。 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 转载请注明本站版权：微品质工作室版权所有
FTP法
&nbsp;&nbsp;&nbsp; 环境介绍： &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 虚拟机：VMware Workstation 5.5 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Host机系统：Windows 2000 Server &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Guest机系统：Red Hat Enterprise Linux 4 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其实作为两个系统而言，要进行资源的共享，方法很多，最初我尝试了使用mount命令挂载文件系统。从命令本身来看，想要挂载一个Windows下的文件系统或驱动盘似乎没有什么问题。 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先在Linux系统/mnt空目录下，建立挂载点：#mkdir /mnt/mystudy&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /mnt目录是专门用来当作挂载点的目录。mystudy是自定义的专用挂载点名称。 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;然后我们看一下mount命令的使用方法：&nbsp]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-04-17 22:44:00</pubDate>
		</item>
				<item>
		<title><![CDATA[在VC中添加响应自定义的消息的代码步骤]]></title>
		<link>http://blog.pfan.cn/lingdlz/33691.html</link>
		<description><![CDATA[1. 首先定义一个消息代码 #define WM_DEBUG WM_USER + 1999　　2. 在窗口头文件中添加class CStreamServerDlg : public CDialog{// Generated message map functions//{{AFX_MSG(CStreamServerDlg)...//}}AFX_MSGafx_msg void OnDebug(WPARAM wParam, LPARAM lParam); ...}　　3. 在窗口的cpp文件中添加BEGIN_MESSAGE_MAP(CStreamServerDlg, CDialog)...ON_MESSAGE(WM_DEBUG, OnDebug)END_MESSAGE_MAP()void CStreamServerDlg::OnDebug(WPARAM wParam, LPARAM lParam){}　　4. 其他地方就可以发送消息pWnd-&gt;PostMessage(WM_DEBUG, (WPARAM)p, 0) )]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-03-31 10:42:00</pubDate>
		</item>
				<item>
		<title><![CDATA[可重入函数与不可重入函数]]></title>
		<link>http://blog.pfan.cn/lingdlz/33135.html</link>
		<description><![CDATA[可重入函数与不可重入函数
2008年01月05日 10:57





主要用于多任务环境中，一个可重入的函数简单来说就是可以被中断的函数，也就是说，可以在这个函数执行的任何时刻中断它，转入OS调度下去执行另外一段代码，而返回控制时不会出现什么错误；而不可重入的函数由于使用了一些系统资源，比如全局变量区，中断向量表等，所以它如果被中断的话，可能会出现问题，这类函数是不能运行在多任务环境下的。
也可以这样理解，重入即表示重复进入，首先它意味着这个函数可以被中断，其次意味着它除了使用自己栈上的变量以外不依赖于任何环境（包括static），这样的函数就是purecode（纯代码）可重入，可以允许有该函数的多个副本在运行，由于它们使用的是分离的栈，所以不会互相干扰。如果确实需要访问全局变量（包括static），一定要注意实施互斥手段。可重入函数在并行运行环境中非常重要，但是一般要为访问全局变量付出一些性能代价。
编写可重入函数时，若使用全局变量，则应通过关中断、信号量（即P、V操作）等手段对其加以保护。
说明：若对所使用的全局变量不加以保护，则此函数就不具有可重入性，即当多个进程调用此函数时，很有可能使有关全局变量变为不可知状态。

示例：假设Exam是int型全局变量，函数Squre_Exam返回Exam平方值。那么如下函数不具有可重入性。
unsigned int example( int para ) 
{
&nbsp;&nbsp;&nbsp; unsigned int temp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Exam = para; // （**）&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; temp = Square_Exam( );&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return temp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; 此函数若被多个进程调用的话，其结果可能是未知的，因为当（**）语句刚执行完后，另外一个使用本函数的进程可能正好被激活，那么当新激活的进程执行到此函数时，将使Exam赋与另一个不同的para值，所以当控制重新回到“temp = Square_Exam( )”]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-03-03 10:13:00</pubDate>
		</item>
				<item>
		<title><![CDATA[红黑树]]></title>
		<link>http://blog.pfan.cn/lingdlz/33124.html</link>
		<description><![CDATA[红黑树: 理论与实现(理论篇) 







红黑树: 理论与实现(理论篇)[修订版]

原创：司徒彦南 
2002年8月19日 


红黑树是一种很有意思的平衡检索树。它的统计性能要好于平衡二叉树(有些书籍根据作者姓名，Adelson-Velskii和Landis，将其称为AVL-树)，因此，红黑树在很多地方都有应用。在C++ STL中，很多部分(目前包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中的红黑树有一些变化，这些修改提供了更好的性能，以及对set操作的支持)。
红黑树的定义如下：




满足下列条件的二叉搜索树是红黑树

每个结点要么是“红色”，要么是“黑色”(后面将说明) 
所有的叶结点都是空结点，并且是“黑色”的 
如果一个结点是“红色”的，那么它的两个子结点都是“黑色”的。 
结点到其子孙结点的每条简单路径都包含相同数目的“黑色”结点 
根结点永远是“黑色”的 
之所以称为红黑树的原因就在于它的每个结点都被“着色”为红色或黑色。这些结点颜色被用来检测树的平衡性。但需要注意的是，红黑树并不是平衡二叉树，恰恰相反，红黑树放松了平衡二叉树的某些要求，由于一定限度的“不平衡”，红黑树的性能得到了提升。
从根结点到叶结点的黑色结点数被称为树的“黑色高度”(black-height)。前面关于红黑树的性质保证了从根结点到叶结点的路径长度不会超过任何其他路径的两倍。
我们来解释一下这个结论。考虑一棵黑色高度为3的红黑树：从根结点到叶结点的最短路径长度显然是2(黑-黑-黑)，最长路径为4(黑-红-黑-红-黑)。由于性质4，不可能在最长路经中加入更多的黑色结点，此外根据性质3，红色结点的子结点必须是黑色的，因此在同一简单路径中不允许有两个连续的红色结点。综上，我们能够建立的最长路经将是一个红黑交替的路径。
由此我们可以得出结论：对于给定的黑色高度为n的红黑树，从根到叶结点的简单路径的最短长度为n-1，最大长度为2(n-1)。
插入和删除操作中，结点可能被旋转以保持树的平衡。红黑树的平均和最差搜索时间都是O(log2 n)。Cormen [2001]给出了对于这一结论的证明。在实际应用中，红黑树的统计性能要好于平衡二叉树，但极端性能略差。
红黑树中结点]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-03-02 21:24:00</pubDate>
		</item>
				<item>
		<title><![CDATA[树，二叉树，森林的转换]]></title>
		<link>http://blog.pfan.cn/lingdlz/33123.html</link>
		<description><![CDATA[树 - 树和森林- 树、森林和二叉树的转换
http://www.educity.cn　作者：自考频道　来源：学赛网　2008年1月5日　发表评论　进入社区 

　　树或森林与二叉树之间有一个自然的一一对应关系。任何一个森林或一棵树可惟一地对应到一棵二叉树;反之，任何一棵二叉树
　　也能惟一地对应到一个森林或一棵树。
　　1.树、森林到二叉树的转换
　　(1)将树转换为二叉树
　　树中每个结点最多只有一个最左边的孩子(长子)和一个右邻的兄弟。按照这种关系很自然地就能将树转换成相应的二叉树：
　　①在所有兄弟结点之间加一连线;
　　②对每个结点，除了保留与其长子的连线外，去掉该结点与其它孩子的连线。
　　【例1】下面(a)图所示的树可转换为(c)图所示的二叉树。具体转换过程可
　　注意：
　　由于树根没有兄弟，故树转化为二叉树后，二叉树的根结点的右子树必为空。
　　(2)将一个森林转换为二叉树
　　具体方法是：
　　① 将森林中的每棵树变为二叉树
　　② 因为转换所得的二叉树的根结点的右子树均为空，故可将各二叉树的根结点视为兄弟从左至右连在一起，就形成了一棵二叉
　　树。
　　【例2】下图中，左边包含三棵树的森林可转换为右边的二叉树。
　　 


　　具体转换过程可
　　2.二叉树到树、森林的转换
　　把二叉树转换到树和森林自然的方式是：若结点x是双亲y的左孩子，则把x的右孩子，右孩子的右孩子，…，都与y用连线连起来
　　，最后去掉所有双亲到右孩子的连线。
　　【例3】下图的森林就是由例2中二叉树转换成的。
　　 


　　具体转换过程可]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-03-02 21:23:00</pubDate>
		</item>
				<item>
		<title><![CDATA[C语言可变参数函数的实现]]></title>
		<link>http://blog.pfan.cn/lingdlz/33121.html</link>
		<description><![CDATA[// 下文转自网络
C语言可变参数函数的实现 
一、什么是可变参数
我们在C语言编程中有时会遇到一些参数个数可变的函数,例如printf()函数,其函数原型为:
int printf( const char* format, ...);
它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的（用三个点“…”做参数占位符）,实际调用时可以有以下的形式: printf("%d",i);
printf("%s",s);
printf("the number is %d ,string is:%s", i, s);&nbsp;&nbsp;&nbsp;
以上这些东西已为大家所熟悉。但是究竟如何写可变参数的C函数以及这些可变参数的函数编译器是如何实现，这个问题却一直困扰了我好久。本文就这个问题进行一些探讨,希望能对大家有些帮助.
二、写一个简单的可变参数的C函数
先看例子程序。该函数至少有一个整数参数,其后占位符…，表示后面参数的个数不定. 在这个例子里，所有的输入参数必须都是整数，函数的功能只是打印所有参数的值.
函数代码如下：
//示例代码1：可变参数函数的使用
＃i nclude "stdio.h"
＃i nclude "stdarg.h"
void simple_va_fun(int start, ...)
{
&nbsp;&nbsp;&nbsp; va_list arg_ptr;
&nbsp;&nbsp;&nbsp; int nArgValue =start;
&nbsp;&nbsp;&nbsp; int nArgCout=0;&nbsp;&nbsp;&nbsp;&nbsp; //可变参数的数目
&nbsp;&nbsp;&nbsp; va_start(arg_ptr,start); //以固定参数的地址为起点确定变参的内存起始地址。
&nbsp;&nbsp;&nbsp; do
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++nArgCout;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("the %d th arg: % d\n",nArgCout,nArgValue]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-03-02 21:19:00</pubDate>
		</item>
				<item>
		<title><![CDATA[#pragma&nbsp;pack(n)作用]]></title>
		<link>http://blog.pfan.cn/lingdlz/32269.html</link>
		<description><![CDATA[通过#pragma pack(n)改变C编译器的字节对齐方式在C语言中，结构是一种复合数据类型，其构成元素既可以是基本数据类型（如int、long、float等）的变量，也可以是一些复合数据类型（如数组、结构、联合等）的数据单元。在结构中，编译器为结构的每个成员按其自然对界（alignment）条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储，第一个成员的地址和整个结构的地址相同。&nbsp;&nbsp;&nbsp;&nbsp; 例如，下面的结构各成员空间分配情况：struct test {&nbsp;&nbsp;&nbsp;&nbsp; char x1;&nbsp;&nbsp;&nbsp;&nbsp; short x2;&nbsp;&nbsp;&nbsp;&nbsp; float x3;&nbsp;&nbsp;&nbsp;&nbsp; char x4;};&nbsp;&nbsp;&nbsp;&nbsp; 结构的第一个成员x1，其偏移地址为0，占据了第1个字节。第二个成员x2为short类型，其起始地址必须2字节对界，因此，编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然对界地址上，在它们前面不需要额外的填充字节。在test结构中，成员x3要求4字节对界，是该结构所有成员中要求的最大对界单元，因而test结构的自然对界条件为4字节，编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。更改C编译器的缺省字节对齐方式&nbsp;&nbsp;&nbsp;&nbsp; 在缺省情况下，C编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地，可以通过下面的方法来改变缺省的对界条件：　　· 使用伪指令#pragma pack (n)，C编译器将按照n个字节对齐。&nbsp;&nbsp;&nbsp;&nbsp; · 使用伪指令#pragma pack ()，取消自定义字节对齐方式。&nbsp;&nbsp;&nbsp;&nbsp; 另外，还有如下的一种方式：&nbsp;&nbsp;&nbsp;&nbsp; · __attribute((aligned (n)))，让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n，则按照最大成员的长度来对齐。&nbsp;&nbsp;&nbsp;&nbsp]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-01-18 16:09:00</pubDate>
		</item>
				<item>
		<title><![CDATA[使用&nbsp;ACCESS&nbsp;时遇到的恼火问题]]></title>
		<link>http://blog.pfan.cn/lingdlz/31730.html</link>
		<description><![CDATA[使用 ACCESS 时遇到的恼火问题
这几天做毕业设计,是与ACCESS 数据库有关的, 因为是刚开始测试,所以手动在ACCESS里输入一些数据,但是当我想输入"CObject" 时却莫明其妙的变成了"Cobject", 如下图: 

我试了其它一些单词发现有的变了,有的没变,当时很恼火,差点没骂ACCESS设计者的老祖宗,最后在输入时出现了一个闪电图标,点了下才知道是"自动更正"把我的输入自动给改了,为什么拿我当白痴,改了我的输入后不给半点提示 !!! 
类似的好像WORD里也有这个功能,我觉得这些功能完全没有必要,毕竟用户不是白痴,当今软件功能都非常强,并不是每个用户都会在使用前不厌其烦的翻你那厚厚的用户手册,个人认为类似的功能要么就不要提供,如果定要提供也要默认禁用.]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2008-01-01 22:21:00</pubDate>
		</item>
				<item>
		<title><![CDATA[在DLL中使用资源]]></title>
		<link>http://blog.pfan.cn/lingdlz/31516.html</link>
		<description><![CDATA[在DLL中使用资源( 此文系网络转载 )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在CSDN论坛上最常看见的关于DLL的问题就是如何在DLL中使用对话框，这是一个很普遍的关于如何在DLL中使用资源的问题。这里我们从Win32 DLL和MFC DLL两个方面来分析并解决这个问题。
1．Win32 DLL
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在Win32 DLL中使用对话框很简单，你只需要在你的DLL中添加对话框资源，而且可以在对话框上面设置你所需要的控件。然后使用DialogBox或者CreateDialog这两个函数（或相同作用的其它函数）来创建对话框，并定义你自己的对话框回调函数处理对话框收到的消息。下面通过一个具体实例来学习如何在Win32 DLL中使用对话框，可以按照以下步骤来完成这个例子：
&nbsp;
1）在VC菜单中File-&gt;New新建一个命名为UseDlg的Win32 Dynamic-Link Library工程，下一步选择A simple DLL project。
&nbsp;
2）在VC菜单中Insert-&gt;Resource添加一个ID为IDD_DLG_SHOW的Dialog资源，将此Dialog上的Cancel按钮去掉，仅保留OK按钮。再添加一个ID为IDD_ABOUTBOX的对话框，其Caption为About。保存此资源，将资源文件命名为UseDlg.rc。并将resource.h和UseDlg.rc加入到工程里面。
&nbsp;
3）在UseDlg.app中包含resource.h，并添加如下代码：
&nbsp;
HINSTANCE hinst = NULL; 
HWND hwndDLG = NULL;
&nbsp;
BOOL CALLBACK DlgProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam);
BOOL CALLBACK AboutProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam);
extern "C" __declspec(dllexport) void ShowDlg()]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2007-12-20 17:08:00</pubDate>
		</item>
				<item>
		<title><![CDATA[COleVariant&nbsp;类]]></title>
		<link>http://blog.pfan.cn/lingdlz/31480.html</link>
		<description><![CDATA[&nbsp;VARIANT、COleVariant 和_variant_t&nbsp;&nbsp;

 &nbsp;&nbsp; (转)
&nbsp;在OLE、ActiveX和COM中，VARIANT数据类型提供了一种非常有效的机制，由于它既包含了数据本身，也包含了数据的类型，因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版：struct tagVARIANT {　VARTYPE vt;　union {　　short iVal; // VT_I2.　　long lVal; // VT_I4.　　float fltVal; // VT_R4.　　double dblVal; // VT_R8.　　DATE date; // VT_DATE.　　BSTR bstrVal; // VT_BSTR.　　…　　short * piVal; // VT_BYREF|VT_I2.　　long * plVal; // VT_BYREF|VT_I4.　　float * pfltVal; // VT_BYREF|VT_R4.　　double * pdblVal; // VT_BYREF|VT_R8.　　DATE * pdate; // VT_BYREF|VT_DATE.　　BSTR * pbstrVal; // VT_BYREF|VT_BSTR.　};}; 　　显然，VARIANT类型是一个C结构，它包含了一个类型成员vt、一些保留字节以及一个大的union类型。例如，如果vt为VT_I2，那么我们可以从iVal中读出VARIANT的值。同样，当给一个VARIANT变量赋值时，也要先指明其类型。例如：VARIANT va;:: VariantInit(&amp;va); // 初始化int a = 2002;va.vt = VT_I4; // 指明long数据类型va.lVal = a; // 赋值 　　为了方便处理VARIANT类型的变量，Windows还提供了这样一些非常有用的函数：　　VariantInit —— 将变量初始化为VT_EMPTY；　　VariantClear —— 消除并初始化VARIANT；　　VariantChangeType —— 改变VARIANT的类型；　　Vari]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2007-12-17 22:48:00</pubDate>
		</item>
				<item>
		<title><![CDATA[匈牙利命名法前缀]]></title>
		<link>http://blog.pfan.cn/lingdlz/31479.html</link>
		<description><![CDATA[匈牙利命名法(转载)
&nbsp;
匈牙利命名法虽然是C++所使用的,但WIN32ADA与它也紧密关联. 




前缀
含义

a&nbsp;&nbsp;
array&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;数组

b
bool(int)&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;布尔

by
Unsigned char&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;无符号字符(字节)

c
Char&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2007-12-17 20:33:00</pubDate>
		</item>
				<item>
		<title><![CDATA[Windows&nbsp;版贪吃蛇]]></title>
		<link>http://blog.pfan.cn/lingdlz/31304.html</link>
		<description><![CDATA[Windows 版贪吃蛇
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;－－我的第一个windows 程序
一：游戏共六个界面，默认界面如下：

二：游戏简介&nbsp; 1）该游戏界面共提供了六个，您可以自己修改界面。&nbsp; 2）游戏在老版贪吃蛇有了更新，提供了各种不同的果实，不同果实有&nbsp; 不同的作用，详情请看“帮助”菜单里的“游戏规则”，或者在游戏&nbsp; 区点击右键，选择“游戏规则”。&nbsp; 3）为了提高趣味兴，游戏设置了七个级别，每升一级，改变蛇的颜色&nbsp;&nbsp;&nbsp; 并自动切换下一个界面。
三：游戏的实现方法&nbsp; 该游戏虽然是用 C++写的，但并没有用MFC，只是调用了一些API函数&nbsp; 其中蛇的移动，以及果实的随机产生，均使用定时器，另外蛇的喷火&nbsp; 功能也是用定时器实现的，本来是用多线程，但是多线程就是在优先&nbsp; 级最低的情况下运行也超快，如果要用空循环来延时倒不如定时器来&nbsp; 的简洁。&nbsp; 游戏主要参考了skyblue 的 &lt;&lt;Visual C++经典游戏程序设计&gt;&gt;&nbsp; 但是却又有本质上的不同，主要不同如下：&nbsp;&nbsp; 1）类的封装方法，skyblue 的程序设计了两个类，我的设计了三个 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (snake,fruit,interface),skyblue 的全局变量太多，而我只设计&nbsp;&nbsp;&nbsp;&nbsp; 了一个 interface 类的全局对象&nbsp;&nbsp; 2）从 bitmap 文件里提取资源，在 skyblue 里的实现非常机械，而我&nbsp;&nbsp;&nbsp;&nbsp; 用一个枚举简洁的实现，并且在位图内容布局改变的情况下，只需&nbsp;&nbsp;&nbsp;&nbsp; 修改少量代码。&nbsp;&nbsp; 3）蛇的移动算法实现也不同，skyblue 用动态内存，个人认为&nbsp;&nbsp]]></description>
		<author><![CDATA[江南孤峰]]></author>
		<pubDate>2007-12-07 16:57:00</pubDate>
		</item>
		</channel>
</rss>