树及二叉树

树:

1 概念

  • 定义:树是节点的有限集合
  • :当前双亲的直接孩子个数
  • 叶子:终端节点(度为0)就是叶子
  • :非终端节点
  • 有序树:树当中的节点之间位置不可以互换
  • 无序树:树当中节点之间位置可以互换
  • 深度之节点深度:当前节点所在第几层即为节点深度
  • 深度之树的深度:该树最大的节点深度

2 二叉树:

  • 定义:所有结点的度都小于等于2

3 二叉搜索树

  • 定义:所有结点的度都小于或等于2,并且当前结点值一定是大于左孩子结点值,小于右孩子结点值
  • 遍历:最后得到的遍历序列是一个有序序列

4 二叉树的遍历:

  • 二叉树当中按照根的遍历顺序分为以下3种遍历方式
             1(0)
             
     3(1)           5(2)
        
        
10(3)   26(4)  19(5)   27(6)
  • 前序遍历:根->左->右: 1->3->10->26->5->19->27
  • 中序遍历:左->根->右: 10->3->26->1->19->5->27
  • 后序遍历:左->右->根 10->26->3->19->27->5->1

5 树的用途

  • 压缩软件-赫夫曼树
  • 人机对战

6 二叉树的常用操作

  • 创建树
  • 销毁树
  • 根据下标搜索结点
  • 往某个结点某个孩子添加结点
  • 删除某个结点
  • 二叉树的深度
  • 二叉树结点个数

7 二叉树双向链表代码实现

  • 1 创建结点类TreeNode
        //该结点所在的下标
        private int index;
        //该结点实际存储的数据
        private T data;
        //该结点下的左孩子
        private TreeNode<T> leftNode;
        //该结点下的右孩子
        private TreeNode<T> rightNode;
        //该结点对应的父结点
        private TreeNode<T> parentNode;

        //属性 
        public T Data{set{ data = value;
            }get{ return data;}}

        public TreeNode<T> LeftNode{
            set{ 
                leftNode = value;
            }
            get{ 
                return leftNode;
            }
        }

        public TreeNode<T> RightNode{
            set{ 
                rightNode = value;
            }
            get{ 
                return rightNode;
            }
        }

        public TreeNode<T> ParentNode{
            set{ 
                parentNode = value;
            }
            get{ 
                return parentNode;
            }
        }

        public int Index{
            set{ 
                index = value;
            }
            get{ 
                return index;
            }
        }
        //常用构造
        public TreeNode ()
        {
            index = 0;
            data = default(T);
            leftNode = null;
            rightNode = null;
            parentNode = null;
        }

        public TreeNode(int index,T data){
            this.index = index;
            this.data = data;
            leftNode = null;
            rightNode = null;
            parentNode = null;
        }

        //使用递归来判断该下标的结点是否存在于该结点之下
        public TreeNode<T> NodeAtIndex(int index){
            //(1)  首先判断是否为该结点
            if (index == this.index) {
                return this;
            } 
            //(2)若不是则遍历该结点下的左右孩子,依次进行遍历下去
            TreeNode<T> temp = null;
            if (this.LeftNode != null) {
                temp = this.LeftNode.NodeAtIndex (index);
            }
            if (temp == null) {
                if(this.RightNode != null) {
                    temp = this.RightNode.NodeAtIndex (index);
                }
            }
            return temp;

        }

        //删除本身结点以及该结点下的子结点
        public void DeleteNode(){
            //(1)判断该结点是否存在左右孩子,若有的话同样进行删除(使用递归)
            if(this.LeftNode != null){
                this.LeftNode.DeleteNode ();
            }
            if (this.RightNode != null) {
                this.RightNode.DeleteNode ();
            }
            //判断该结点是属于双亲结点的左孩子还是右孩子,删除掉双亲对应的孩子 
            if (this.ParentNode != null) {
                if (this.ParentNode.LeftNode == this) {
                    this.ParentNode.LeftNode = null;
                }
                if (this.ParentNode.RightNode == this) {
                    this.ParentNode.RightNode = null;
                }
            }
        }

        //使用递归该结点下的所有结点进行前序遍历
        public void PreordeTraversal(){
                /*思路:遍历该结点下以及左右孩子(左右孩子存在的时候)
                        对于左右孩子则视为某些结点的双亲再进行前序遍历
                */
            Console.WriteLine("index = {0},data = {1}  ",Index,Data);
            if (this.LeftNode != null) {
                this.LeftNode.PreordeTraversal();
            }
            if (this.RightNode != null) {
                this.RightNode.PreordeTraversal ();
            }
        }

        //该结点下的所有结点进行中序遍历
        public void InorderTraversal(){
            /*思路同前序遍历,顺序调整为中,左,右*/
            if (this.LeftNode != null) {
                this.LeftNode.InorderTraversal();
            }
            Console.WriteLine("index = {0},data = {1}  ",Index,Data);

            if (this.RightNode != null) {
                this.RightNode.InorderTraversal ();
            }
        }
        //该结点下的所有结点进行后序遍历
        public void PostorderTraversal(){
            /*思路同前序遍历,顺序调整为左,右,中*/
            if (this.LeftNode != null) {
                this.LeftNode.PostorderTraversal ();
            }
            if (this.RightNode != null) {
                this.RightNode.PostorderTraversal ();
            }
            Console.WriteLine("index = {0},data = {1}  ",Index,Data);
        }

        //该结点的子结点包括该结点总共有几个结点
        public int CountOFChildNode(){
            int count = 0;
            if(this.LeftNode != null){
                count += this.LeftNode.CountOFChildNode ();
            }
            if (this.RightNode != null) {
                count += this.RightNode.CountOFChildNode ();
            }
            //返回之前进行++操作是将本身添加进去
            return ++count;
        }

        //某个结点的最大深度
        public int Depth(){
            int leftDepth = 0,rightDepth = 0;
            if(this.LeftNode != null){
                leftDepth = this.LeftNode.Depth ();
            }
            if (this.RightNode != null) {
                rightDepth = this.RightNode.Depth ();
            }
            return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1;
        }
  • 2 创建二叉树类BinaryTree<T>
        //根结点
        public TreeNode<T> rootNode;
        //构造方法,在创建树的时候对根结点进行初始化
        public BinaryTree ()
        {
            rootNode = new TreeNode<T> ();
        }

        //根据某个下标返回对应的结点 
        public TreeNode<T> NodeAtIndex(int index){
            return rootNode.NodeAtIndex(index);
        }

        //在下标为index添加一个结点node,direction为0表示左孩子,为1表示右孩子
        public bool AddNode(int index,int direction,TreeNode<T> node){
            //先判断index对应的结点是否存在,不存在则没法挂载
            TreeNode<T> temp = NodeAtIndex(index);
            if (temp == null) {
                return false;
            }
            //若是该结点存在则将要挂载的结点拷贝一份出来
            TreeNode<T> newNode = new TreeNode<T>();
            newNode.Index = node.Index;
            newNode.Data = node.Data;
            newNode.ParentNode = temp;
            if (direction == 0) {
                temp.LeftNode = newNode;
            }
            if (direction == 1) {
                temp.RightNode = newNode;
            }
            return true;
        }

        //根据下标删除一个结点
        public bool DeleteNode(int index){
            TreeNode<T> temp = NodeAtIndex(index);
            if (temp == null) {
                return false;
            }

            if (temp.ParentNode.LeftNode ==temp) {
                temp.ParentNode.LeftNode = null;
            } else if (temp.ParentNode.RightNode == temp) {
                temp.ParentNode.RightNode = null;
            }
            temp.DeleteNode ();
            return true;
        }

        //二叉树的深度
        public int DepthOfTree(){
            return rootNode.Depth();
        }
         
        //树的某个结点下子结点个数(包括该结点)
        public int CountOfNode(TreeNode<T> node){
            if (rootNode == null) {
                return 0;
            } else {
                return rootNode.CountOFChildNode ();
            }
        }

        //前序遍历
        public void PreordeTraversal(){
            rootNode.PreordeTraversal();
        }
        //中序遍历
        public void InorderTraversal(){
            rootNode.InorderTraversal();
        }
        //后序遍历
        public void PostorderTraversal(){
            rootNode.PostorderTraversal();
        }
  • 3 使用二叉树
            0
        1       2
    3    4  5     6
  7  8 9
            前序遍历:根左右: 0 1 3 7 8 4 9 2 5 6
            后序遍历:左右根:7 8 3 9 4 1 5 6 2 0
            中序遍历:左根右:7 3 8 1 9 4 0 5 2 6
  • 代码实现
//创建结点
BinaryTree<string> btTree = new BinaryTree<string> ();
            TreeNode<string> node0 = new TreeNode<string> (1, "node0");
            TreeNode<string> node1 = new TreeNode<string> (2, "node1");
            TreeNode<string> node2 = new TreeNode<string> (3, "node2");
            TreeNode<string> node3 = new TreeNode<string> (4, "node3");
            TreeNode<string> node4 = new TreeNode<string> (5, "node4");
            TreeNode<string> node5 = new TreeNode<string> (6, "node5");
            TreeNode<string> node6 = new TreeNode<string> (7, "node6");
            TreeNode<string> node7 = new TreeNode<string> (8, "node7");
            TreeNode<string> node8 = new TreeNode<string> (9, "node8");
            //添加结点
            btTree.AddNode (0, 0, node0);
            btTree.AddNode (0, 1, node1);
            btTree.AddNode (1, 0, node2);
            btTree.AddNode (1, 1, node3);
            btTree.AddNode (2, 0, node4);
            btTree.AddNode (2, 1, node5);
            btTree.AddNode (3, 0, node6);
            btTree.AddNode (3, 1, node7);
            btTree.AddNode (4, 0, node8);
            //删除结点
            btTree.DeleteNode (3);
            btTree.DeleteNode (4);
            //结点个数
            Console.WriteLine ("count = {0}", btTree.CountOfNode (btTree.rootNode));
            Console.WriteLine ("树的深度 = {0}", btTree.DepthOfTree ());
            //某个下标下的结点
            Console.WriteLine (btTree.NodeAtIndex (6).Data);
            //前序遍历
            btTree.PreordeTraversal ();
            //后序遍历
            btTree.PostorderTraversal();
            //中序遍历
            btTree.InorderTraversal();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容

  • 树的概述 树是一种非常常用的数据结构,树与前面介绍的线性表,栈,队列等线性结构不同,树是一种非线性结构 1.树的定...
    Jack921阅读 4,452评论 1 31
  • 四、树与二叉树 1. 二叉树的顺序存储结构 二叉树的顺序存储就是用数组存储二叉树。二叉树的每个结点在顺序存储中都有...
    MinoyJet阅读 1,528评论 0 7
  • B树的定义 一棵m阶的B树满足下列条件: 树中每个结点至多有m个孩子。 除根结点和叶子结点外,其它每个结点至少有m...
    文档随手记阅读 13,221评论 0 25
  • 数据结构和算法--二叉树的实现 几种二叉树 1、二叉树 和普通的树相比,二叉树有如下特点: 每个结点最多只有两棵子...
    sunhaiyu阅读 6,461评论 0 14
  • 树和二叉树 1、树的定义 树(Tree)是由一个 或 多个结点 组成的有限集合T,且满足: ①有且仅有一个称为根的...
    利伊奥克儿阅读 1,367评论 0 1