二元查找树:
它首先要是一棵二元树,在这基础上它或者是一棵空树;或者是具有下列性质的二元树:
(1)若左子树不空,则左子树上所有结点的值均小于它的父结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于等于它的根结点的值;
(3)左、右子树也分别为二元查找树
节点类:
public class Node
{
public int Data;
public Node Left;
public Node Right;
public void DisplayNode()
{
Console.Write(this.Data + " ");
}
}
BinarySearchTree类:(二元查找树类)
#region 二叉树定义
public Node Root;
public BinarySearchTree()
{
this.Root = null;
}
/// <summary>
/// 插入操作
/// </summary>
/// <param name="i"></param>
public void Insert(int i)
{
//value节点
Node value = new Node();
value.Data = i;
if (Root == null)
{
Root = value;
}
else
{
//Root不为空,则当前操作节点(当前操作指针节点)置为Root
Node Current = Root;
Node Parent;
while (true)
{
//置换父节点
Parent = Current;
//如果插入的数据小于当前操作的节点,就向当前节点的左子树索引,反义右子树
if (i < Current.Data)
{
//置换当前操作指针节点
Current = Current.Left;
if (Current == null)
{
Parent.Left= value;
break;
}
}
else
{
Current = Current.Right;
if (Current == null)
{
Parent.Right = value;
break;
}
}
}
}
}
#endregion
递归遍历:
#region 迭代遍历
//中序遍历 从左到右
public void InOrder(Node theRoot)
{
if (!(theRoot == null))
{
InOrder(theRoot.Left);
theRoot.DisplayNode();
InOrder(theRoot.Right);
}
}
// 先根遍历/先序遍历 从左到右 从上往下
public void PreOrder(Node theRoot)
{
if (!(theRoot == null))
{
theRoot.DisplayNode();
PreOrder(theRoot.Left);
PreOrder(theRoot.Right);
}
}
// 后根遍历 从左到右 从下到上
public void PostOrder(Node theRoot)
{
if (!(theRoot == null))
{
PostOrder(theRoot.Left);
PostOrder(theRoot.Right);
theRoot.DisplayNode();
}
}
#endregion
非递归遍历:
#region 非迭代遍历
//先根遍历
public void StackPreOrder(Node head)
{
Console.WriteLine("Pre-Order: ");
if (head !=null)
{
Stack<Node> stack = new Stack<Node>();
stack.Push(head);
while (stack.Count>0)
{
head = stack.Pop();
Console.WriteLine(head.Data+" ");
//压入栈顶 先进后出 (大的先进)
if (head.Right!=null)
{
stack.Push(head.Right);
}
if (head.Left !=null)
{
stack.Push(head.Left);
}
}
}
}
//中序遍历
public void StackInOrder(Node head)
{
Console.WriteLine("In-Order: ");
if (head != null)
{
Stack<Node> stack = new Stack<Node>();
while (stack.Count > 0 || head != null)
{
//先进后出 (从左往右 从小到大)
if (head != null)
{
stack.Push(head);
head = head.Left;
}
else
{
head = stack.Pop();
Console.WriteLine(head.Data + " ");
head = head.Right;
}
}
}
}
//后序遍历
public void DoubleStackPostOrder(Node head)
{
Console.WriteLine("POST-Order: ");
if (head != null)
{
//双栈实现 非迭代遍历 排序栈 输出栈
Stack<Node> orderStack = new Stack<Node>();
Stack<Node> outputStack = new Stack<Node>();
orderStack.Push(head);
while (orderStack.Count>0)
{
head = orderStack.Pop();
outputStack.Push(head);
if (head.Left !=null)
{
orderStack.Push(head.Left);
}
if(head.Right !=null)
{
orderStack.Push(head.Right);
}
}
while (outputStack.Count > 0)
{
Console.WriteLine(outputStack.Pop().Data + " ");
}
}
}
public void SingleStackPostOrder(Node head)
{
Console.WriteLine("PSOT-Order : ");
if (head != null)
{
Stack<Node> stack = new Stack<Node>();
stack.Push(head);
Node current = null;
while (stack.Count>0)
{
//Peek 和 Pop 前者不改变栈的值,后者会Delete栈顶元素
current = stack.Peek();
if (current.Left != null&& head !=current.Left&&head !=current.Right)
{
stack.Push(current.Left);
}
else if (current.Right != null && head != current.Right)
{
stack.Push(current.Right);
}
else
{
Console.WriteLine(stack.Pop().Data + " ");
head = current;
}
}
}
}
#endregion
算法解析:
1.二叉树构建:
BinarySearchTree.Insert() Function.
BinarySearchTree nums = new BinarySearchTree();
int[] item = new[] {23,45,16,37,3,99,22};
foreach (int i in item)
{
nums.Insert(i);
}
测试代码:实例化Tree对象。遍历数组利用Insert()插入操作。
Insert()Function前提声明:
1.3个申请的数据结点,便于操作数据。
2.判断根节点是否IsNull。
3.确定当前操作节点和父节点。(置换节点)
4.二元查找树的特性判断插入。(左边永远比根小,右边永远比根大。)
5.插入操作完成,置换当前操作节点。
6.Value节点是插入域节点。Current节点当前操作节点,操作前后都需置换。Parent节点同Current。
num.Insert(23);
1.赋值域 Value。
2.判断Root节点,Root.Date=23;
Root=23 Current=23 parent=23
23
num.Insert(45);
1.判断Root节点,Value.Date=45;
2.Current=Root;Parent=Current;
3.插入域大于Root域,置换当前操作节点Current为右子节点Current=Current.Right。判定Current为null->父节点右子节点赋值Value域。
4.跳出循环。
R=23,C=23,P=23
23
45
num.Insert(16);
1.判断Root节点,Value.Date=16;
2.Current=Root;Parent=Current;
3.插入域小于Root域,置换当前操作节点Current为左子节点Current=Current.Left。判定Current为null->父节点左子节点赋值Value域。
4.跳出循环。
R=23,C=23,P=23
23
16 45
num.Insert(37);
1.判断Root节点,Value.Date=37;
2.Current=Root;Parent=Current;
3.插入域大于Root域,置换当前操作节点Current为左子节点Current=Current.Right。判定Current不为null->
R=23 C=45 P=23
4.while再循环。
R=23 C=45 P=45
5.插入域小于Root域,置换当前操作节点Current为左子节点Current=Current.Left。判定Current为null->父节点左子节点赋值Value域。
6.跳出循环。
R=23,C=45,P=45
23
16 45
37
num.Insert(3);
1.判断Root节点,Value.Date=3;
2.Current=Root;Parent=Current;
3.插入域小于Root域,置换当前操作节点Current为左子节点Current=Current.Left。判定Current不为null->
R=23 C=16 P=23
4.while再循环。
R=23 C=16 P=16
5.插入域小于Root域,置换当前操作节点Current为左子节点Current=Current.Left。判定Current为null->父节点左子节点赋值Value域。
6.跳出循环。
R=23,C=16,P=16
23
16 45
3 37
num.Insert(99);
1.判断Root节点,Value.Date=99;
2.Current=Root;Parent=Current;
3.插入域大于Root域,置换当前操作节点Current为右子节点Current=Current.Right。判定Current不为null->
R=23 C=45 P=23
4.while再循环。
R=23 C=45 P=45
5.插入域大于Root域,置换当前操作节点Current为右子节点Current=Current.Right。判定Current为null->父节点右子节点赋值Value域。
6.跳出循环。
R=23,C=45,P=45
23
16 45
3 37 99
num.Insert(22);
1.判断Root节点,Value.Date=99;
2.Current=Root;Parent=Current;
3.插入域小于Root域,置换当前操作节点Current为右子节点Current=Current.Right。判定Current不为null->
R=23 C=16 P=23
4.while再循环。
R=23 C=16 P=16
5.插入域大于Root域,置换当前操作节点Current为右子节点Current=Current.Right。判定Current为null->父节点右子节点赋值Value域。
6.跳出循环。
R=23,C=16,P=16
23
16 45
3 22 37 99
递归遍历:
//先根遍历/先序遍历 根 左 右 中序遍历 左 根 右 后序遍历 左 右 根
中序遍历:
非递归遍历: