c#数和二叉树
树(Tree)是 n(n≥0)个相同类型的数据元素的有限集合。树中的数据元素叫结点(Node)。n=0 的树称为空树(Empty Tree);对于 n>0 的任意非空树 T 有: (1)有且仅有一个特殊的结点称为树的根(Root)结点,根没有前驱结点; (2)若n>1,则除根结点外,其余结点被分成了m(m>0)个互不相交的集合T1,T2,…,Tm,其中每一个集合Ti(1≤i≤m)本身又是一棵树。树T1,T2,…,Tm称为这棵树的子树(Subtree)
二叉树(Binary Tree)是 n(n≥0)个相同类型的结点的有限集合。n=0 的二叉树称为空二叉树(Empty Binary Tree);对于 n>0 的任意非空二叉树有:
(1)有且仅有一个特殊的结点称为二叉树的根(Root)结点,根没有前驱结点;
(2)若n>1,则除根结点外,其余结点被分成了 2 个互不相交的集合TL,TR,而TL、TR本身又是一棵二叉树,分别称为这棵二叉树的左子树(Left Subtree)和右子树(Right Subtree)。
1)满二叉树(Full Binary Tree):如果一棵二叉树只有度为 0 的结点和度为 2的结点,并且度为 0 的结点在同一层上,则这棵二叉树为满二叉树
(2)完全二叉树(Complete Binary Tree):深度为 k,有 n 个结点的二叉树当且仅当其每一个结点都与深度为 k,有 n 个结点的满二叉树中编号从1到n的结点一一对应时,称为完全二叉树
二叉树的存储结构主要有三种:顺序存储结构、二叉链表存储结构和三叉链表存储结构
二叉链表存储结构的类实现
二叉树的二叉链表的结点类有3个成员字段:数据域字段data、左孩子引用域字段lChild和右孩子引用域字段rChild。
public class Node<T>
{
private T data;//数据域 public T Data
{
get { return data; }
set { data = value; }
}
private Node<T> lchild;//左孩子 public Node<T> Lchild
{
get { return lchild; }
set { lchild = value; }
}
private Node<T> rchild;//右孩子 public Node<T> Rchild
{
get { return rchild; }
set { rchild = value; }
}
public Node()
{
data = default(T);
lchild = null;
rchild = null;
}
public Node(T data )
{
this.data = data;
lchild = null;
rchild = null;
} public Node(T data, Node<T> lchild, Node<T> rchlid)
{
this.data = data;
this.lchild = lchild;
this.rchild = rchild;
}
}
不带头结点的二叉树的二叉链表比带头结点的二叉树的二叉链表的区别与不带头结点的单链表与带头结点的单链表的区别一样。
下面只介绍不带头结点的二叉树的二叉链表的类
public class BinaryTree<T>
{
private Node<T> head; //头引用 internal Node<T> Head
{
get { return head; }
set { head = value; }
} public BinaryTree()
{
head = null;
}
public BinaryTree(T data)
{
Node<T> p = new Node<T>(data);
head = p;
}
public BinaryTree(T data, Node<T> lchild, Node<T> rchild)
{
Node<T> p = new Node<T>(data, lchild, rchild);
head = p;
}
// 二叉树是否为空
public bool IsEmptyTree()
{
if (null != head)
{
return false;
}
else
{
return true;
}
} // 获取根节点
public Node<T> GetRoot()
{
if (IsEmptyTree())
{
return null;
}
return head;
}
//获取结点的左孩子结点
public Node<T> GetLChild(Node<T> p)
{
return p.Lchild;
}
// right child
public Node<T> GetRChild(Node<T> p)
{
return p.Rchild;
}
//将结点p的左子树插入值为val的新结点,
//原来的左子树成为新结点的左子树
public void InsertL(T val, Node<T> p)
{
Node<T> temp = new Node<T>(val);
temp.Lchild = p.Lchild;
p.Lchild = temp;
} //将结点p的右子树插入值为val的新结点,
//原来的右子树成为新结点的右子树
public void InsertR(T val, Node<T> p)
{
Node<T> tmp = new Node<T>(val);
tmp.Rchild = p.Rchild;
p.Rchild = tmp;
}
//若p非空,删除p的左子树
public Node<T> DeleteL(Node<T> p)
{
if (p == null || p.Lchild == null)
{
return null;
}
Node<T> temp = p.Lchild;
p.Lchild = null;
return temp;
} //若p非空,删除p的右子树
public Node<T> DeleteR(Node<T> p)
{
if (p == null || p.Rchild == null)
{
return null;
}
Node<T> temp = p.Rchild;
p.Rchild = null;
return temp;
}
//判断是否是叶子结点
public bool IsLeaf(Node<T> p)
{
if ( p != null && p.Lchild == null && p.Rchild == null)
{
return true;
}
return false;
}
// 销毁二叉树
public void DestroyTree( Node<T> node )
{
if ( node != null )
{
if (node.Lchild != null)
{
node.Lchild = null;
}
if (node.Rchild != null)
{
node.Rchild = null;
}
node = null;
}
} // 1、先序遍历(DLR)
public void PreOredr(Node<T> root)
{
if ( root == null )
{
//Console.WriteLine("树为空,无法遍历");
return;
}
//处理根结点
Console.WriteLine("{0}", root.Data);
//先序遍历左子树
PreOredr(root.Lchild);
//再遍历右子树
PreOredr(root.Rchild);
} /*
2、中序遍历(LDR)
中序遍历的基本思想是:首先中序遍历根结点的左子树,然后访问根结点,
最后中序遍历其右子树
*/
public void InOrder(Node<T> root)
{
if (root.Lchild != null)
{
InOrder(root.Lchild);
} Console.WriteLine( root.Data ); if (root.Rchild != null)
{
InOrder(root.Rchild);
}
}
/*
3、后序遍历(LRD)
后序遍历的基本思想是:首先后序遍历根结点的左子树,然后后序遍历根结
点的右子树,最后访问根结点
*/
public void PostOrder(Node<T> root)
{
if (root.Lchild != null)
{
PostOrder(root.Lchild);
}
if (root.Rchild != null)
{
PostOrder(root.Rchild);
}
Console.WriteLine(root.Data);
} /*
层序遍历的基本思想是:由于层序遍历结点的顺序是先遇到的结点先访问,
与队列操作的顺序相同。所以,在进行层序遍历时,设置一个队列,将根结点引
用入队,当队列非空时,循环执行以下三步:
(1) 从队列中取出一个结点引用,并访问该结点;
(2) 若该结点的左子树非空,将该结点的左子树引用入队;
(3) 若该结点的右子树非空,将该结点的右子树引用入队
*/
public void LevelOrder(Node<T> root)
{
if ( root == null )
{
return;
}
Queue<Node<T>> queue = new Queue<Node<T>>();
queue.Enqueue(root);
while ( queue.Count > )
{
//结点出队
Node<T> temp = queue.Dequeue();
//处理当前结点
Console.WriteLine("结点出队{0}", temp.Data);
//将当前结点的左孩子结点入队
if (temp.Lchild != null)
{
queue.Enqueue(temp.Lchild);
}
if (temp.Rchild != null)
{
queue.Enqueue(temp.Rchild);
}
}
}
}
// 测试
BinaryTree<char> tree = new BinaryTree<char>();
Node<char> p = new Node<char>('A');
Node<char> p1 = new Node<char>('B');
tree.InsertL('B', p);
tree.InsertL('D', p);
tree.InsertR('E', p1);
tree.InsertR('C', p);
tree.InsertR('F', p);
tree.InsertR('G', p);
Console.WriteLine("先序遍历*******************************");
tree.PreOredr(p); //tree.PreOredr(p1);
Console.WriteLine("中序遍历*******************************");
tree.InOrder(p);
Console.WriteLine("后序遍历*******************************");
tree.PostOrder(p);
Console.WriteLine("层序遍历*******************************");
tree.LevelOrder(p);
c#数和二叉树的更多相关文章
- [ACM训练] 数据结构----树、二叉树----c++ && python
树结构,尤其是二叉树结构是算法中常遇见的,这里根据学习过程做一个总结. 二叉树所涉及到的知识点有:满二叉树与完全二叉树.节点数目的关系.节点数与二叉树高度的关系.层次遍历.深度优先遍历.广度优先遍历等 ...
- 数据结构——二叉树(Binary Trees)
非线性数据结构 二叉搜索树(Binary Search Tree) 树的密度=结点数/高度 二叉树类 #pragma once class stnode { public: int nodeValue ...
- Android版数据结构与算法(六):树与二叉树
版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 之前的篇章主要讲解了数据结构中的线性结构,所谓线性结构就是数据与数据之间是一对一的关系,接下来我们就要进入非线性结构的世界了,主要是树与图,好了接 ...
- 卡特兰(Catalan)数入门详解
也许更好的阅读体验 基本概念 介绍 学卡特兰数我觉得可能比组合数要难一点,因为组合数可以很明确的告诉你那个公式是在干什么,而卡特兰数却像是在用大量例子来解释什么时卡特兰数 这里,我对卡特兰数做一点自己 ...
- Leetcode823 : 因子二叉树问题
问题描述 给定一个数组,数组中的数不重复,且均大于1.要求使用数组中的数构建二叉树,每个数字可以被重复使用,除了叶子节点,每个节点的值等于其子节点的乘积,求构建二叉树的数量,返回的结果mod 10** ...
- 数据结构(一)二叉树 & avl树 & 红黑树 & B-树 & B+树 & B*树 & R树
参考文档: avl树:http://lib.csdn.net/article/datastructure/9204 avl树:http://blog.csdn.net/javazejian/artic ...
- 二叉树&满二叉树与完全二叉树
二叉树的定义 二叉树(Binary Tree)是n(n≥0)个元素的有限集合,该集合为空或者为由一个称为"根"的元素及两个不相交的.被分别称为左子树和右子树的二叉树组成 二叉树的基 ...
- Java数据结构——树、二叉树的理论知识汇总
通用树的理论知识 一.树的定义 由一个或多个(n>=0)节点组成的有限集合T,有且仅有一个节点称为根(root),当n>1时,其7余的节点为m(m>=0)个互不相交的有限集合T1,T ...
- leetcode_二叉树篇_python
主要是深度遍历和层序遍历的递归和迭代写法. 另外注意:因为求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中). 所有题目首先考虑root否是空.有的 ...
随机推荐
- JS 检测浏览器中是否安装了特定的插件
1.检测非IE浏览器 可以使用plugins数组来达到这个目的,例: //检测插件(在IE中无效) function hasPlugin(name){ name = name.toLowerCase( ...
- Vue 介绍
1. 条件 效果图. 如果seen为false,文字将消失 2. 循环 script里定义数据 效果 3. 事件处理 效果如下图, hello world被逆转了
- 使用overflow:hidden之后使的同行元素不对齐
一个父元素(块级元素)中有几个在同一水平线上的几个元素(行内块元素),设置其中某个元素的oveflow:hidden之后,会导致这几个行内元素不再是同一水平线上对齐 原因是: 1)行内元素的默认ver ...
- 大数据学习资料之SQL与NOSQL数据库
这几年的大数据热潮带动了一激活了一大批hadoop学习爱好者.有自学hadoop的,有报名培训班学习的.所有接触过hadoop的人都知道,单独搭建hadoop里每个组建都需要运行环境.修改配置文件测试 ...
- JS时间(日期)比较或相减(暂时停用)
注:此文均来自网上,可行,只供参考 //JAVASCRIPT中 日期相减很麻烦 ,现在有现成的实现方法,拷贝过去就可以用了,方便 //调用该方法(主方法) function dateDiff(date ...
- 关于新建android项目时 appcompat_v7报错问题的一点总结
说下我的解决方案: 1.确保 appcompat项目的 target版本 低于 实际项目的android版本(就像.net中 低版本的 framewrok项目不能引用高版本framework项目一样) ...
- Python获取当前年月日
import datetime datetime.datetime.now().year datetime.datetime.now().month datetime.datetime.now().d ...
- 发布程序时出现“类型ASP.global_asax同时存在于...”错误的解决办法
web程序发布后,通过浏览器访问程序显示如下的错误信息: 编译器错误消息: CS0433: 类型“ASP.global_asax”同时存在于“c:\WINDOWS\Microsoft.NET\Fram ...
- [UE4]添加蒙太奇动画
选择蒙太奇所使用的骨骼
- mongodb 如何区分大小写
mongodb是区分大小写的,在做mongodb数据库操作是经常使用toUpperCase()等方法将value转换为大写存到数据库中 e.g. 在做数据库模糊查询时语句如下 db.COLLECTIO ...