1. 引言

在实际的项目中,树还是用的比较多的一种,尤其是对于具有层次结构的数据。相信很多人都学过树的遍历,比如先序遍历,后序遍历等,利用递归还是很容易理解的。

今天给大家介绍下二叉树的几种遍历算法,包括递归和非递归的实现。

首先建立一棵二叉树 如:

        [DebuggerDisplay("Value={Value}")]
public class Tree
{
public string Value;
public Tree Left;
public Tree Right;
} public static Tree CreatFakeTree()
{
Tree tree = new Tree() {Value = "A"};
tree.Left = new Tree()
{
Value = "B",
Left = new Tree() {Value = "D", Left = new Tree() {Value = "G"}},
Right = new Tree() {Value = "E", Right = new Tree() {Value = "H"}}
};
tree.Right = new Tree() {Value = "C", Right = new Tree() {Value = "F"}}; return tree;
}

一棵简单的二叉树

2. 先序遍历

先序遍历还是很好理解的,一次遍历根节点,左子树,右子数

递归实现

        public static void PreOrder(Tree tree)
{
if (tree == null)
return; System.Console.WriteLine(tree.Value);
PreOrder(tree.Left);
PreOrder(tree.Right);
}

非递归实现

        public static void PreOrderNoRecursion(Tree tree)
{
if(tree == null)
return; System.Collections.Generic.Stack<Tree> stack = new System.Collections.Generic.Stack<Tree>();
Tree node = tree; while (node != null || stack.Any())
{
if (node != null)
{
stack.Push(node);
System.Console.WriteLine(node.Value);
node = node.Left;
}
else
{
var item = stack.Pop();
node = item.Right;
}
}
}

输出结果:

3. 中序遍历

递归实现

        public static void InOrder(Tree tree)
{
if(tree == null)
return; InOrder(tree.Left);
System.Console.WriteLine(tree.Value);
InOrder(tree.Right);
}

非递归实现

        public static void InOrderNoRecursion(Tree tree)
{
if (tree == null)
return; System.Collections.Generic.Stack<Tree> stack = new System.Collections.Generic.Stack<Tree>();
Tree node = tree; while (node != null || stack.Any())
{
if (node != null)
{
stack.Push(node);
node = node.Left;
}
else
{
var item = stack.Pop();
System.Console.WriteLine(item.Value); node = item.Right;
}
}
}

输出结果:

4. 后序遍历

递归实现

        public static void PostOrder(Tree tree)
{
if (tree == null)
return; PostOrder(tree.Left);
PostOrder(tree.Right);
System.Console.WriteLine(tree.Value);
}

非递归实现 比前两种稍微复杂一点。要保证左右节点都被访问后,才能访问根节点。这里给出两种形式。

        public static void PostOrderNoRecursion(Tree tree)
{
if (tree == null)
return; System.Collections.Generic.Stack<Tree> stack = new System.Collections.Generic.Stack<Tree>();
Tree node = tree;
Tree pre = null;
stack.Push(node); while (stack.Any())
{
node = stack.Peek();
if ((node.Left == null && node.Right == null) ||
(pre != null && (pre == node.Left || pre == node.Right)))
{
System.Console.WriteLine(node.Value);
pre = node; stack.Pop();
}
else
{
if(node.Right != null)
stack.Push(node.Right); if(node.Left != null)
stack.Push(node.Left);
}
}
} public static void PostOrderNoRecursion2(Tree tree)
{
HashSet<Tree> visited = new HashSet<Tree>();
System.Collections.Generic.Stack<Tree> stack = new System.Collections.Generic.Stack<Tree>();
Tree node = tree; while (node != null || stack.Any())
{
if (node != null)
{
stack.Push(node);
node = node.Left;
}
else
{
var item = stack.Peek();
if (item.Right != null && !visited.Contains(item.Right))
{
node = item.Right;
}
else
{
System.Console.WriteLine(item.Value);
visited.Add(item);
stack.Pop();
}
}
}
}

输出结果:

5. 层序遍历

层序遍历就是按照层次由左向右输出

        public static void LevelOrder(Tree tree)
{
if(tree == null)
return; Queue<Tree> queue = new Queue<Tree>();
queue.Enqueue(tree); while (queue.Any())
{
var item = queue.Dequeue();
System.Console.Write(item.Value); if (item.Left != null)
{
queue.Enqueue(item.Left);
} if (item.Right != null)
{
queue.Enqueue(item.Right);
}
}
}

输出结果:

6. Z-型层序遍历

Z-层序遍历就是奇数层按照由左向右输出,偶数层按照由右向左输出,这里定义了几个辅助函数,比如计算节点所在的层次。算法思想是按照层次保存树形节点,应该是有更加优化的算法,希望大家指出。

        public static int GetDepth(Tree tree, Tree node)
{
if (tree == null)
return ; if (tree == node)
return ; if (tree.Left == node || tree.Right == node)
return ; int lDepth = GetDepth(tree.Left, node);
lDepth = lDepth == ? : lDepth + ; int rDepth = GetDepth(tree.Right, node);
rDepth = rDepth == ? : rDepth + ; return lDepth >= rDepth ? lDepth : rDepth;
} public static void Z_LevelOrder(Tree tree, Dictionary<int, List<Tree>> dictionary)
{
if (tree == null)
return; Queue<Tree> queue = new Queue<Tree>();
queue.Enqueue(tree); while (queue.Any())
{
var item = queue.Dequeue();
var depth = GetDepth(tree, item); List<Tree> list;
if (!dictionary.TryGetValue(depth, out list))
{
list = new List<Tree>();
dictionary.Add(depth, list);
}
list.Add(item); if (item.Left != null)
{
queue.Enqueue(item.Left);
} if (item.Right != null)
{
queue.Enqueue(item.Right);
}
}
} public static void Z_LevelOrder(Tree tree)
{
if (tree == null)
return; Dictionary<int, List<Tree>> dictionary = new Dictionary<int, List<Tree>>();
Z_LevelOrder(tree, dictionary); foreach (KeyValuePair<int, List<Tree>> pair in dictionary)
{
if (pair.Key% == )
{
pair.Value.Reverse();
} pair.Value.ForEach(t=> { System.Console.Write(t.Value); });
}
}

输出结果:

C#实现二叉树的各种遍历的更多相关文章

  1. 二叉树的层序遍历 BFS

    二叉树的层序遍历,或者说是宽度优先便利,是经常考察的内容. 问题一:层序遍历二叉树并输出,直接输出结果即可,输出格式为一行. #include <iostream> #include &l ...

  2. codevs3143 二叉树的序遍历

    难度等级:白银 3143 二叉树的序遍历 题目描述 Description 求一棵二叉树的前序遍历,中序遍历和后序遍历 输入描述 Input Description 第一行一个整数n,表示这棵树的节点 ...

  3. codevs 3143 二叉树的序遍历

    传送门 Description 求一棵二叉树的前序遍历,中序遍历和后序遍历 Input 第一行一个整数n,表示这棵树的节点个数. 接下来n行每行2个整数L和R.第i行的两个整数Li和Ri代表编号为i的 ...

  4. lintcode : 二叉树的层次遍历II

    题目 二叉树的层次遍历 II 给出一棵二叉树,返回其节点值从底向上的层次序遍历(按从叶节点所在层到根节点所在的层遍历,然后逐层从左往右遍历) 样例 给出一棵二叉树 {3,9,20,#,#,15,7}, ...

  5. lintcode : 二叉树的层次遍历

    题目 二叉树的层次遍历 给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问) 样例 给一棵二叉树 {3,9,20,#,#,15,7} : 3 / \ 9 20 / \ 15 7 返回他的分层遍历 ...

  6. lintcode :Binary Tree Preorder Traversal 二叉树的前序遍历

    题目: 二叉树的前序遍历 给出一棵二叉树,返回其节点值的前序遍历. 样例 给出一棵二叉树 {1,#,2,3}, 1 \ 2 / 3 返回 [1,2,3]. 挑战 你能使用非递归实现么? 解题: 通过递 ...

  7. Leetcode 102. Binary Tree Level Order Traversal(二叉树的层序遍历)

    Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...

  8. 二叉树中序遍历 (C语言实现)

    在计算机科学中,树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构.二叉树是每个节点最多有两个子树的有序树.通常子树被称作“左子树”(left subtre ...

  9. 94 Binary Tree Inorder Traversal(二叉树中序遍历Medium)

    题目意思:二叉树中序遍历,结果存在vector<int>中 解题思路:迭代 迭代实现: /** * Definition for a binary tree node. * struct ...

  10. 144 Binary Tree Preorder Traversal(二叉树先序遍历Medium)

    题目意思:二叉树先序遍历,结果存在vector<int>中 解题思路:1.递归(题目中说用递归做没什么意义,我也就贴贴代码吧) 2.迭代 迭代实现: class Solution { pu ...

随机推荐

  1. synchronized同步对象锁

    package com.system.util; import com.common.Constants; import com.util.Cache; /** * 创建同步对象锁 * * @auth ...

  2. jmx server 和jmx client

    启动jmx server 和jmx client,通过jconsole进入jmx server 然后通过其中远程进程,进入jmx client: 发现,两者可用的tab页不同, MBean的数量类型也 ...

  3. jmx完整示例

    很早就开始去了解这个了,不过一直都是皮毛,基本概念明白,具体api几乎一无不知... 认真看了几篇文章,做了测试,终于有所了解 参考 入门级别: http://www.cnblogs.com/agou ...

  4. Java基础之I/O和file

    五.IO流1.IO流概述 (1)用来处理设备(硬盘,控制台,内存)间的数据. (2)java中对数据的操作都是通过流的方式. (3)java用于操作流的类都在io包中. (4)按照流操作的数据的类型不 ...

  5. EF架构~CodeFirst模型下的数据初始化

    回到目录 我为什么会来 在传统的大型系统设计中,数据库建模是个比开发更早的环节,先有数据库,然后是ORM模型,最后才是开发程序,而这种模型在EF出现后发生了转变,而且有可能将来会被code first ...

  6. 第2讲 Redis常用命令与高级应用

    目录 一.redis数据类型 5. sorted sets类型和操作 二.Redis常用命令 1.键值相关命令 2.服务器相关命令 三. redis高级应用 1. 给redis服务器设置密码 2.持久 ...

  7. [Java面试五]Spring总结以及在面试中的一些问题.

    1.谈谈你对spring IOC和DI的理解,它们有什么区别? IoC Inverse of Control 反转控制的概念,就是将原本在程序中手动创建UserService对象的控制权,交由Spri ...

  8. fir.im Weekly - 2016 年 Android 最佳实践列表

    2016 年已经过去一半,你在年初制定的成长计划都实现了吗? 学海无涯,技术成长不是一簇而就的事情.本期 fir.im Weekly 推荐 王下邀月熊_Chevalier的 我的编程之路--知识管理与 ...

  9. React 入门实例教程

    现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩目程度可见一斑. React 起源于 Face ...

  10. android 键盘遮挡 父布局上滚解决

    private void controlKeyboardLayout(final View root, final View scrollToView) { root.getViewTreeObser ...