1.基本概念:
二叉树是每个结点最多有两个子结点的树,二叉树不是树的特殊形式,他们的数据结构是不一样的。
二叉树有以下性质:
1)第i-1层最多有2的i-1次方个结点
2)深度为k的二叉树最多有2的k次方-1个结点,可以由第一个性质推出
3)若0度的结点为n0个,2度的结点为n2个,则有n0=n2+1
2.二叉树的链式存储结构,二叉链表
public class node<T>
{
public T value{get;set;}//结点信息
public Node leftChild{get;set;}//左孩子
public Node rightChild{get;set;}//右孩子
}
3. 二叉树的遍历
前/先序遍历NLR:先访问结点的信息,然后遍历结点的左子树再遍历结点的右子树
中序遍历LNR:先遍历结点的左子树,然后访问结点的信息再遍历结点的右子树
后续遍历LRN:先遍历结点的左子树,然后遍历结点的右子树再访问结点的信息
4.遍历算法的实现
public class BinaryTree<T>
{
/// <summary>
/// 前序遍历NLR N为结点信息,L为左子树R为右子树
/// </summary>
/// <param name="node"></param>
public void PreOrderTraserval(Node<T> node)
{
if (node == null)
return;
Console.WriteLine(node.value);
PreOrderTraserval(node.leftChild);
PreOrderTraserval(node.rightChild);
}
/// <summary>
/// 中序遍历
/// </summary>
/// <param name="node"></param>
public void InOrderTraserval(Node<T> node)
{
if (node == null)
return;
InOrderTraserval(node.leftChild);
Console.WriteLine(node.value);
InOrderTraserval(node.rightChild);
}
/// <summary>
/// 后序遍历
/// </summary>
/// <param name="node"></param>
public void PostOrderTraserval(Node<T> node)
{
if (node == null)
return;
PostOrderTraserval(node.leftChild);
PostOrderTraserval(node.rightChild);
Console.WriteLine(node.value);
}
}
public class Node<T>
{
public T value { get; set; }
public Node<T> leftChild { get; set; }
public Node<T> rightChild { get; set; }
}
5.非递归实现
//前序遍历,非递归算法,需要恢复现场,所以需要用的栈,栈是一个后进先出的队列,先访问根结点后将根结点压入栈,将左结点压入栈直到为空,这时出栈(恢复现场),将结点的右子节点看做为跟压入栈中
public void PreOrder(Node node)
{
Stack<Node> s = new Stack<Node>();
while(node!=null || s.Count>0)//结点尚可能有子结点或者栈未空
{
if(node!=null)
{
Console.Write(node.value);
s.Push(node);
node = node.leftChild;
}
else
{
node = s.Pop();
node = node.rightChild;
}
}
}
//中序遍历和先序遍历代码上稍微改造即可,其的做法是先压入栈出栈时访问
public void InOrder(Node node)
{
Stack<Node> s = new Stack<Node>();
while(node!=null || s.Count>0)//结点尚可能有子结点或者栈未空
{
if(node!=null)
{
s.Push(node);
node = node.leftChild;
}
else
{
node = s.Pop();
Console.Write(node.value);
node = node.rightChild;
}
}
}
//后序遍历是三种遍历中最复杂的一个,基本流程差不多,出栈时访问,但是何时出栈是很有讲究的
public void PostOrder(Node node)
{
Stack<Node> s = new Stack<Node>();
Node pre = null;
while(node!=null || s.Count>0)//结点尚可能有子结点或者栈未空
{
if(node!=null)
{
s.Push(node);
node = node.leftChild;
}
else
{
node = s.Peek();//拿到栈伟结点但不出栈
if( node.rightChild == null || pre==node.rightChild)//当右结点为空,或者右结点已经访问过了
{
s.Pop();//出栈
Console.Write(node.value);
pre = node;
node = null;
}
else
{
node = node.rightChild;
}
}
}
}