基于C#的泛型搜索二叉树

搜索二叉树是序列式容器的底层数据结构;泛型版本能存储各种类型的数据。

二叉树有三个关键数据成员:存储数据,左节点,右节点;在C#中定义为三个属性:Data, Left, Right。

1)为使用方便,实现了<,>两个操作符;主要C#的泛型定义与C++有所区别,不能直接使用模板类的操作符。C#这方面坚持比较严格,会报出operator '<' cannot be applied to operands 'T' and operands 'T'编译错误。这里使用C#的Comparer<T>得到模板类的默认比较操作符解决。Comparer<T>实现的C#的IComparable接口。如果你的类有自己的基类,不妨实现此接口,方便在泛型版本进行比较操作。

2)这里枚举了三种搜索方式 SearchOrder{ InOrder, PreOrder, PostOrder };划分的依据是左,右和父节点之间的先后顺序。L->P->R:InOrder,P->L->R:PreOrder,L->R->P:PostOrder。

3)为方便调试,定义的节点的打印;为保留输出方式的多变性,把StreaWriter传入;比如想打印到标注输出,就可以这样创建StreamWriter:

StreamWriter sw = new StreamWriter(Console.OpenStandardOutput());
            sw.AutoFlush = true;

也可以输出到文本文件中。

4)public方法简介:

  • public void Insert(T t)出入类型T数据
  • public void Traverse(Node<T> root, StreamWriter sw, SearchOrder so)二叉树遍历
  • public T FindMin()查找最小值
  • public T FindMax()查找最大值
  • public Node<T> Find(T key)查找指定值的节点
  • public bool Delete(T key)删除某一值的节点

实际运行结果:

InOrder traversal:
3 16 22 23 37 45 99
23 16 3 22 45 37 99
3 22 16 37 99 45 23
Minmum value:3, Maximum value:99

find a 3
16 22 23 37 45 99
16 22 23 37 99
22 23 37 99
22 23 99
22 99
22

Press any key to continue . . .

 

源代码清单。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace BinaryTree
{   
    public class Node<T>
    {
        private T tData;
        private Node<T> left;
        private Node<T> right;
        public T Data
        {
            get
            {
                return tData;
            }
            set
            {
                tData = value;
            }
        }
        public Node<T> Left
        {
            get
            {
                return left;
            }
            set
            {
                left = value;
            }       
        }
        public Node<T> Right
        {
            get
            {
                return right;
            }
            set
            {
                right = value;
            }     
        }
        public void Write(StreamWriter sw)
        {             
            sw.Write(tData);
            sw.Write(' ');
        }
        public static bool operator< (Node<T> n1, Node<T> n2)
        {
            return 0 > Comparer<T>.Default.Compare(n1.Data, n2.Data);
        }
        public static bool operator >(Node<T> n1, Node<T> n2)
        {
            return 0 < Comparer<T>.Default.Compare(n1.Data, n2.Data);
        }
    }
    public class BinarySearchTree<T>
    {
        private Node<T> root;
        public Node<T> Root
        {
            get
            {
                return root;
            }
            set
            {
                root = value;
            }
        }
        public enum SearchOrder{ InOrder, PreOrder, PostOrder };
        public BinarySearchTree()
        {
            root = null;
        }
        public void Insert(T t)
        {
            Node<T> newNode = new Node<T>();
            newNode.Data = t;
            if (root == null)
            {
                root = newNode;
            }
            else
            {
                Node<T> current = root;
                Node<T> parent;
                while (true)
                {
                    parent = current;
                    if (0 > Comparer<T>.Default.Compare(t,current.Data))
                    {
                        current = current.Left;
                        if (current == null)
                        {
                            parent.Left = newNode;
                            break;
                        }
                        else
                        {
                            //next loop
                        }
                    }
                    else
                    {
                        current = current.Right;
                        if (current == null)
                        {
                            parent.Right = newNode;
                            break;
                        }
                    }
                }
            }      
        }
        private void InOrder(Node<T> root, StreamWriter sw)
        {
            if (root != null)
            {
                InOrder(root.Left,sw);
                root.Write(sw);
                InOrder(root.Right, sw);               
            }
        }
        private void PreOrder(Node<T> root, StreamWriter sw)
        {
            if (root != null)
            {
                root.Write(sw);
                PreOrder(root.Left, sw);
                PreOrder(root.Right, sw);
            }
        }
        private void PostOrder(Node<T> root, StreamWriter sw)
        {
            if (root != null)
            {
                PostOrder(root.Left, sw);
                PostOrder(root.Right, sw);
                root.Write(sw);
            }
        }
        public void Traverse(Node<T> root, StreamWriter sw, SearchOrder so)
        {
            switch (so)
            {
                case BinarySearchTree<T>.SearchOrder.InOrder: InOrder(root, sw); break;
                case BinarySearchTree<T>.SearchOrder.PreOrder: PreOrder(root, sw); break;
                case BinarySearchTree<T>.SearchOrder.PostOrder: PostOrder(root, sw); break;
            }           
        }
        public T FindMin()
        {
            Node<T> current = root;
            while (current.Left != null)
            {
                current = current.Left;
            }
            return current.Data;
        }
        public T FindMax()
        {
            Node<T> current = root;
            while (current.Right != null)
            {
                current = current.Right;
            }
            return current.Data;
        }
        public Node<T> Find(T key)
        {
            Node<T> current = root;
            while (current != null)
            {
                int cmp = Comparer<T>.Default.Compare(current.Data, key);
                if (0 == cmp)
                {
                    return current;
                }
                else if (0 < cmp)
                {
                    current = current.Left;
                }
                else
                {
                    current = current.Right;
                }
            }
            return null;
        }
        public bool Delete(T key)
        {
            Node<T> current = root;
            Node<T> parent = root;
            bool isLeft = true;
            while (current != null)
            {
                int cmp = Comparer<T>.Default.Compare(current.Data, key);
                if (0 == cmp)
                {                          
                    if (current.Left == null && current.Right == null)
                    {
                        //leaf node
                        if (current != root)
                        {
                            if (isLeft == true)
                            {
                                parent.Left = null;
                            }
                            else
                            {
                                parent.Right = null;
                            }
                        }
                        else
                        {
                            root = null;
                        }
                    }
                    else if (current.Left == null)
                    {
                        //with right child
                        if (current == root)
                        {
                            root = current.Right;
                        }
                        else if (isLeft)
                        {
                            parent.Left = current.Right;
                        }
                        else
                        {
                            parent.Right = current.Right;
                        }
                    }
                    else if (current.Right == null)
                    {
                        //with left child
                        if (current == root)
                        {
                            root = current.Left;
                        }
                        else if (isLeft)
                        {
                            parent.Left = current.Left;
                        }
                        else
                        {
                            parent.Right = current.Left;
                        }
                    }
                    else
                    {
                        isLeft = false;
                        //two children   
                        Node<T> successor = GetSuccessor(current);
                        if (successor == root.Right)
                        {
                            root = successor;
                        }
                        else if (isLeft)
                        {
                            parent.Left = successor;
                        }
                        else
                        {
                            parent.Right = successor;
                        }
                        successor.Left = current.Left;
                    }                   

                    return true ;
                }
                else if (0 < cmp)
                {
                    parent = current;
                    current = current.Left;                   
                    isLeft = true;
                }
                else
                {
                    parent = current;
                    current = current.Right;
                    isLeft = false;
                }
            }
            return false;
        }
        private Node<T> GetSuccessor(Node<T> delNode)
        {
            Node<T> sucParent = delNode;
            Node<T> suc = delNode;
            Node<T> current = delNode.Right;
            while (current != null)
            {
                sucParent = current;
                suc = current;
                current = current.Left;
            }
            if (suc != delNode.Right)
            {
                //only right child
                sucParent.Right = current.Right;
            }
            return suc;
        }
    }

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值