欢迎访问binary的Blog   虚心使人进步,骄傲使人落后。

          W3CHINA Blog首页    管理页面    写新日志    退出



«November 2025»
1
2345678
9101112131415
16171819202122
23242526272829
30


登录

用户名称:
登陆密码:
密码保存:


联系我
email: binaryluo(at)gmail.com

我的分类

日志更新

最新评论

留言板

Blog信息

 
blog名称:二进制-虚心使人进步,骄傲使人落后。
日志总数:42
评论数量:370
留言数量:88
访问次数:643787
建立时间:2005年2月19日




[算法设计与分析][原创]知先序后序构建二叉树改进算法
原创空间,  软件技术

binaryluo 发表于 2006/1/1 7:27:37

原来在“已知先序中序序列求二叉树算法”( http://blogger.org.cn/blog/more.asp?name=binaryluo&id=11409)中的算法"生成左右子树时(第二个for循环)外层循环为n-1次,其中定位pre[ i ]时最坏比较n次,所以基本操作次数是n+n*(n-1),时间复杂度为O(n方)",考虑到在order中定位pre[ i ]的时候可以先将中序的序列进行一次索引排序,即:索引排序就是先为数列建立一个索引表,然后在索引表上进行排序。举个例子:原中序数组InOrder[n]={f,e,a,g,d,c,b,h}那么先建立一个索引(为了清楚起见,我把它所对应的InOrder值也写在旁边):Idx[n]={<0,f>,<1,e>,<2,a>,<3,g>,<4,d>,<5,c>,<6,b>,<7,h>}然后以InOrder[n]为关键字,对Idx[n]进行排序。最后Idx[n]={<2,a>,<6,b>,<5,c>,<4,d>,<1,e>,<0,f>,<3,g>}(实际上Idx[n]只用保存{2,6,5,4,1,0,3}就可以了,后面的值可以随时在InOrder里查)。这样排序之后,既可以在O(log n)的时间内,通过Idx数组在InOrder中查到任意需要的节点,又不会破坏原InOrder的顺序。上述构造能在O(log n)的时间能找到所需要的子树边界,从而把时间复杂度降到O(nlogn)。改进后的算法:(红色的部分是在原算法上改进的地方)#define   FALSE    0#define   TRUE     1typedef int Status;typedef struct {       BiTNode node;  // 原来中序中的节点       int index;           // 新加的索引字段}IndexNode, IndexList;Status IndexSort(BiTNode order[], IndexList idx){       for (i = 0; i < order.length; i ++){  // 构建一个索引表             idx[ i ].node = order[ i ];             idx[ i ].index = i;       }       QSort(idx, 0, L.length);  // 快速排序,需在清华数据结构274-275页算法的基础上稍加改变       return OK;}Status createTree(BiTree &T, BiTNode pre[], BiTNode order[]){          // 已知先序序列pre和中序序列order,构建一个二叉树T的非递归实现。          // 其中涉及到的数据结构请参看清华大学《数据结构》(C语言版)                      IndexList *idx;                      IndexSort(order, idx);  // 对order索引排序          InitStack(Stack);        //初始化栈          for (i = 0; i < order.length; i ++) visited[ i ] = FALSE;                                            // 初始化visited,visited用于标记order                                            // 中的元素是否已经被访问过          T = (BiTree *) malloc (sizeof(BiTree));          T.data = pre[0]; T -> lchild = NULL; T -> rchild = NULL;                                           // 生成根节点,先序pre中的第一个元素肯定是树根,                                           // 左右孩子初始化为NULL。          p = idx[ pre[ 0 ].data - idx[ 0 ].data].index   // 在order中找到根节点所在的位置          visited[ p ] = TRUE;                         // 标识order中的根元素已被访问过          cur = T;                                    // cur表示当前构建的节点          for (i = 1; i < pre.length; ) {                               if (p > 0 && !visited[p - 1]) {                        // 在order中pre[ i ]的左边有元素并且未被访问过,说明有左子树存在,                        // 生成左子树                        cur->lchild = (BiTNode *) malloc (sizeof(BiTNode));                        cur->lchild.data = pre[ i ];                                        // 将当前pre中的元素赋给lchild后指向下一个元素                        cur->lchild->lchild = NULL; cur->rchild->rchild= NULL;                        p = idx[pre[ i  ++].data - indx[ 0 ].data].index; // 用索引在order中定位                        visited[ p ] = TRUE;                        Push(Stack, cur);        // 当前节点进栈                        cur = cur->lchild;        // 当前节点指向左孩子                }                else if (p < order.length && !visited[p + 1]) {                        // 生成右子树                        cur->rchild = (BiTNode *) malloc (sizeof(BiTNode));                        cur->rchild.data = pre[ i ];                        cur->rchild.lchild = NULL; cur->rchlid.rchild = NULL;                        p = idx[pre[ i  ++].data - idx[ 0 ].data].index; // 用索引在order中定位                        visited[ p ] = TRUE;                        cur = cur->rchild;                }                else {                        Pop(Stack, cur);        // 左右都没有子树即是叶子,则退栈                        p = idx[cur.data - indx[ 0 ].data].index; // 用索引在order中定位                }          }}改进后的算法生成左右子树时(第二个for循环)的时间复杂度降为O(n),而在进行索引排序时的时间复杂度由选择的排序算法决定,在此选择了快速排序,所以时间复杂度为O(nlogn)。总的算法时间复杂度:O(nlogn) + O(n),取O(nlogn)。但是由于要创建一个索引表,所以空间复杂度为O(n)。在此特别感谢W3China的 Logician 的提示。^_^ 


阅读全文(4283) | 回复(1) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.031 second(s), page refreshed 144807581 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号