月度归档:2011年06月

学习二叉树,研究数据结构的本质

二叉树的定义(递归定义)[Binary Tree]:它是n(n>=0)个节点的有限集合,当n=0时,它是空集,n<>0时,它由一个根节点和两棵互不相交的子二叉树构成,分别称为左、右子树。
二叉树有五种基本形态:(1)空集;(2)左子树为空;(3)右子树为空;(4)左右皆为空;(5)左右皆不为空。
有上面二叉树的定义知,每一个二叉树中的节点有如下特征:(1)至多两个子节点;(2)节点有左右之分;(3)有一个左节点活又节点;(4)没有子节点。
二叉树与树、有序树的不同点: 二叉树与度数不超过不超过2的树和有序树不同。在有序树中,虽然也有左右之分,但如果一个节点只有一个子节点,就无须区分左右节点。而在二叉树中,即使一个节点也是区分左右的,
二叉树遍历(Traversal) 二叉树的遍历就是沿着某条搜索路径,一次对树中的每个节点访问且仅访问一次。由二叉树的递归定义知,我们可以用递归方法遍历:
a. 访问树的根节点(N--root Node);
b. 遍历根节点的左子树(L–Left);
c.遍历根节点的右子树(R);
由于二叉树是“L/NR” 结构,所以我们可以有如下可能的遍历次序:LNR, LRN; NLR, || NRL; RLN, RNL, 对这个序列进行调整,
LNR, LRN, NLR, || RLN, NRL,RNL, 这时我们就会发现这个序列关于 "||" 轴对称,也就是一边的是另一边的遍历的倒序。所以,我们只需要研究其中的三种就可以了。依据根节点被访问的次序,我们就可以得到前序遍历 NLR(Preorder Traversal), 中序遍历LNR(Inorder Traversal), 后序遍历LRN(Postorder Traversal).
下面我们来看看二叉树的存储问题。在这里,我们现不研究它如何在硬盘/文件中的存储方式,先研究如何把它用数据结构方式存储到内存中,方便我们的操作。
二叉树的存储(内存中的结构)对于二叉树,它的结构由以下三个要素构成:(1)节点;(2)节点的连接关系;(3)父节点相同时子节点的左右次序。知道了这三个要素,我们也就知道了我们需要设计出一种结构来保存这三个元素,但此时,我们还要多想一点,这三个元素中哪哪一个是主导元素呢? 是节点?边?左右次序? 这时也许要迷惑了,为什么要想这么多呢? 请注意,虽然它自身在定义时是以节点为主体来定义的,但二叉树是一种抽象的结构,它不仅仅可以存储节点(一般被用来保存数据),同时也保存了边(一般保存了节点之间的关系,如父子关系。),所以,以何为主体完全可以由自己的实机需要来决定。
下面我们先假设我们认为主体是节点(这也是数据结构教科书中常常默认的),也就是我们要处理的数据,那我们可以设计出下面的结构,
/*****************************
* binary tree node definition
*****************************/
typedef struct binaryNode{
T *data; /* T is the type you stored in node. data is the data in the node.*/
struct binaryNode *left; /* left node of parent node. */
struct binaryNode *right; /* right node of parent node. */
}BinaryNode;
由前面遍历的递归描述我们可以得到下面的递归遍历算法,
/*********************
*binarytree.h
**********************/
#include
#include
#include

/*****************************
* binary tree node definition
*****************************/
typedef struct binaryNode{
T *data; /* T is the type you stored in node. data is the data in the node.*/
struct binaryNode *left; /* left node of root. */
struct binaryNode *right; /* right node of root. */
}BinaryNode;

/********************************
* Inorder binary tree traversal.
********************************/
void inorder(BinaryNode* root)
{
if (root != NULL) {
inorder(root -> left); /* recur left */
printf("%c ", root -> data);
inorder(root -> right); /* recur right */
}
}

/*********************************
* Preorder binary tree traversal.
**********************************/

void preorder(BinaryNode* root)
{
if (root != NULL) {
printf("%c ", root -> data);
preorder(root -> left);
preorder(root -> right);
}
}

/***********************************
* Postorder binary tree traversal.
***********************************/

void postorder(BinaryNode* root)
{
if (root != NULL) {
postorder(root -> left);
postorder(root -> right);
printf("%c ", root -> data);
}
}

这个递归遍历算法看起来很简单,但效率不会太高。因为递归调用会倒置没递归一次都需要在栈中保存一个函数指针,而系统的栈的空间大小却是非常有限的(一般是 1M到几M),所以,当数据很多时就可能出现stack over flow的错误。所以,这个递归算法通常在小数据量的情形下是可行的,太多的数据时就得考虑用非递归算法了。
接下来,我们就考虑用非递归方式实现遍历。可参考http://blog.csdn.net/rainer7/archive/2004/08/10/70671.aspx

作者:豆博草堂

0.7check规则

今天在工作中遇到个问题,发现有个已经单体测试完成的source严重与详细设计书不一致,经过调查发现,程序在单体测试开始过程中进行了不断的修正,而没有同步的将详细设计对应的进行修正。于是,我查看了版本发现,程序从单体测试开始到测试完成共修正了18次,而详细设计仅修改了7次,详细设计对应频率为7/18=0.39,这个比值直观的感觉就比较小了!然后我查看了没有不一致的代码和详细设计,并计算了这个比值,发现,它们基本在0.7左右波动。呵呵,也许这就是个规则,也就是说,平均每修改10次source就应该对应修改7次详细设计,小于这个值就很有可能出现不一致现象,一定要进行严格 check,而大于这个可能会导致大家的厌烦,所以我喜欢把这个称为0.7check规则。以后检查时先看这个频率

p=详细设计对应修改次数/source修改次数
当p<0.7时, 一定要进行再次check; 0.7=<p<0.8时,应该基本正常;p>=0.8时,详细设计修改次数过多,增加了工作量.
希望这个规则能对大家管理项目有所帮助.:)

作者:豆博草堂

Fedora 10下面通过华为EC266无线网卡连接电信3G

    经过实验fedora 右上角那个NetWork Manager Applet、KPPP、Network Device Control, 现在终
于可以通过Network Device Control来实现电信的无线3G上网了。现在,我把配置方法记录到这里,
同时记录不同工具配置后出现的问题。
    虽然我的无线网卡是EC266, 只要你的无线上网卡能够被fedora 10识别, 下面的方法应该是适
用于所有无线上网卡的。判断是否被识别的方法很简单,将你的无线上网卡与电脑连接,然后,右
键点击右上角的那个网络图标(就是NetWork Manager Applet),点击Edit Connections菜单,点
击Mobile Broadband 标签, 点击Add按钮,这时会弹出一个对话框,如果您的上网卡已经被识别,
对话框里面应该出现一个**Modem的条目,比如,我的EC266被识别成了E620, 就显示了
Huawei Technologies E620 USB Modem .
  
   成功案例Network Device Control:
   1. 进入Network Device Control:
      通过面板上System–>Administration –> Network Device Control, 点击Configuration,
输入root用户密码。
   2. 添加Modem{即无线上网卡}
      在Network Device Control中点击Hardware标签,然后点击工具栏的 New图标,此时就会出现
Choose Hardware Type的对话框,在其中选择Modem, 点击OK按钮,在出现的对话框中选择Modem Device,
 对于USB类型的上网卡, Fedora 10 一般会挂载到/dev/ttyUSB* (*为0,1,2,3,…)等下面, 这时,
你需要选择/dev/ttyUSB0,/dev/ttyUSB1, /dev/ttyUSB2来试验下,开始先选择/dev/ttyUSB0 吧,其
他参数不要修改,点击OK按钮,这时您的Hardware标签下应该多出一个类型为Modem的设备。
   3. 添加设备
      点击Device标签, 然后点击New图标,在出现的对话框中选择Modem Connection, 点击Forward,
 在对话框中的Phone number 中填入#777, 在Provider name中填入随便一个名字,Login name和Password
都填入card,然后点击Forward, 后面的信息用默认直。最后,您的设备标签下应该多出一个Modem
Connection, 然后激活他,如果不行,试着在2中所描述的位置更换设备加载位置/dev/ttyUSB0为其它的,
如果选择对了,应该在激活后就可以上网了。
  
   特别注意:如果您下次将上网卡插到了别的USB口上,如果出现无发上网的现象,可以试着修改2里面
设备的挂载位置来试。

-------------------------------------------------------------------------------
   失败案例:
   NetWork Manager Applet:怎么配都无法连接,虽然它里面的选项最接近我们无线网卡的实际选项,
有APN, PIN, LoginName/Passwords, phone number等。
   KPPP: 配置类似与Network Device Control,选设备的方式和上面2中一样,也要试,如果选择
正确,就会连接到网络,也得到了IP,但却没有速度。估计某些参数不对。
   -----------------------------------------------------------------------------

 

作者:豆博草堂