c#数和二叉树

树(Tree)是 n(n≥0)个相同类型的数据元素的有限集合。树中的数据元素叫结点(Node)。n=0 的树称为空树(Empty Tree);对于 n>0 的任意非空树 T 有: (1)有且仅有一个特殊的结点称为树的根(Root)结点,根没有前驱结点; (2)若n>1,则除根结点外,其余结点被分成了m(m>0)个互不相交的集合T1,T2,…,Tm,其中每一个集合Ti(1≤i≤m)本身又是一棵树。树T1,T2,…,Tm称为这棵树的子树(Subtree)

二叉树(Binary Tree)是 n(n≥0)个相同类型的结点的有限集合。n=0 的二叉树称为空二叉树(Empty Binary Tree);对于 n>0 的任意非空二叉树有:
(1)有且仅有一个特殊的结点称为二叉树的根(Root)结点,根没有前驱结点;
(2)若n>1,则除根结点外,其余结点被分成了 2 个互不相交的集合TL,TR,而TL、TR本身又是一棵二叉树,分别称为这棵二叉树的左子树(Left Subtree)和右子树(Right Subtree)。

1)满二叉树(Full Binary Tree):如果一棵二叉树只有度为 0 的结点和度为 2的结点,并且度为 0 的结点在同一层上,则这棵二叉树为满二叉树

(2)完全二叉树(Complete Binary Tree):深度为 k,有 n 个结点的二叉树当且仅当其每一个结点都与深度为 k,有 n 个结点的满二叉树中编号从1到n的结点一一对应时,称为完全二叉树

二叉树的存储结构主要有三种:顺序存储结构、二叉链表存储结构和三叉链表存储结构

二叉链表存储结构的类实现
二叉树的二叉链表的结点类有3个成员字段:数据域字段data、左孩子引用域字段lChild和右孩子引用域字段rChild。

 public class Node<T>
    {
        private T data;//数据域

        public T Data
        {
            get { return data; }
            set { data = value; }
        }
        private Node<T> lchild;//左孩子

        public Node<T> Lchild
        {
            get { return lchild; }
            set { lchild = value; }
        }
        private Node<T> rchild;//右孩子

        public Node<T> Rchild
        {
            get { return rchild; }
            set { rchild = value; }
        }
        public Node()
        {
            data = default(T);
            lchild = null;
            rchild = null;
        }
        public Node(T data )
        {
            this.data = data;
            lchild = null;
            rchild = null;
        }

        public Node(T data, Node<T> lchild, Node<T> rchlid)
        {
            this.data = data;
            this.lchild = lchild;
            this.rchild = rchild;
        }
    }

不带头结点的二叉树的二叉链表比带头结点的二叉树的二叉链表的区别与不带头结点的单链表与带头结点的单链表的区别一样。

下面只介绍不带头结点的二叉树的二叉链表的类

public class BinaryTree<T>
    {
        private Node<T> head; //头引用

        internal Node<T> Head
        {
            get { return head; }
            set { head = value; }
        }

        public BinaryTree()
        {
            head = null;
        }
        public BinaryTree(T data)
        {
            Node<T> p = new Node<T>(data);
            head = p;
        }
        public BinaryTree(T data, Node<T> lchild, Node<T> rchild)
        {
            Node<T> p = new Node<T>(data, lchild, rchild);
            head = p;
        }
        // 二叉树是否为空
        public bool IsEmptyTree()
        {
            if (null != head)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        // 获取根节点
        public Node<T> GetRoot()
        {
            if (IsEmptyTree())
            {
                return null;
            }
            return head;
        }
        //获取结点的左孩子结点
        public Node<T> GetLChild(Node<T> p)
        {
            return p.Lchild;
        }
        // right child
        public Node<T> GetRChild(Node<T> p)
        {
            return p.Rchild;
        }
        //将结点p的左子树插入值为val的新结点,
        //原来的左子树成为新结点的左子树
        public void InsertL(T val, Node<T> p)
        {
            Node<T> temp = new Node<T>(val);
            temp.Lchild = p.Lchild;
            p.Lchild = temp;
        }

        //将结点p的右子树插入值为val的新结点,
        //原来的右子树成为新结点的右子树
        public void InsertR(T val, Node<T> p)
        {
            Node<T> tmp = new Node<T>(val);
            tmp.Rchild = p.Rchild;
            p.Rchild = tmp;
        }
        //若p非空,删除p的左子树
        public Node<T> DeleteL(Node<T> p)
        {
            if (p == null || p.Lchild == null)
            {
                return null;
            }
            Node<T> temp = p.Lchild;
            p.Lchild = null;
            return temp;
        }

        //若p非空,删除p的右子树
        public Node<T> DeleteR(Node<T> p)
        {
            if (p == null || p.Rchild == null)
            {
                return null;
            }
            Node<T> temp = p.Rchild;
            p.Rchild = null;
            return temp;
        }
        //判断是否是叶子结点
        public bool IsLeaf(Node<T> p)
        {
            if ( p != null && p.Lchild == null && p.Rchild == null)
            {
                return true;
            }
            return false;
        }
        // 销毁二叉树
        public void DestroyTree( Node<T> node )
        {
            if ( node != null )
            {
                if (node.Lchild != null)
                {
                    node.Lchild = null;
                }
                if (node.Rchild != null)
                {
                    node.Rchild = null;
                }
                node = null;
            }
        }

        // 1、先序遍历(DLR)
        public void PreOredr(Node<T> root)
        {
            if ( root == null )
            {
                //Console.WriteLine("树为空,无法遍历");
                return;
            }
            //处理根结点
            Console.WriteLine("{0}", root.Data);
            //先序遍历左子树
            PreOredr(root.Lchild);
            //再遍历右子树
            PreOredr(root.Rchild);
        }

        /*
         2、中序遍历(LDR)
         中序遍历的基本思想是:首先中序遍历根结点的左子树,然后访问根结点,
         最后中序遍历其右子树
         */
        public void InOrder(Node<T> root)
        {
            if (root.Lchild != null)
            {
                InOrder(root.Lchild);
            }

            Console.WriteLine( root.Data );

            if (root.Rchild != null)
            {
                InOrder(root.Rchild);
            }
        }
        /*
         3、后序遍历(LRD)
         后序遍历的基本思想是:首先后序遍历根结点的左子树,然后后序遍历根结
         点的右子树,最后访问根结点
         */
        public void PostOrder(Node<T> root)
        {
            if (root.Lchild != null)
            {
                PostOrder(root.Lchild);
            }
            if (root.Rchild != null)
            {
                PostOrder(root.Rchild);
            }
            Console.WriteLine(root.Data);
        }

        /*
         层序遍历的基本思想是:由于层序遍历结点的顺序是先遇到的结点先访问,
         与队列操作的顺序相同。所以,在进行层序遍历时,设置一个队列,将根结点引
         用入队,当队列非空时,循环执行以下三步:
        (1) 从队列中取出一个结点引用,并访问该结点;
        (2) 若该结点的左子树非空,将该结点的左子树引用入队;
        (3) 若该结点的右子树非空,将该结点的右子树引用入队
         */
        public void LevelOrder(Node<T> root)
        {
            if ( root == null )
            {
                return;
            }
            Queue<Node<T>> queue = new Queue<Node<T>>();
            queue.Enqueue(root);
            while ( queue.Count > 0 )
            {
                //结点出队
                Node<T> temp = queue.Dequeue();
                //处理当前结点
                Console.WriteLine("结点出队{0}", temp.Data);
                //将当前结点的左孩子结点入队
                if (temp.Lchild != null)
                {
                    queue.Enqueue(temp.Lchild);
                }
                if (temp.Rchild != null)
                {
                    queue.Enqueue(temp.Rchild);
                }
            }
        }
    }

// 测试

BinaryTree<char> tree = new BinaryTree<char>();
            Node<char> p = new Node<char>(‘A‘);
            Node<char> p1 = new Node<char>(‘B‘);
            tree.InsertL(‘B‘, p);
            tree.InsertL(‘D‘, p);
            tree.InsertR(‘E‘, p1);
            tree.InsertR(‘C‘, p);
            tree.InsertR(‘F‘, p);
            tree.InsertR(‘G‘, p);
            Console.WriteLine("先序遍历*******************************");
            tree.PreOredr(p);

            //tree.PreOredr(p1);
            Console.WriteLine("中序遍历*******************************");
            tree.InOrder(p);
            Console.WriteLine("后序遍历*******************************");
            tree.PostOrder(p);
            Console.WriteLine("层序遍历*******************************");
            tree.LevelOrder(p);
时间: 2024-10-01 05:00:12

c#数和二叉树的相关文章

数和二叉树——二叉树的建立及应用(遍历等)(基础篇)

二叉树:二叉树是每个结点最多有两个子树的有序树. 先来介绍一下二叉树的一些基本性质吧~ 二叉树的性质: 1.非空二叉树上叶子结点数等于双分支节点数加一. 性质1 二叉树第i层上的结点数目最多为2i-1(i≥1).证明:用数学归纳法证明:     归纳基础:i=1时,有2i-1=20=1.因为第1层上只有一个根结点,所以命题成立.    归纳假设:假设对所有的j(1≤j<i)命题成立,即第j层上至多有2j-1个结点,证明j=i时命题亦成立.    归纳步骤:根据归纳假设,第i-1层上至多有2i-2

数和二叉树(第七章)

树的基本概念 树的定义 数是有n个节点组成的有限集合(记为T).其中 如果n=0,它是一颗空树,这是树的特例 如果n>0,这n个节点中存在(且仅存在)一个节点作为树的根节点,简称为根:其余节点可分为m(m>=0)个互不交集的有限集T1,T2,Tn,其中每个子集本身又是一颗符合本定义的树,称为根的子树 树的定义是递归的 树是一种非线性结构. 树的逻辑表示方法 树形表示法 文氏图表示方法 凹入表示法 括号表示法 树的基本术语 节点的度与树的度:树中某个节点的子树的个数称为该节点的度.树中各节点的度

二叉树(8)----求二叉树第K层的节点数和二叉树第K层的叶子节点数,递归方式

1.二叉树定义 typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct BTreeNode_t_ { BTreeNodeElement_t *m_pElemt; struct BTreeNode_t_ *m_pLeft; struct BTreeNode_t_ *m_pRight; } BTreeNode_t; 2.求二叉树第K层的节点数 (1)递归方式 给定根节点pRoot: 如

浅谈数和二叉树

树:非线性结构.一对多的关系. 根节点:没有前驱节点的节点. 叶子节点:没有后继节点的节点. 节点的度:一个节点的子节点个数. 树的度:树中度最大的节点的度. 树的节点个数计算: 满树:一棵度为n,高度为h的满树,其节点个数是: n^0 + n^1 + n^2 + .......+ n^(n-1)  等比公式 总结点树和叶子节点数的计算: 度 个数 1 n1 2 n2 ...   ... d    nd n总 = n1 + 2n2  + 3n3 +.... +d*nd -1 n0 = n总 -

07_2.二叉数,二叉树的简单应用:表达式树

""" 二叉树的list实现 """ def BinTree(data, left=None, right=None): """ 二叉树 :param data: 根结点的元素 :param left: 左子树元素 :param right: 右子树元素 :return: """ return [data, left, right] def is_empty_BinTree(btree)

数据结构----树、二叉树----c++ &amp;&amp; python

树结构,尤其是二叉树结构是算法中常遇见的,这里根据学习过程做一个总结. 二叉树所涉及到的知识点有:满二叉树与完全二叉树.节点数目的关系.节点数与二叉树高度的关系.层次遍历.深度优先遍历.广度优先遍历等等. 这里对二叉树的基本结构实现c++版本以及python版本的代码,并且实现二叉树的前中后序遍历过程以及前中.中后序列创建唯一二叉树的过程. 1.C++版本实现 基本结构: http://www.cnblogs.com/elleniou/archive/2012/05/03/2480042.htm

数据结构——二叉树(Binary Trees)

非线性数据结构 树的密度=结点数/高度 二叉树类 1 #pragma once 2 3 class stnode 4 { 5 public: 6 int nodeValue; // node data 7 8 stnode *left, *right, *parent; // child pointers and pointer to the node's parent 9 10 // constructor 11 stnode (const int item, stnode *lptr = N

重温数据结构:二叉树的常见方法及三种遍历方式 Java 实现

读完本文你将了解到: 什么是二叉树 Binary Tree 两种特殊的二叉树 满二叉树 完全二叉树 满二叉树 和 完全二叉树 的对比图 二叉树的实现 用 递归节点实现法左右链表示法 表示一个二叉树节点 用 数组下标表示法 表示一个节点 二叉树的主要方法 二叉树的创建 二叉树的添加元素 二叉树的删除元素 二叉树的清空 获得二叉树的高度 获得二叉树的节点数 获得某个节点的父亲节点 二叉树的遍历 先序遍历 中序遍历 后序遍历 遍历小结 总结 树的分类有很多种,但基本都是 二叉树 的衍生,今天来学习下二

11.二叉树基本理论

一.二叉树基本概念 1.定义 二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者为空集(或称空二叉树),或者由一个根节点和两颗互不相交的.分别称为根结点的左子树和右子树的二叉树组成. 2.二叉树特点 (1)每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点; (2)左子树和右子树是有顺序的,次序不能任意颠倒; (3)即使树中某节点只有一颗子树,也要区分它是左子树还是右子树. 另外,二叉树具有五种基本形态: a.空二叉树;b.只有一个根结点;c.根结点只有左子树;d