二叉树 订阅
二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分 [1]  。二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个结点 [1]  。 展开全文
二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分 [1]  。二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个结点 [1]  。
信息
概    述
计算机中数据结构的一种
存储方式
顺序存储、链式存储
应用学科
计算机科学
中文名
二叉树
简    介
每个结点最多有两个子树的树结构
外文名
Binary Tree
二叉树定义
二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树 [2]  。
收起全文
精华内容
下载资源
问答
  • 二叉树

    千次阅读 多人点赞 2019-08-04 11:39:26
    二叉树二叉树概念二叉树分类完全二叉树二叉树平衡二叉树相关术语解释二叉树性质二叉树的遍历方式先序遍历中序遍历后序遍历层次遍历特殊的二叉树堆二叉查找树(BST)红黑树 二叉树概念 在计算机科学中,二叉树是每个...

    二叉树概念

    在计算机科学中,二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”和“右子树”。二叉树常被用于实现二叉查找树和二叉堆。

    二叉树分类

    完全二叉树

    若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。

    满二叉树

    除了叶子结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树

    平衡二叉树

    它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

    相关术语解释

    树的结点:包含一个数据元素及若干指向子树的分支;
    孩子结点:结点的子树的根称为该结点的孩子;
    双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;
    兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;
    祖先结点: 从根到该结点的所经分支上的所有结点
    子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙
    结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;
    树的深度:树中最大的结点层
    结点的度:结点子树的个数
    树的度: 树中最大的结点度。
    叶子结点:也叫终端结点,是度为 0 的结点;
    分枝结点:度不为0的结点;
    有序树:子树有序的树,如:家族树;
    无序树:不考虑子树的顺序;

    二叉树性质

    (1) 在非空二叉树中,第i层的结点总数不超过2的i-1次方 , i>=1;
    (2) 深度为h的二叉树最多有2的h次方减1个结点(h>=1),最少有h个结点;
    (3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
    (4) 具有n个结点的完全二叉树的深度为[2为底n的对数]+1 (注:[ ]表示向下取整)
    (5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
    若I为结点编号则 如果I>1,则其父结点的编号为I/2;
    如果2*I<=N,则其左孩子(即左子树的根结点)的编号为2*I;若2*I>N,则无左孩子;
    如果2*I+1<=N,则其右孩子的结点编号为2*I+1;若2*I+1>N,则无右孩子。
    (6)给定N个节点,能构成h(N)种不同的二叉树。
    h(N)为卡特兰数的第N项。h(n)=C(2*n,n)/(n+1)。
    (7)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i

    二叉树的遍历方式

    先序遍历

    先访问根节点,先序遍历左子树,先序遍历右子树

    中序遍历

    中序遍历左子树,访问根节点,中序遍历右子树

    后序遍历

    后序遍历左子树,后序遍历右子树,访问根节点

    层次遍历

    即按照层次访问,通常用队列来做。访问根,访问子女,再访问子女的子女

    特殊的二叉树

    堆具有以下性质:
    每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;
    每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

    二叉查找树(BST)

    二叉查找树的特点:
    若任意节点的左子树不空,则左子树上所有结点的 值均小于它的根结点的值
    若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值
    任意节点的左、右子树也分别为二叉查找树
    没有键值相等的节点

    红黑树

    红黑树具有以下性质:
    每个节点非红即黑
    根节点总是黑色的
    每个叶子节点都是黑色的空节点(NIL节点)
    如果节点是红色的,则它的子节点必须是黑色的(反之不一定)
    从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)

    展开全文
  • 数据结构 - 二叉树的遍历

    万次阅读 多人点赞 2019-02-18 14:32:52
    分享一个大牛的人工智能教程。...给定一棵二叉树的前序遍历序列和中序遍历序列可以惟一确定一棵二叉树二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。 ...

    分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net 

    二叉树的遍历

    N:访问根结点,L:遍历根结点的左子树,R:遍历根结点的右子树。

    给定一棵二叉树的前序遍历序列和中序遍历序列可以惟一确定一棵二叉树。

    二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。

    深度优先遍历二叉树

    1. 中序遍历(LNR)的递归算法:

    若二叉树为空,则算法结束;否则:

    中序遍历根结点的左子树;

    访问根结点;

    中序遍历根结点的右子树。

    2. 前序遍历(NLR)的递归算法:

    若二叉树为空,则算法结束,否则:

    访问根结点;

    前序遍历根结点的左子树;

    前序遍历根结点的右子树。

    3. 后序遍历(LRN)的递归算法:

    若二叉树为空,则算法结束,否则:

    后序遍历根结点的左子树;

    后序遍历根结点的右子树;

    访问根结点。

    非递归深度优先遍历二叉树

    栈是实现递归最常用的结构,利用一个栈来记下尚待遍历的结点或子树,以备以后访问,可以将递归的深度优先遍历改为非递归的算法。

    1. 非递归前序遍历:遇到一个结点,就访问该结点,并把此结点推入栈中,然后下降去遍历它的左子树。遍历完它的左子树后,从栈顶托出这个结点,并按照它的右链接指示的地址再去遍历该结点的右子树结构。

    2. 非递归中序遍历:遇到一个结点,就把它推入栈中,并去遍历它的左子树。遍历完左子树后,从栈顶托出这个结点并访问之,然后按照它的右链接指示的地址再去遍历该结点的右子树。

    3. 非递归后序遍历:遇到一个结点,把它推入栈中,遍历它的左子树。遍历结束后,还不能马上访问处于栈顶的该结点,而是要再按照它的右链接结构指示的地址去遍历该结点的右子树。遍历完右子树后才能从栈顶托出该结点并访问之。另外,还需要给栈中的每个元素加上一个特征位,以便当从栈顶托出一个结点时区别是从栈顶元素左边回来的(则要继续遍历右子树),还是从右边回来的(则该结点的左、右子树均已遍历)。特征为Left表示已进入该结点的左子树,将从左边回来;特征为Right表示已进入该结点的右子树,将从右边回来。

    非递归广度优先遍历二叉树

    非递归广度优先遍历二叉树(层序遍历)是用队列来实现的。从二叉树的第一层(根结点)开始,自上至下逐层遍历;在同一层中,按照从左到右的顺序对结点逐一访问。

    按照从根结点至叶结点、从左子树至右子树的次序访问二叉树的结点。算法如下:

    1. 初始化一个队列,并把根结点入队列;

    2. 当队列为非空时,循环执行步骤3到步骤5,否则执行6;

    3. 出队列取得一个结点,访问该结点;

    4. 若该结点的左子树为非空,则将该结点的左子树入队列;

    5. 若该结点的右子树为非空,则将该结点的右子树入队列;

    6. 结束。

    /*
     * Binary Tree Breadth-First Traverse - by Chimomo
     */
    
    #include <iostream>
    
    #define _OK 1
    #define _ERROR 0
    
    using namespace std;
    
    // Define node element type in binary tree.
    typedef char Element;
    
    // Binary tree node.
    typedef struct BTNode {
        Element data;
        BTNode *lChild, *rChild; // Define left, right subtree.
    } BTNode, *BTree;
    
    // Define node element type in queue. (The node element type in queue is the pointer to binary tree node)
    typedef BTNode *QElementType;
    typedef int status;
    
    // We need use queue to perform level traverse. So, define queue first.
    typedef struct QNode {
        QElementType data;
        QNode *next;
    } QNode, *QueuePtr;
    
    // Definition of queue.
    typedef struct {
        QueuePtr front;
        QueuePtr rear;
    } LinkQueue;
    
    status InitQueue(LinkQueue &Q) {
        Q.front = NULL;
        Q.rear = NULL;
        return _OK;
    }
    
    bool IsEmpty(LinkQueue Q) {
        return Q.front == NULL;
    }
    
    /**
     * Enqueue.
     * @param Q The queue.
     * @param e The queue element.
     * @return 1 for ok, 0 for error.
     */
    status EnQueue(LinkQueue &Q, QElementType e) {
        // Construct queue node.
        QNode *ptrNode = (QNode *) malloc(sizeof(QNode));
        if (!ptrNode) {
            return _ERROR;
        }
    
        ptrNode->data = e;
        ptrNode->next = NULL;
        if (IsEmpty(Q)) {
            Q.front = Q.rear = ptrNode;
            return _OK;
        }
    
        Q.rear->next = ptrNode;
        Q.rear = ptrNode;
        return _OK;
    }
    
    /**
     * Dequeue.
     * @param Q The queue.
     * @param e The queue element.
     * @return 1 for ok, 0 for error.
     */
    status DeQueue(LinkQueue &Q, QElementType &e) {
        if (IsEmpty(Q)) {
            return _ERROR;
        }
    
        QNode *tempPtr = Q.front;
        e = tempPtr->data;
        Q.front = tempPtr->next;
        free(tempPtr);
        return _OK;
    }
    
    /**
     * Create binary tree.
     * @param T The binary tree address.
     * @return 1 for success, 0 for fail.
     */
    int CreateBTree(BTree &T) {
        char ch;
        cout << "Please input a character:" << endl;
        cin >> ch;
        if (ch == '#') {
            T = NULL;
        } else {
            // Allocate memory for new node.
            if (!(T = (BTNode *) malloc(sizeof(BTNode)))) {
                return 0; // Allocation fails.
            }
    
            T->data = ch;
    
            // Create left subtree.
            CreateBTree(T->lChild);
    
            // Create right subtree.
            CreateBTree(T->rChild);
        }
    
        return 1;
    }
    
    void VisitBTNode(BTNode *BT) {
        cout << BT->data << " ";
    }
    
    void VisitQNode(QNode *Q) {
        VisitBTNode(Q->data);
    }
    
    /**
     * Breadth-first traverse.
     * @param T The binary tree.
     */
    void LevelTraverse(BTree T) {
        QElementType e;
        LinkQueue Q;
        InitQueue(Q);
        EnQueue(Q, T);
        while (!IsEmpty(Q)) {
            VisitQNode(Q.front);
            if (Q.front->data->lChild != NULL) {
                EnQueue(Q, Q.front->data->lChild);
            }
            if (Q.front->data->rChild != NULL) {
                EnQueue(Q, Q.front->data->rChild);
            }
            DeQueue(Q, e);
        }
    }
    
    int main() {
        BTree T;
        CreateBTree(T);
        cout << "Breadth-first traverse: ";
        LevelTraverse(T);
        return 0;
    }
    
    // Output:
    /*
    Please input a character:
    1
    1
    Please input a character:
    2
    2
    Please input a character:
    3
    3
    Please input a character:
    4
    4
    Please input a character:
    5
    5
    Please input a character:
    6
    6
    Please input a character:
    #
    #
    Please input a character:
    #
    #
    Please input a character:
    #
    #
    Please input a character:
    #
    #
    Please input a character:
    #
    #
    Please input a character:
    #
    #
    Please input a character:
    #
    #
    Breadth-first traverse: 1 2 3 4 5 6
    */

     

    展开全文
  • 为什么叫 平衡二叉树?而不叫 二叉平衡树 呢?
    本文已收录于专栏
    🌳《画解数据结构》🌳

    前言

      上一篇文章 二叉搜索树 中,对于 「 增 」「 删 」「 改 」「 查 」 的时间复杂度为 O ( l o g 2 n ) O(log_2n)

    展开全文
  • 数据结构——二叉树先序、中序、后序三种遍历二叉树先序、中序、后序三种遍历三、代码展示: 二叉树先序、中序、后序三种遍历 先序遍历:3 2 2 3 8 6 5 4 中序遍历:2 2 3 3 4 5 6 8 后序遍历: 2 3 2 4 5 6 8 3 ...

    一、图示展示:

    (1)先序遍历

    先序遍历可以想象为,一个小人从一棵二叉树根节点为起点,沿着二叉树外沿,逆时针走一圈回到根节点,路上遇到的元素顺序,就是先序遍历的结果

    先序遍历结果为:A B D H I E J C F K G

    在这里插入图片描述
    动画演示:

    记住小人沿着外围跑一圈(直到跑回根节点),多看几次动图便能理解

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

    (2)中序遍历

    中序遍历可以看成,二叉树每个节点,垂直方向投影下来(可以理解为每个节点从最左边开始垂直掉到地上),然后从左往右数,得出的结果便是中序遍历的结果

    中遍历结果为:H D I B E J A F K C G
    在这里插入图片描述

    动画展示:

    记住,中序遍历就是从最左边开始,把每个节点垂直投影到同一直线上,然后从左往右读值就可以了,多看几遍动图就理解了

    在这里插入图片描述

    (3)后序遍历

    后序遍历就像是剪葡萄,我们要把一串葡萄剪成一颗一颗的

    还记得我上面提到先序遍历绕圈的路线么?(不记得翻上面理解)

    就是围着树的外围绕一圈,如果发现一剪刀就能剪下的葡萄(必须是一颗葡萄)(也就是葡萄要一个一个掉下来,不能一口气掉超过1个这样),就把它剪下来,组成的就是后序遍历了。

    后序遍历中,根节点默认最后面

    后序遍历结果:H I D J E B K F G C A
    在这里插入图片描述
    动画展示:
    在这里插入图片描述

    (4)层次遍历

    层次遍历很好理解,就是从根节点开始,一层一层,从上到下,每层从左到右,依次写值就可以了

    层次遍历结果:A B C D E F G H I J K

    在这里插入图片描述

    解释外圈跑的意思:

    绕着外围跑一整圈的真正含义是:遍历所有结点时,都先往左孩子走,再往右孩子走。

    (5)口诀

    先序遍历: 先根 再左 再右

    中序遍历: 先左 再根 再右

    后序遍历: 先左 再右 再根

    这里的根,指的是每个分叉子树(左右子树的根节点)根节点,并不只是最开始头顶的根节点,需要灵活思考理解,建议画图理解!!

    二、代码展示:

    #include<stdio.h>
    #include<stdlib.h>
    
    typedef struct Tree{
     
     int data;					//	存放数据域
     struct Tree *lchild;			//	遍历左子树指针
     struct Tree *rchild;			//	遍历右子树指针
     
    }Tree,*BitTree;
    
    BitTree CreateLink()
    {
    	int data;
    	int temp;
    	BitTree T;
    	
    	scanf("%d",&data);		//	输入数据
    	temp=getchar();			//	吸收空格
    	
    	if(data == -1){			//	输入-1 代表此节点下子树不存数据,也就是不继续递归创建
    		
    		return NULL;
    
    	}else{
    		T = (BitTree)malloc(sizeof(Tree));			//		分配内存空间
    		T->data = data;								//		把当前输入的数据存入当前节点指针的数据域中
    		
    		printf("请输入%d的左子树: ",data);		
    		T->lchild = CreateLink();					//		开始递归创建左子树
    		printf("请输入%d的右子树: ",data);			
    		T->rchild = CreateLink();					//		开始到上一级节点的右边递归创建左右子树
    		return T;							//		返回根节点
    	}	
    	
    }
    //	先序遍历
    void ShowXianXu(BitTree T)			//		先序遍历二叉树
    {
    	if(T==NULL)						//	递归中遇到NULL,返回上一层节点
    	{
    		return;
    	}
    	printf("%d ",T->data);
    	ShowXianXu(T->lchild);			//	递归遍历左子树
    	ShowXianXu(T->rchild);			//	递归遍历右子树
    }
    //	中序遍历
    void ShowZhongXu(BitTree T)			//		先序遍历二叉树
    {
    	if(T==NULL)						//	递归中遇到NULL,返回上一层节点
    	{
    		return;
    	}
    	
    	ShowZhongXu(T->lchild);			//	递归遍历左子树
    	printf("%d ",T->data);
    	ShowZhongXu(T->rchild);			//	递归遍历右子树
    	
    }
    //	后序遍历
    void ShowHouXu(BitTree T)			//		后序遍历二叉树
    {
    	if(T==NULL)						//	递归中遇到NULL,返回上一层节点
    	{
    		return;
    	}
    	
    	ShowHouXu(T->lchild);			//	递归遍历左子树
    	ShowHouXu(T->rchild);			//	递归遍历右子树
    	printf("%d ",T->data);
    }
    
    
    int main()
    {
    	BitTree S;
    	printf("请输入第一个节点的数据:\n");
    	S = CreateLink();			//		接受创建二叉树完成的根节点
    	printf("先序遍历结果: \n");
    	ShowXianXu(S);				//		先序遍历二叉树
    
    	printf("\n中序遍历结果: \n");
    	ShowZhongXu(S);				//		中序遍历二叉树
    	
    	printf("\n后序遍历结果: \n");
    	ShowHouXu(S);				//		后序遍历二叉树
    	
    	return 0;	
    } 	
    
    
    展开全文
  • 二叉树的基本操作

    万次阅读 多人点赞 2019-04-21 01:43:02
    2、掌握二叉树的基本操作,如二叉树的建立、遍历、结点个数统计、树的深度计算等。 二、实验内容 (一)用递归的方法实现以下算法: 1、以二叉链表表示二叉树,建立一棵二叉树(算法5.3); 2、输出二叉树的中序...
  • 数据结构 - 平衡二叉树(C++)

    万次阅读 多人点赞 2019-02-22 15:36:53
    平衡二叉树(Balanced Binary Tree)是具有以下性质的二叉树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。 判断一棵二叉树是否平衡(C++) /* * Cr...
  • java实现简单二叉树

    万次阅读 多人点赞 2018-07-25 08:08:03
    二叉树全面讲解
  • 关于二叉树的前序、中序、后序三种遍历

    万次阅读 多人点赞 2018-05-07 12:25:02
    二叉树遍历分为三种:前序、中序、后序,其中序遍历最为重要。为啥叫这个名字?是根据根节点的顺序命名的。比如上图正常的一个满节点,A:根节点、B:左节点、C:右节点,前序顺序是ABC(根节点排最先,然后同级先左...
  • 二叉树的详解与实现

    万次阅读 多人点赞 2019-08-18 22:40:30
    二叉树的相关概念,如,树高度,节点层数,节点度数,路径,叶节点,分支节点,根节点,父节点,左节点,右节点,兄弟节点,祖先节点,子孙节点,左子树,右子树等基本概念,不再赘述。 二叉树分类 1、完全二叉树 ...
  • 二叉树的建立及其递归遍历(C语言实现)

    万次阅读 多人点赞 2018-06-22 22:58:03
    以下是我对二叉树的一些总结内容 二叉树的特点有: - 每一个节点最多有两棵子树,所以二叉树中不存在度大于2的节点,注意,是最多有两棵,没有也是可以的 左子树和右子树是有顺序的,次序不能颠倒,这点可以在...
  • 二叉树的遍历

    万次阅读 2020-05-30 12:36:43
    遍历 先序遍历[先访问根节点] 先访问根节点 再先序访问左子树 ...但是通过先序和后序是无法还原出原始的二叉树的 换种说法: 只有通过先序和中序,或 通过中序和后序 我们才可以唯一的确定一个二叉树 ...
  • 二叉树层次遍历算法——C/C++

    万次阅读 多人点赞 2019-06-16 00:32:47
    二叉树层序遍历 1、算法思想 用一个队列保存被访问的当前节点的左右孩子以实现层序遍历。 在进行层次遍历的时候,设置一个队列结构,遍历从二叉树的根节点开始,首先将根节点指针入队列,然后从队头取出一个元素...
  • 完美二叉树, 完全二叉树和完满二叉树

    万次阅读 多人点赞 2018-06-22 15:05:42
    如果学习过二叉树,但是对这三种二叉树并没有深入的理解,或者完全被国产数据结构教科书所误导(只听说过满二叉树和完全二叉树)的朋友不妨花点时间耐着性子将本文仔细阅读N(>=1)遍。 1. 树(Tree)的基本概念 1.1 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 478,741
精华内容 191,496
关键字:

二叉树