C#使用数组实现二叉查找树

原创性申明:

本文地址是http://blog.csdn.net/zhujunxxxxx/article/details/40925687 转载请注明出处。作者联系邮箱 zhujunxxxxx@163.com

二叉排序树

(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树。
它或者是一棵空树;或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; 
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; 
(3)左、右子树也分别为二叉排序树;

树的储方案:

用数组来实现二叉树,树上的元素存放位置在数组中是固定的—如果树的i位置(从1开始按层编号)有元素,就放在数组的i号位置,没有元素,数组对应的位置就空着。

i的左右子树的编号为2i和2i+1。

1,实例变量,容量动态扩展,以及构造方法:

/// <summary>
        /// 数组存储树的结构(还有一种是Node)
        /// </summary>
        private int[] data;//从1开始存储数据
        /// <summary>
        /// 树的长度
        /// </summary>
        private int len;

        /// <summary>
        /// 删除节点时用的一个临时的数据结构
        /// </summary>
        private List<int> tmpList;
        public Tree()
        {   
            //先初始化一个1w大小的数组
            this.data = new int[100];
            tmpList = new List<int>();
            len = 0;
        }

2,树的插入

数组实现插入其实跟链式思想还是一样,往下找插入节点就是往下找插入的下标,下标的关系已经在前面说过,要注意的是数组容量可能不够,需要扩展容量

/// <summary>
        /// 把节点插入树
        /// </summary>
        public void Insert(int key)
        {
            if (len == 0)
            {
                data[1] = key;
                len++;
            }
            else
            {
                int index = 1;
                while (index <data.Length)
                {
                    if (key < data[index])
                    {
                        //拓展数组
                        if (LeftChild(index) >= data.Length)
                            Expand();
                        //判断这个节点是否为空
                        if (data[LeftChild(index)] == 0)
                        {
                            data[LeftChild(index)] = key;
                            len++;
                            break;
                        }
                        else
                        {
                            index = LeftChild(index);
                        }
                    }
                    else
                    {
                        //拓展数组
                        if (RightChild(index) >= data.Length)
                            Expand();
                        //判断这个节点是否为空
                        if (data[RightChild(index)] == 0)
                        {
                            data[RightChild(index)] = key;
                            len++;
                            break;
                        }
                        else
                        {
                            index = RightChild(index);
                        }
                    }
                }
            }

        }

3,树的删除

当某个结点被删后,它的子树上的全部结点的下标都要调整,而且这个调整顺序还得从上网下调,否则下面的节点的可能覆盖上面的,

没有想到什么好的办法,最后只有用了一个消耗最大的笨方法—将被删结点置为null后,前序遍历树(或者后序,不能中序),

将前序序列依次重新插入建树。相当于删除节点后,把剩下结点取出来重新建树

/// <summary>
        /// 删除树的节点
        /// </summary>
        public int Delete(int key)
        {
            int value=-1;
            int index = Search(key);
            if (index != -1)
            {
                value=data[index];
                Remove(index);
            }
            return value;
 
        }
        /// <summary>
        /// 移除一个节点,并重新构造树
        /// </summary>
        /// <param name="index"></param>
        private void Remove(int index)
        {
            //设置要删除的值为0
            data[index] = 0;
            //删除指定下标处的元素,并得到删除后的树(调整位置)
            List<int> it = PreInorderList();//得到前序遍历的迭代器
            for (int i = 1; i < data.Length; i++)//将树清空
                data[i] = 0;
            //把树给清空,长度也变为0
            len = 0;
            foreach (int item in it)
            {
                Insert(item);
            }
        }

4,树的前序遍历

 /// <summary>
        /// 先序遍历
        /// </summary>
        public void PreOrder(int i)
        {
            if (i >= data.Length)
                return;
            if (data[i] != 0)
            {
                tmpList.Add(data[i]);
            }
            PreOrder(LeftChild(i));
            PreOrder(RightChild(i));
 
        }

5,树的中序遍历

/// <summary>
        /// 中序遍历
        /// </summary>
        /// <param name="i"></param>
        public void InOrder(int i)
        {
            if (i >=data.Length)
                return;
            InOrder(LeftChild(i));
            if (data[i] != 0)
            {
                Console.Write(data[i] + " ");
            }
            InOrder(RightChild(i));
        }

6,树的后续遍历

/// <summary>
        /// 后续遍历
        /// </summary>
        /// <param name="i"></param>
        public void PostOrder(int i)
        {
            if (i >= data.Length)
                return;
            PostOrder(LeftChild(i));
            PostOrder(RightChild(i));
            if (data[i] != 0)
            {
                Console.Write(data[i] + " ");
            }
        }

使用实例

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

namespace Other
{
    /// <summary>
    /// 二叉排序树(Binary Sort Tree)
    /// 二叉查找树(Binary Search Tree)
    /// </summary>
    public class Tree
    {
        /// <summary>
        /// 数组存储树的结构(还有一种是Node)
        /// </summary>
        private int[] data;//从1开始存储数据
        /// <summary>
        /// 树的长度
        /// </summary>
        private int len;

        /// <summary>
        /// 删除节点时用的一个临时的数据结构
        /// </summary>
        private List<int> tmpList;
        public Tree()
        {   
            //先初始化一个1w大小的数组
            this.data = new int[100];
            tmpList = new List<int>();
            len = 0;
        }
        /// <summary>
        /// 把节点插入树
        /// </summary>
        public void Insert(int key)
        {
            if (len == 0)
            {
                data[1] = key;
                len++;
            }
            else
            {
                int index = 1;
                while (index <data.Length)
                {
                    if (key < data[index])
                    {
                        //拓展数组
                        if (LeftChild(index) >= data.Length)
                            Expand();
                        //判断这个节点是否为空
                        if (data[LeftChild(index)] == 0)
                        {
                            data[LeftChild(index)] = key;
                            len++;
                            break;
                        }
                        else
                        {
                            index = LeftChild(index);
                        }
                    }
                    else
                    {
                        //拓展数组
                        if (RightChild(index) >= data.Length)
                            Expand();
                        //判断这个节点是否为空
                        if (data[RightChild(index)] == 0)
                        {
                            data[RightChild(index)] = key;
                            len++;
                            break;
                        }
                        else
                        {
                            index = RightChild(index);
                        }
                    }
                }
            }

        }
        /// <summary>
        /// 删除树的节点
        /// </summary>
        public int Delete(int key)
        {
            int value=-1;
            int index = Search(key);
            if (index != -1)
            {
                value=data[index];
                Remove(index);
            }
            return value;
 
        }
        /// <summary>
        /// 移除一个节点,并重新构造树
        /// </summary>
        /// <param name="index"></param>
        private void Remove(int index)
        {
            //设置要删除的值为0
            data[index] = 0;
            //删除指定下标处的元素,并得到删除后的树(调整位置)
            List<int> it = PreInorderList();//得到前序遍历的迭代器
            for (int i = 1; i < data.Length; i++)//将树清空
                data[i] = 0;
            //把树给清空,长度也变为0
            len = 0;
            foreach (int item in it)
            {
                Insert(item);
            }
        }
        /// <summary>
        /// 获取先序遍历的序列
        /// </summary>
        /// <returns></returns>
        private List<int> PreInorderList()
        {
            //生成前序序列
            PreOrder(1);
            List<int> tmp = tmpList;
            //重新把这个初始为空
            tmpList = new List<int>();
            return tmp;
        }
        /// <summary>
        /// 获取左孩子
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        private int LeftChild(int i)
        {
            return i * 2;
        }
        /// <summary>
        /// 获取右孩子
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        private int RightChild(int i)
        {
            return i * 2+1;
        }

        /// <summary>
        /// 当容量不够的时候拓展数组的大小
        /// </summary>
        private void Expand()
        {
            //一次扩大两倍
            int[] larger = new int[data.Length * 2];

            for (int i = 1; i < data.Length; i++)
            {
                larger[i] = data[i];
            }
            data = larger;
        }

        /// <summary>
        /// 查找树节点
        /// </summary>
        public int Search(int key)
        {
            int index = 1;
            while (index < data.Length && data[index] != 0)
            {
                if (data[index] == key)
                    return index;
                else if (key < data[index])
                {
                    index = LeftChild(index);
                }
                else
                {
                    index = RightChild(index);
                }
            }
            return -1;
        }
        /// <summary>
        /// 输出树的结构
        /// </summary>
        public override string ToString()
        {
            return null;
        }
        /// <summary>
        /// 先序遍历
        /// </summary>
        public void PreOrder(int i)
        {
            if (i >= data.Length)
                return;
            if (data[i] != 0)
            {
                tmpList.Add(data[i]);
            }
            PreOrder(LeftChild(i));
            PreOrder(RightChild(i));
 
        }
        /// <summary>
        /// 中序遍历
        /// </summary>
        /// <param name="i"></param>
        public void InOrder(int i)
        {
            if (i >=data.Length)
                return;
            InOrder(LeftChild(i));
            if (data[i] != 0)
            {
                Console.Write(data[i] + " ");
            }
            InOrder(RightChild(i));
        }
        /// <summary>
        /// 后续遍历
        /// </summary>
        /// <param name="i"></param>
        public void PostOrder(int i)
        {
            if (i >= data.Length)
                return;
            PostOrder(LeftChild(i));
            PostOrder(RightChild(i));
            if (data[i] != 0)
            {
                Console.Write(data[i] + " ");
            }
        }

    }
}
 static void Main(string[] args)
        {
            Tree t = new Tree();


            
            t.Insert(50);
            t.Insert(20);
            t.Insert(60);
            t.Insert(15);
            t.Insert(30);
            t.Insert(70);


            //从第一个位置开始
            t.InOrder(1);
            Console.WriteLine();
            t.Delete(20);
            t.InOrder(1);
        }

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/zhujunxxxxx/article/details/40925687
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞