Perl 闭包模拟类实现二叉树

perl 实现二叉树,二叉平衡树  #! /usr/bin/perl -wuse strict;use warnings;use Data::Dumper;my $head = undef;my $copy = /$head;foreach my $index( 1 .. 10 ){  &AVLTree_insert($copy, $index);}#&create_BSTree( $copy );#&create_tre 阅读详情

在上一篇文章中用函数方式实现了一个二叉树,本篇用闭包模拟类的方式来重新实现,不同于传统意义的Perl 类,否则也不用去费力重新实现,本篇用闭包来模拟类的一些行为,以消息传递的方式调用方法。


功能同上一个版本的基本一样,是用闭包的好处:

1。 模拟类行为,开放类方法

2。 内部变量不可直接修改,只能通过方法调用获取或修改值

3。 消息类型多样,自己可以随便控制


特点:

1。 每次取得一个节点(增加,删除,修改)都是一个闭包Node 的返回,可以看作对应的类实例,可通过进一步调用来获取相应的值

2。 只有两个模拟类,Node and BNSTree,通篇都是通过这两个闭包类来进行操作


附代码以及编写过程中的一些注释:

use strict;
use warnings;
use Data::Dumper;

sub Node {
    my $_node = { left => undef, right => undef, key => undef, parent => undef };

    # set multiple value at same time
    my %params = @_;
    map { $_node->{$_} = $params{$_} if defined $params{$_} } keys %$_node;

    # set or get value for each item
    return sub {
        my ( $msg, $value ) = @_;
        if ( exists $_node->{$msg} ) {
            defined $value ? $_node->{$msg} = $value : $_node->{$msg};
        }
        # because cannot set one of attribute of _node to undef, so add one method delete to set to undef
        elsif ( $msg eq 'delete' && $value ) {
            $_node->{$value} = undef;
        }
        else {
            die "Undefined key: $msg";
        }
    }
}

sub BNSTree {
    my $root = undef;

    my $empty = sub {
        return !$root;
    };

    #this is original version for insert, logic is clear but code is too much
    my $insert_old = sub {
        my ($value) = @_;
        if ( $empty->() ) {
            my $node = Node( key => $value );
            return $root = $node;
        }

        my $tmp = $root;
        while ( $value != $tmp->('key') ) {
            if ( $value < $tmp->('key') && $tmp->('left') ) {
                $tmp = $tmp->('left');
            }
            elsif ( $value > $tmp->('key') && $tmp->('right') ) {
                $tmp = $tmp->('right');
            }
            else {
                last;
            }
        }

        if ( $value < $tmp->('key') ) {
            my $node = Node( key => $value, parent => $tmp );
            return $tmp->( left => $node );
        }
        elsif ( $value > $tmp->('key') ) {
            my $node = Node( key => $value, parent => $tmp );
            return $tmp->( right => $node );
        }
        else {
            return $tmp;
        }
    };

    #this is optimized version for insert, almost 1/2 less code than previous and tight
    my $insert = sub {
        my ($value) = @_;
        return $root = Node( key => $value ) if $empty->();

        my $tmp = $root;
        while ( $value != $tmp->('key') ) {
            if ( $value < $tmp->('key') ) {
                $tmp->('left')
                  ? $tmp = $tmp->('left')
                  : return $tmp->( left => Node( key => $value, parent => $tmp ) );
            }
            elsif ( $value > $tmp->('key') ) {
                $tmp->('right')
                  ? $tmp = $tmp->('right')
                  : return $tmp->( right => Node( key => $value, parent => $tmp ) );
            }
            #~ else{ last; }
        }
        return $tmp;
    };

    my $min_max = sub {
        #~ my ($msg) = @_;
        #~ return if $empty->();

        #~ my $tmp = $root;
        #~ while($tmp->($msg)){
        #~ $tmp = $tmp->($msg);
        #~ }
        #~ return $tmp;

        #previous version work for the whole tree, but successor need it, so modify it that can be used by sub-tree min max
        my ( $msg, $tmp_root ) = @_;
        return if !$tmp_root;

        while ( $tmp_root->($msg) ) {
            $tmp_root = $tmp_root->($msg);
        }
        return $tmp_root;
    };

    my $search = sub {
        my ($value) = @_;
        return if $empty->();

        my $tmp = $root;
        while ( $value != $tmp->('key') ) {
            if ( $value < $tmp->('key') ) {
                $tmp->('left') ? $tmp = $tmp->('left') : return;
            }
            elsif ( $value > $tmp->('key') ) {
                $tmp->('right') ? $tmp = $tmp->('right') : return;
            }
            else { last; }
        }
        return $tmp;
    };

    my $successor = sub {
        my ($value) = @_;

        #~ return undef if $empty->();
        my $search_item = $search->($value);
        return if !$search_item;

        if ( $search_item->('right') ) {
       #~ my $tmp = $search_item->('right');
       #~ while($tmp->('left')){
       #~ $tmp = $tmp->('left');
       #~ }
       #~ return $tmp;
       # previous version need expend min function, so modify it use subtree min
            return $min_max->( 'left', $search_item->('right') );
        }

        my $tmp = $search_item;
        while ($tmp->('parent')
            && $tmp->('parent')->('right')
            && $tmp->('parent')->('right') == $tmp )
        {
            $tmp = $tmp->('parent');
        }
        return $tmp->('parent');
    };

    my $predecessor = sub {
        my ($value) = @_;

        #~ return undef if $empty->();
        my $search_item = $search->($value);
        return undef if !$search_item;

        if ( $search_item->('left') ) {
       #~ my $tmp = $search_item->('right');
       #~ while($tmp->('left')){
       #~ $tmp = $tmp->('left');
       #~ }
       #~ return $tmp;
       # previous version need expend min function, so modify it use subtree min
            return $min_max->( 'right', $search_item->('left') );
        }

        my $tmp = $search_item;
        while ($tmp->('parent')
            && $tmp->('parent')->('left')
            && $tmp->('parent')->('left') == $tmp )
        {
            $tmp = $tmp->('parent');
        }
        return $tmp->('parent');
    };

    #go through from upper level to lower level
    my $level_order = sub {
        return if $empty->();

        #~ my $tmp = $root;
        my @stack = ($root);
        while (@stack) {
            my $tmp = shift @stack;
            print $tmp->('key'), ' ';
            push @stack, $tmp->('left')  if $tmp->('left');
            push @stack, $tmp->('right') if $tmp->('right');
        }
    };

    my $in_order = sub {
        return if $empty->();

        my $tmp   = $root;
        my @stack = ();
        while ( $tmp || @stack ) {
            if ($tmp) {
                print $tmp->('key'), ' ';
                push @stack, $tmp;
                $tmp = $tmp->('left');
            }
            else {
                $tmp = pop @stack;

                #~ print $tmp->('key'),' ';
                $tmp = $tmp->('right');
            }
        }
    };

    my $pre_order = sub {
        return if $empty->();

        my $tmp   = $root;
        my @stack = ();
        while ( $tmp || @stack ) {
            if ($tmp) {
                push @stack, $tmp;
                $tmp = $tmp->('left');
            }
            else {
                $tmp = pop @stack;
                print $tmp->('key'), ' ';
                $tmp = $tmp->('right');
            }
        }
    };

    my $suc_order = sub {
        return if $empty->();

        my $tmp   = $root;
        my @stack = ();
        while ( $tmp || @stack ) {
            if ($tmp) {
                push @stack, $tmp;
                $tmp = $tmp->('right');
            }
            else {
                $tmp = pop @stack;
                print $tmp->('key'), ' ';
                $tmp = $tmp->('left');
            }
        }
    };

    my $internal_delete = sub {
        my ($node) = @_;

        if ( $node->('parent') ) {
            my $pchild =
              $node->('parent')->('key') > $node->('key') ? 'left' : 'right';
            if ( !$node->('left') && !$node->('right') ) {
                $node->('parent')->( delete => $pchild );
            }
            elsif ( !$node->('left') || !$node->('right') ) {
                my $child = $node->('left') ? 'left' : 'right';

                $node->('parent')->( $pchild => $node->($child) );
                $node->($child)->( parent => $node->('parent') );
            }
        }
        else {
            if ( !$node->('left') && !$node->('right') ) {
                $root = undef;
            }
            elsif ( !$node->('left') || !$node->('right') ) {
                my $child = $node->('left') ? 'left' : 'right';

                $root = $node->($child);
                $node->($child)->( delete => 'parent' );
            }
        }
    };

    my $delete = sub {
        my ($value) = @_;
        my $tmp = $search->($value);

        if ( !$tmp ) {
            return;
        }
        elsif ( !$tmp->('left') || !$tmp->('right') ) {
            $internal_delete->($tmp);
        }
        else {
            my $suc = $successor->($value);
            $internal_delete->($suc);
            $tmp->( 'key', $suc->('key') );
        }
    };

    #initial binary search tree with more values
    for (@_) {
        $insert->($_);
    }

    return sub {
        my ( $msg, $value ) = @_;
        if ( $msg eq 'empty' ) {
            $empty->();
        }
        elsif ( $msg eq 'insert' ) {
            $insert->($value);
        }
        elsif ( $msg eq 'min' ) {
            $min_max->( 'left', $root );
        }
        elsif ( $msg eq 'max' ) {
            $min_max->( 'right', $root );
        }
        elsif ( $msg eq 'search' ) {
            $search->($value);
        }
        elsif ( $msg eq 'successor' ) {
            $successor->($value);
        }
        elsif ( $msg eq 'predecessor' ) {
            $predecessor->($value);
        }
        elsif ( $msg eq 'print' && $value && $value eq 'pre' ) {
            $pre_order->();
        }
        elsif ( $msg eq 'print' && $value && $value eq 'suc' ) {
            $suc_order->();
        }
        elsif ( $msg eq 'print' ) {
            $in_order->();
        }
        elsif ( $msg eq 'delete' ) {
            $delete->($value);
        }
    }
}

my $a = BNSTree(qw(14  20 18 21 7 ));

$a->( 'delete', 14 );
$a->( parent => undef );
$a->('print');
print "\n";
$a->( 'print', 'pre' );
print "\n";
$a->( 'print', 'suc' );
print "\n";



Perl 二叉搜索树 用Perl 的一般方式实现了一个完整的二叉搜索树,有如下功能: 1. 插入,删除,搜索 2. 最大,最小值 3. 某节点的前序节点,后序节点 整个过程中更改了好几次: 1. 增加了parent 属性,可以方便的找到父节点,有利于前序后序节点的查找。 2. 最初节点不是都有left right 属性,只有在有子节点的情况下才出现,后来为了统一所有节点都加上这些属性,没有子节点的情 阅读详情

相关推荐

【16】linux命令/工具,systemd,文件操作,动静态库,信号,socket

apt install python3-pip --fix-missing(断开vpn,cp /etc/apt/sources.list /etc/apt/sources.list.bak,python3 -m pip install --upgrade pip,apt-get update,pip install 包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com)设置时间,联网,apt-get install vim。

持续更新ing... 6788

Perl implement Tree data structure (1)

用perl实现了Tree的数据结构,使用Class::Struct来实现,以下为代码: use Data::Dumper; use Class::Struct; struct Node =>{     left  => 'Node',     value => '$',     right => 'Node', }; $root = Node->new; add($r

USTBHacker的专栏 1070

perl 编写的tree显示结构

use perl programming tool to struct tree

数据结构-----二叉树的遍历

数据结构学完有好长时间了。渐渐忘记了很多,在此机会以做笔记的形式将其复习一般,同时熟悉敲点代码熟悉VIM。 一,基本概念 1,二叉树是节点的有限集合,该集合或者为空(而树不允许为空)或者是由一个根和两棵互不相交的、称为该根的左子树和右子树组成。 2,几种特殊的二叉树 满二叉树:高度为h的二叉树敲好有2h -1个结点时称为满二叉树 完全二叉树:一个二叉树中,只有最下面两层结点的度(一个结点

kkxgx的专栏 2526

别光看Demo了!用UE5 Lyra框架快速搭建你的多人对战游戏原型(含完整配置流程)

本文详细介绍了如何利用UE5 Lyra框架快速搭建多人对战游戏原型,包含完整的配置流程和实战案例。Lyra作为可直接二次开发的游戏模板,内置了GAS技能系统、Enhanced Input输入控制等核心功能,大幅缩短开发周期。通过替换角色模型、调整武器数值和配置新地图规则,开发者可在48小时内完成科幻团队竞技游戏原型的搭建。

weixin_28717411的博客 457

Windows 10下用Python 3搞定Android源码下载:最新repo工具避坑指南

本文详细介绍了在Windows 10系统上,使用Python 3和官方最新repo工具下载Android源码的完整流程。文章提供了从Git安装、环境配置到repo工具初始化、同步加速及常见错误排查的避坑指南,帮助开发者高效搭建稳定的源码下载环境。

weixin_29266749的博客 436

Perl中的闭包(closure)

什么是闭包,“This is a notion out of the Lisp world that says if you define an anonymous function in a particular lexical context, it pretends to run in that context even when it's called outside of the con...

云计算? 186

Fortify SCA 24.4 最新可用版

Fortify Static Code Analyzer(Fortify SCA) 是一款由 Micro Focus(原惠普旗下)开发的 静态应用安全测试(SAST)工具,专注于在软件开发早期通过分析源代码或编译后的二进制文件,识别潜在的安全漏洞、代码缺陷和合规性问题。以下是其核心特点与功能:核心功能 静态代码分析 在不运行程序的情况下,通过语法、语义分析检测代码中的安全漏洞(如 SQL 注入、跨站脚本(XSS)、缓冲区溢出等)和代码质量问题。

棉花糖的博客 3181

perl中的闭包使用

直接先上代码,看看示例一的实现: 示例一: sub make_new_counter{ my $start = shift; #返回匿名函数 return sub{ #自由变量 print $start++ ,"\n"; ...

weixin_30362083的博客 172

如何根据芯片手册时序图编写驱动程序

如何根据芯片手册时序图编写驱动程序 对于电子开发者来说,刚刚拿到一个芯片,常用的芯片可以参考网上的例程来做深入了解,对于一个不常用的芯片来说,Datasheet几乎是使用芯片的唯一的资料,所以根据Datasheet时序图写出对应的驱动程序就尤为重要。 本文根据一个简单的例子来阐述根据时序图来编写对应的程序过程。旨在讲解对于初学者应该怎么利用芯片的时序图编写符合要求的底层驱动程序(老鸟请跳过)。 下载芯片的Datasheet,(个人常用http://www.21icsearch.com/)如..

weixin_36447711的博客 1万+

1. 基于STM32的1.28寸圆形IPS屏(GC9A01)驱动移植实战:软件SPI与硬件SPI双方案详解

本文详细介绍了如何在STM32平台上为1.28寸圆形IPS屏(GC9A01驱动芯片)移植驱动程序,涵盖软件SPI与硬件SPI两种实现方案。内容从引脚定义、工程搭建、GPIO配置到SPI外设初始化逐步详解,并提供了完整的测试代码,帮助开发者根据项目需求(灵活性或性能)选择合适的通信方式,快速点亮屏幕并集成到智能手表等嵌入式项目中。

weixin_42300144的博客 203

正则表达式到DFA的编译原理:从理论到工程实践详解

正则表达式是描述文本模式的强大工具,其核心原理基于形式语言与自动机理论。通过将人类可读的正则表达式转换为机器可高效执行的确定有限自动机,可以实现O(n)时间复杂度的模式匹配,这是编译器词法分析、文本搜索等场景的基石。转换过程遵循正则表达式→NFA→DFA的经典链式,其中汤普森构造法用于构建非确定有限自动机作为中间表示,子集构造法则负责将NFA确定化为DFA。在工程实践中,需结合ε-闭包计算、DFA最小化及转移表压缩等优化技术,以应对大规模字符集与复杂规则。理解这一转换链,不仅能深入掌握正则表达式引擎如Lex

weixin_30723433的博客 327

Windows 10/11下彻底卸载Chrome的终极指南(附一键清理注册表脚本)

本文提供了一份在Windows 10/11系统中彻底卸载Google Chrome浏览器的终极指南。针对标准卸载后用户数据与注册表项残留的问题,文章详细介绍了从应用程序层、用户数据层到系统集成层的三层深度清理方法,并重点提供了安全高效的注册表清理脚本,确保浏览器所有痕迹被完全移除,解决重装冲突并释放磁盘空间。

elastic6hunter的博客 782

perl实现二叉树

最开始写的代码,每个结点用一个匿名哈希来表示,可惜运行时错误。。。代码如下 use strict ;use warnings ;sub create_tree { my $n8 = { 'left' =&gt; undef , 'right' =&gt; undef , 'value' =&gt; 8 , } ; my $n6 = ...

weixin_34414196的博客 226

实战MSP-M0G3507与陶晶驰串口屏的通信协议解析

本文详细解析了MSP-M0G3507微控制器与陶晶驰串口屏的通信协议实现。内容涵盖串口配置、协议帧结构、数据校验机制及ASCII协议实战代码,重点介绍了陶晶驰串口屏的指令集应用和调试技巧,为嵌入式开发提供可靠的串口通信解决方案。

h9j8k7l6m5n的博客 867

Unity之ASE如何实现UV扰动闪电效果

UV扰动,顾名思义,就是通过干扰原贴图的UV,使UV发生变化,导致贴图出现会动的效果,如果我们贴图和扰动的速度调整的刚好合适的话,会出现一些非常棒的效果,比如下图所示的闪电效果:好了,一个简单的UV扰动就讲完了,同学们可以发挥想象力,我们是否可以利用UV扰动的原理,做一点别的炫酷的效果出来,比如,交错流动,流光效果等等。很期待你的留言,这篇文章就到这里,希望对你有所帮助。

TxNet 1790

使用Perl的HTML::TreeBuilder::XPath来解析网页内容

原文地址:http://www.php-oa.com/2009/09/24/perl-html-tree-builder-xpath.html转过来 慢慢研究强大的Perl中,有超级多强大的模块,让我们不在需要重复的发明轮子.下面这个就是一个强大的模块.HTML::TreeBuilder::XPath.它能象xml一样解析网站.怎么使用就不细讲了,如下,见实例,我是从alexa.com网站

天山古猿 2453

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Perl implement Tree data structure (2)

之前用struct实现的Tree不够灵活,重新使用hash来实现,更加灵活而且可以更改节点,进而实现平衡二叉树。 以下为程序代码: use Data::Dumper; my $tree = {}; add($tree,$_) for (5,7,1,4,9,6,0,9,100,20,30,21,60); print Dumper $tree; LMR($tree,$tre

USTBHacker的专栏 1553

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Binary tree for perl

#!/usr/bin/perl -w # bintree - binary tree demo program use strict; my ( $root, $n ); # first generate 20 random inserts while ( $n++ < 20 ) { insert ( $roo...

weixin_33939843的博客 151

perl的建树算法

=pod=item  @result=();  $ldap_root="NTA::ou1";  push @result,"NTA::ou1::ou2::ou3";  push @result,"NTA::ou1::ou2::ou4";  push @result,"NTA::ou1::ou5::ou6";  push @result,"NTA::ou1::ou5::ou6::o8";  

RobinKin的专栏 1330

二叉树的遍历及其用途

之前说过了多叉树,实现了前序遍历和后序遍历,但是多叉树是没有中序遍历了 之前因为一直没想到中序遍历的用途,所以忽略掉了,今天继续看数据结构和算法这本书 里面说到了.中序遍历,可以用来做表达式树,在编译器底层实现的时候用户很,可以实现基本的加减乘除 比如 a*b+c,非常有意思 前序遍历用来实现目录结构的显示 后序遍历可以用来实现计算目录内的文件,占用的数据大小~非常有用 学以致用,知道

zlklove1234的专栏 2385

Perl 前缀树实现

前缀树,用来处理大量字符串的查找、排序,也称为字典树,可以代替hash table。 http://en.wikipedia.org/wiki/Trie 以下翻译自Wikipedia: The following are the main advantages of tries over binary search trees (BSTs): Looking up keys

USTBHacker的专栏 2773

perl详解

第一章 概述 一、Perl是什么?       Perl是Practical Extraction and Report Language的缩写,它是由Larry Wall设计的,并由他不断更新和维护,用于在UNIX环境下编程。       .Perl具有高级语言(如C)的强大能力和灵活性。事实上,你将看到,它的许多特性是从C语言中借用来的。       .与脚本语言一样,Perl不需

彦彦专栏 6198
上一篇: Perl 二叉搜索树
下一篇: Perl KMP 算法
Bai_Yuanyong
博客等级 码龄24年 46粉丝 53原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值