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否是空.有的 ...
随机推荐
- mySQL 教程 第2章 安装和介绍mySQL
设置mySQL字符集 支持中文的字符集是utf8,该设置可以更改mySQL配置文件进行全局设置,也可以针对数据库设置,也可以针对表设置,也可以针对列设置.字符集更改后新插入的数据生效,对以前不生效. ...
- angularjs 本地数据存储LocalStorage
1.定义服务 //=========本地存储数据服务============ app.factory('locals', ['$window', function ($window) { return ...
- Centos替换默认源
将默认的国外源替换为国内的网易的源 参考帮助文档:http://mirrors.163.com/.help/centos.html 查看本机版本:cat /etc/redhat-release 先安装 ...
- go的module用法
新版不需要项目放在GOPATH里面了,这个恶心的机制之前还被n多人捧臭脚.简单列一下用法 新建项目 cd 项目目录go mod init 项目名 写好代码 go build 或者 go mod tid ...
- 关于分布式锁Java常用技术方案
前言: 由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题. 所以自己结合实际工作中的一些经验和网上 ...
- 安卓秘钥生成命令以及SHA1值获取办法
切换到秘钥所在目录,例如:cd C:\Program Files\Java\jdk1.8.0_171\bin 执行命令:keytool -genkey -alias demo.keystore -ke ...
- 转转转!SpringMVC访问静态资源的三种方式
如果你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题.如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg ...
- Windows下永久解决数据库乱码 utf8 转 gbk
产生乱码原因 因为windows终端的默认字符集是gbk编码,而mysql数据库是utf8的编码,所以会产生乱码问题 解决乱码问题(临时修改) 询当前数据库默认编码: mysql> show v ...
- java-appium-527 WebDriver协议&针对控件的操作
1.WebDriver协议 https://www.w3.org/TR/webdriver/#list-of-endpoints 1.1查看当前所有的session情况 http://127.0.0. ...
- Air test ios类使用
1.iOS手机的滑动 相关代码 #python class IOS(Device): ... @property #获取屏幕的尺寸 def display_info(self): if not sel ...