数据结构:树(1)

树的基本概念与术语

树的定义:

  • 树是N(N>=0)个结点组成的有穷集合T

树的特征:

  • 除N=0的树外,有且仅有一个特定的称为根的结点
  • 其余结点分为m(m>=0)个互不相交的有穷集合,其中每个集合都是一棵树,称为该根的子树

树的特点:

  • 有一个总根
  • 没有分支相交
  • 树有层次

基本术语:

  • 结点的度:该结点具有子树的数目
  • 叶子结点:度为0的结点
  • 树的度:树中结点度的最大值
  • 结点的层:根到该结点的路径长度(根为第0层)
  • 树的高度:树中结点层的最大值
  • 子女与双亲:子女指该结点子树的根节点,双亲即该结点
  • 兄弟与堂兄弟:同一双亲孩子之间称为兄弟,其双亲在同一层的结点互为堂兄弟
  • 祖先与子孙:从根到该结点所经分支上的所有结点称为该结点的祖先,以该结点为根的子树中的所有结点称为该结点的子孙
  • 森林:m棵互不相交的树的集合

二叉树

二叉树的定义及性质:

  • 二叉树是结点的有穷集合,二叉树可以是空树或者由一个根结点和其左右子树构成,且其左右子树满足二叉树的定义
  • 二叉树的基本形态
    在这里插入图片描述

二叉树的特征:

  • 二叉树的每个结点的度不大于2
  • 二叉树的子树有左右之分

二叉树的性质

  • 二叉树中层数为i的结点至多有2^i
  • 高度为k的二叉树至多有2^(k+1)-1个结点,这样的二叉树称为满二叉树
  • 若一棵具有n个结点,高度为k的二叉树,其中所有结点与高度为k的满二叉树中编号由1至n的结点对应,这样的二叉树称为完全二叉树
    满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树
  • 设二叉树中叶子结点的个数为n0,度为1结点的个数为n1,度为2结点的个数为n2,则n0=n2+1(推导:通过结点个数得出n0+n1+n2=n,通过结点和边的关系n1+2n2=n-1)
  • 将一棵具有n个结点的完全二叉树按层次顺序(从上到下,从左到右)从1开始编号,则对编号为i的结点有:
    若i不为1,则编号为i结点的双亲结点编号为[i/2]
    若2i<=n,则编号为i结点的左孩子的编号为2i,否则i无左孩子
    若2i+1<=n,则编号为i结点的右孩子的编号为2i+1,否则i无有孩子
    具有n个结点的完全二叉树高度为
    在这里插入图片描述
    利用n大于2^k-1小于等于2^(k+1)-1处理后两边同时取对数再取整得到完全二叉树的高度

二叉树结点的结构

在这里插入图片描述
在这里插入图片描述

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;

namespace ConsoleApp1
{
    public class BinTreeNode<T> : IComparable<BinTreeNode<T>> where T : IComparable<T>
    {
        private T _data;
        private BinTreeNode<T> _leftChild;
        private BinTreeNode<T> _rightChild;
        public T Data
        {
            get { return _data; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException();
                _data = value;
            }
        }
        public BinTreeNode<T> LeftChild
        {
            get { return _leftChild; }
            set { _leftChild = value; }
        }
        public BinTreeNode<T> RightChild 
        {
            get { return _rightChild; }
            set { _rightChild = value; }
        }
        public BinTreeNode(T data) 
        {
            if (data == null)
                throw new ArgumentNullException();
            _data = data;
            _leftChild = null;
            _rightChild = null;
        }
        public BinTreeNode(T data, BinTreeNode<T> left, BinTreeNode<T> right) 
        {
            if (data == null)
                throw new ArgumentNullException();
            _data = data;
            _leftChild = left;
            _rightChild = right;
        }
        public int CompareTo(BinTreeNode<T> other)
        {
            if (other == null)
                throw new ArgumentNullException();
            return _data.CompareTo(other._data);
        }

二叉树的遍历

定义

  • 按照一定次序访问树中所有结点,并且每个结点的值仅被访问一次的过程

遍历的方式

  • 前序遍历:访问根结点,前序遍历左子树,前序遍历右子树
  • 中序遍历:中序遍历左子树,访问根节点,中序遍历右子树
  • 后序遍历:后序遍历左子树,后序遍历右子树,访问根节点
  • 层序遍历:遍历第0层、遍历第1层、…、遍历第k层(k为树的高度)
    在这里插入图片描述

二叉树的实现

在这里插入图片描述

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

namespace ConsoleApp1
{
    public class BinTree<T>where T:IComparable<T>
    {
        private BinTreeNode<T> _root;
        private string _orderString;
        public BinTreeNode<T> Root 
        {
            get { return _root; }
            set { _root = value; }
        }
        public BinTree(BinTreeNode<T> root) 
        {
            _root = root;
        }
        public void Insert(BinTreeNode<T> current, BinTreeNode<T> lChild, BinTreeNode<T> rChild) 
        {
            if (current == null)
                throw new ArgumentNullException();
            current.LeftChild = lChild;
            current.RightChild = rChild;
        }
        public string PreOrderTraversal() 
        {
            _orderString = string.Empty;
            PreOrder(_root);
            return _orderString.Trim();
        }
        private void PreOrder(BinTreeNode<T>current) 
        {
            if (current == null)
                return;
            _orderString += current.Data + " ";
            PreOrder(current.LeftChild);
            PreOrder(current.RightChild);
        }
        public string MidOrderTraversal() 
        {
            _orderString = string.Empty;
            MidOrder(_root);
            return _orderString.Trim();
        }
        private void MidOrder(BinTreeNode<T>current) 
        {
            if (current == null) 
                return;
            MidOrder(current.LeftChild);
            _orderString += current.Data + " ";
            MidOrder(current.RightChild);
        }
        public string PostOrderTraversal()
        {
            _orderString = string.Empty;
            PostOrder(_root);
            return _orderString.Trim();
        }
        private void PostOrder(BinTreeNode<T>current) 
        {
            if (current == null)
                return;
            PostOrder(current.LeftChild);
            PostOrder(current.RightChild);
            _orderString += current.Data + " ";
        }
                public string LevelTraversal()
        {
            if (Root == null)
                return string.Empty;

            _orderString = string.Empty;
            LinkQueue<BinTreeNode<T>> lq = new LinkQueue<BinTreeNode<T>>();
            lq.EnQueue(_root);

            while (lq.IsEmpty() == false)
            {
                BinTreeNode<T> current = lq.QueueFront;
                lq.DeQueue();
                _orderString += current.Data.ToString() + " ";

                if (current.LeftChild != null)
                    lq.EnQueue(current.LeftChild);
                if (current.RightChild != null)
                    lq.EnQueue(current.RightChild);
            }
            return _orderString.Trim();
        }
                private BinTreeNode<T> FindParent(BinTreeNode<T> current, BinTreeNode<T> find)
        {
            if (find == null)
                throw new ArgumentNullException();
            if (current == null)
                return null;
            if (current != null && current.LeftChild == find)
                return current;
            if (current != null && current.RightChild == find)
                return current;
            BinTreeNode<T> temp = FindParent(current.LeftChild, find);
            if (temp != null)
                return temp;
            return FindParent(current.RightChild, find);
        }
        public BinTreeNode<T> GetParent(BinTreeNode<T> find)
        {
            if (find == null)
                throw new ArgumentNullException();
            return FindParent(_root, find);
        }
        public BinTreeNode<T> GetLeftSibling(BinTreeNode<T> current)
        {
            if (current == null)
                throw new ArgumentNullException();
            BinTreeNode<T> parent = GetParent(current);
            if (parent != null && parent.LeftChild != null && parent.LeftChild.Equals(current) == false)
                return parent.LeftChild;
            return null;
        }
        public BinTreeNode<T> GetRightSibling(BinTreeNode<T> current)
        {
            if (current == null)
                throw new ArgumentNullException();
            BinTreeNode<T> parent = GetParent(current);
            if (parent != null && parent.RightChild != null && parent.RightChild.Equals(current) == false)
                return parent.RightChild;
            return null;
        }
        public void DeleteSubTree(BinTreeNode<T> current)
        {
            if (current == null)
                throw new ArgumentNullException();
            if (_root != null && _root.Equals(current))
            {
                _root = null;
                return;
            }
            BinTreeNode<T> parent = GetParent(current);
            if (parent != null && parent.LeftChild != null && parent.LeftChild.Equals(current))
                parent.LeftChild = null;
            if (parent != null && parent.RightChild != null && parent.RightChild.Equals(current))
                parent.RightChild = null;
        }
        public BinTreeNode<T> Search(T data)
        {
            if (data == null)
                throw new ArgumentNullException();
            return FindDate(_root, data);
        }
        public BinTreeNode<T> FindDate(BinTreeNode<T> current, T data)
        {
            if (data == null)
                throw new ArgumentNullException();
            if (current == null)
                return null;
            if (current.Data.CompareTo(data) == 0)
                return current;
            BinTreeNode<T> temp = FindDate(current.LeftChild, data);
            if (temp != null)
                return temp;
            return FindDate(current.RightChild, data);
        }
        public void Exchange() 
        {
            Exchange(_root);
        }
        private void Exchange(BinTreeNode<T> current) 
        {
            if (current == null)
                throw new ArgumentNullException();
            if (current.LeftChild != null || current.RightChild != null) 
            {
                BinTreeNode<T> temp = current.LeftChild;
                current.LeftChild = current.RightChild;
                current.RightChild = temp;
            }
            if (current.LeftChild != null) Exchange(current.LeftChild);
            if (current.RightChild != null) Exchange(current.RightChild);
        }
        public int GetLeafCount() 
        {
            int count = 0;
            FindLeafCount(_root, ref count);
            return count;
        }
        private void FindLeafCount(BinTreeNode<T> current, ref int count) 
        {
            if (current == null)
                return;
            if (current.LeftChild == null && current.RightChild == null)
                count++;
            FindLeafCount(current.LeftChild, ref count);
            FindLeafCount(current.RightChild, ref count);
        }
    }
}
//
using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            BinTreeNode<string> A = new BinTreeNode<string>("A");
            BinTreeNode<string> B = new BinTreeNode<string>("B");
            BinTreeNode<string> C = new BinTreeNode<string>("C");
            BinTreeNode<string> D = new BinTreeNode<string>("D");
            BinTreeNode<string> E = new BinTreeNode<string>("E");
            BinTreeNode<string> F = new BinTreeNode<string>("F");
            BinTree<string> binTree = new BinTree<string>(A);
            binTree.Insert(A, B, E);
            binTree.Insert(B, null, C);
            binTree.Insert(E, null, F);
            binTree.Insert(C, D, null);//构造一棵树,用来实现各种方法
        }
    }
}

二叉树的存储

顺序存储

  • 完全二叉树利用顺序存储(数组)
  • 非完全二叉树利用链式存储
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值