优雅地非递归遍历二叉树

 前中后序遍历二叉树

public class BinaryTreeNode<T>
    {
        public T Value { get;set; }
        public BinaryTreeNode<T> Parent { get;set; }
        public BinaryTreeNode<T> Left { get;set; }
        public BinaryTreeNode<T> Right { get;set; }
        
        public virtual void Traverse(TraverseOrder order, NodeWorker<T> worker)
        {
            if (worker == null) { return; }

            var left = this.Left;
            var right = this.Right;
            switch (order)
            {
            case TraverseOrder.Preorder:
                /* recursive preorder traverse
                worker.DoActionOnNode(this);
                if (left != null) { Left.Traverse(order, worker); }
                if (right != null) { Right.Traverse(order, worker); }
                */
                PreorderTraverse(worker);
                break;
            case TraverseOrder.Inorder:
                /* recursive inorder traverse
                if (left != null) { Left.Traverse(order, worker); }
                worker.DoActionOnNode(this);
                if (right != null) { Right.Traverse(order, worker); }
                */
                InorderTraverse(worker);
                break;
            case TraverseOrder.Postorder:
                /* recursive postorder traverse
                if (left != null) { Left.Traverse(order, worker); }
                if (right != null) { Right.Traverse(order, worker); }
                worker.DoActionOnNode(this);
                */
                PostorderTraverse(worker);
                break;
            default:
                break;
            }
        }
        
        void PreorderTraverse(NodeWorker<T> worker)
        {
            var stack = new Stack<BinaryTreeNode<T>>();
            stack.Push(this); 
            
            while (stack.Count > 0)
            {
                var node = stack.Pop(); 
                //if (node == null) { continue; }
                //else
                {
                    var right = node.Right;
                    var left = node.Left;
                    worker.DoActionOnNode(node);
                    if (right != null) { stack.Push(right); }
                    if (left != null) { stack.Push(left); }
                }
            }
        }        
        /* This works fine and is better for tuition. The code above is an optimized version.
        void PreorderTraverse(NodeWorker<T> worker)
        {
            var stack = new Stack<BinaryTreeNode<T>>(); var stackReady4Visit = new Stack<bool>();
            
            stack.Push(this); stackReady4Visit.Push(false);
            
            while (stack.Count > 0)
            {
                var node = stack.Pop(); var ready4Visit = stackReady4Visit.Pop();
                //if (node == null) { continue; }
                if (ready4Visit)
                {
                    worker.DoActionOnNode(node);
                }
                else
                {
                    var right = node.Right;
                    var left = node.Left;
                    if (right != null) { stack.Push(right); stackReady4Visit.Push(false); }
                    if (left != null) { stack.Push(left); stackReady4Visit.Push(false); }
                    stack.Push(node); stackReady4Visit.Push(true);
                }
            }
        }
        */
        
        void InorderTraverse(NodeWorker<T> worker)
        {
            var stack = new Stack<BinaryTreeNode<T>>(); var stackReady4Visit = new Stack<bool>();
            
            stack.Push(this); stackReady4Visit.Push(false);
            
            while (stack.Count > 0)
            {
                var node = stack.Pop(); var ready4Visit = stackReady4Visit.Pop();
                //if (node == null) { continue; }
                if (ready4Visit)
                {
                    worker.DoActionOnNode(node);
                }
                else
                {
                    var right = node.Right;
                    var left = node.Left;
                    if (right != null) { stack.Push(right); stackReady4Visit.Push(false); }
                    stack.Push(node); stackReady4Visit.Push(true);
                    if (left != null) { stack.Push(left); stackReady4Visit.Push(false); }
                }
            }
        }
        
        void PostorderTraverse(NodeWorker<T> worker)
        {
            var stack = new Stack<BinaryTreeNode<T>>(); var stackReady4Visit = new Stack<bool>();
            
            stack.Push(this); stackReady4Visit.Push(false);
            
            while (stack.Count > 0)
            {
                var node = stack.Pop(); var ready4Visit = stackReady4Visit.Pop();
                //if (node == null) { continue; }
                if (ready4Visit)
                {
                    worker.DoActionOnNode(node);
                }
                else
                {
                    var right = node.Right;
                    var left = node.Left;
                    stack.Push(node); stackReady4Visit.Push(true);
                    if (right != null) { stack.Push(right); stackReady4Visit.Push(false); }
                    if (left != null) { stack.Push(left); stackReady4Visit.Push(false); }
                }
            }
        }
    }
    public abstract class NodeWorker<T>
    {
        public abstract void DoActionOnNode(BinaryTreeNode<T> node);
    }

前中后序遍历二叉树

以上三种遍历实现代码行数一模一样,如同递归遍历一样,只有三行核心代码的先后顺序有区别。用原作者的话解释就是:"得以统一三种更简单的非递归遍历方法的基本思想:有重合元素的局部有序一定能导致整体有序。基于这种思想,我就构思三种非递归遍历的统一思想:不管是前序,中序,后序,只要我能保证对每个结点而言,该结点,其左子结点,其右子结点都满足以前序/中序/后序的访问顺序,整个二叉树的这种三结点局部有序一定能保证整体以前序/中序/后序访问,因为相邻的局部必有重合的结点,即一个局部的"根"结点是另外一个局部的"子"结点。"。

 

public class BinaryTree<T>
    {
        BinaryTreeNode<T> Node { get;set; }
        public BinaryTree(BinaryTreeNode<T> node)
        {
            this.Node = node;
        }
        
        public void Traverse(TraverseOrder order, NodeWorker<T> worker)
        {
            if (worker == null) { return; }
            var node = this.Node;
            if (node == null) { return; }
            
            switch (order)
            {
            case TraverseOrder.Preorder:
                node.Traverse(order, worker);
                break;
            case TraverseOrder.Inorder:
                node.Traverse(order, worker);
                break;
            case TraverseOrder.Postorder:
                node.Traverse(order, worker);
                break;
            case TraverseOrder.Layer:
                TraverseLayer(worker);
                break;
            default:
                break;
            }
        }
        
        private void TraverseLayer(NodeWorker<T> worker)
        {
            var queue = new Queue<BinaryTreeNode<T>>();
            queue.Enqueue(this.Node);
            while (queue.Count > 0)
            {
                var element = queue.Dequeue();
                if (element != null)
                {
                    worker.DoActionOnNode(element);
                    var left = element.Left;
                    var right = element.Right;
                    if (left != null) { queue.Enqueue(left); }
                    if (right != null) { queue.Enqueue(right); }
                }
            }
        }
    }

层次遍历

 

考虑柔性负荷的综合能源系统低碳经济优化调度【考虑碳交易机制】(Matlab代码实现)内容概要:本文围绕“考虑柔性负荷的综合能源系统低碳经济优化调度”展开,重点研究在碳交易机制下如何实现综合能源系统的低碳化与经济性协同优化。通过构建包含风电、光伏、储能、柔性负荷等多种能源形式的系统模型,结合碳交易成本与能源调度成本,提出优化调度策略,以降低碳排放并提升系统运行经济性。文中采用Matlab进行仿真代码实现,验证了所提模型在平衡能源供需、平抑可再生能源波动、引导柔性负荷参与调度等方面的有效性,为低碳能源系统的设计与运行提供了技术支撑。; 适合人群:具备一定电力系统、能源系统背景,熟悉Matlab编程,从事能源优化、低碳调度、综合能源系统等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究碳交易机制对综合能源系统调度决策的影响;②实现柔性负荷在削峰填谷、促进可再生能源消纳中的作用;③掌握基于Matlab的能源系统建模与优化求解方法;④为实际综合能源项目提供低碳经济调度方案参考。; 阅读建议:建议读者结合Matlab代码深入理解模型构建与求解过程,重点关注目标函数设计、约束条件设置及碳交易成本的量化方式,可进一步扩展至多能互补、需求响应等场景进行二次开发与仿真验证。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值