C# 数组集合<四> 二元查找树

二元查找树:

 它首先要是一棵二元树,在这基础上它或者是一棵空树;或者是具有下列性质的二元树: 

(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

递归遍历:

//先根遍历/先序遍历  根 左 右  中序遍历 左 根  右   后序遍历   左 右 根

中序遍历:


先根遍历和后根遍历与此雷同,弄清楚一个,其余自然举一反三。
关键点:
1.迭代的当前数据是否有值,否则不予执行如图橘红色部分。
2.Date域输出顺序,根据遍历类型调整顺序。

非递归遍历:

(未完待续)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值