数据结构笔记(6)二叉树的实现

目录

二叉树定义

二叉树图解

特殊的二叉树

二叉树的性质

二叉树的基本代码实现

二叉数的定义

二叉树的输入(创建)

二叉树的遍历

二叉树的深度优先遍历

二叉树的广度优先遍历

二叉树的基本功能函数的实现

返回宽度和深度

深度

宽度

返回节点个数

返回二度节点

返回一度节点

返回叶子节点(0度)

返回空节点(NULL)

二叉树基本特点函数的实现

翻转二叉树

二叉树性质的判断

完全二叉树

平衡二叉树

对称二叉树

单值二叉树


树的介绍

二叉树定义

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分。

二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点。

二叉树图解

特殊的二叉树

完全二叉树:

一棵深度为k的有n个结点的 二叉树 ,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与 满二叉树 中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。.

满二叉树:

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。. 也就是说,如果一个二叉树的层数为K,且结点总数是 (2^k) -1 ,则它就是满二叉树。

二叉搜索树:

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的值; 若它的右子树不空,则右子树上所有结点的值均大于它的值

二叉平衡树(AVL):

平衡树(Balance Tree,BT) 指的是,任意节点的子树的高度差都小于等于1。常见的符合平衡树的有,B树(多路平衡搜索树)、AVL树(二叉平衡搜索树)等。

B树,B+树:

一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树:根结点至少有两个子女;每个非根节点所包含的关键字个数 j 满足:[m/2] - 1 <= j <= m - 1;除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:[m/2] <= k <= m ;所有的叶子结点都位于同一层。

红黑树:

红黑树是每个结点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求: 1.结点是红色或黑色;2.根结点是黑色;3. 所有叶子都是黑色(叶子是NIL结点);4. 每个红色结点的两个子结点都是黑色(从每个叶子到根的所有路径上不能有两个连续的红色结点);5. 从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。  

二叉树的性质

(1):一颗非空二叉树的第n层最多有2^(n-1)个节点

(2):若一颗非空二叉树的深度为h,那么它最多能有2^h-1个节点

(3):具有N个节点的完全二叉树,它的深度h=ceil(㏒₂(N+1))ceil表示向上取整,例如ceil(2.23)=ceil(2.64)=ceil(3)=3

★(4):一颗二叉树,2度节点和叶子节点(度为0)满足以下关系:D₀=D₂+1 也就是说叶子节点个数始终等于二度节点个数加一

★(5):一颗二叉树,若他的节点个数是2n个,那么他的叶子节点个数为n

二叉树的基本代码实现

二叉数的定义

二叉树通常采用孩子表示法,因此定义的代码为:

//定义二叉树
typedef struct BTNode {
	char data;//数据域
	BTNode* left;//指向左孩子节点
	BTNode* right;//指向右孩子节点
}BinaryTree;
/*该结构体有两个名字
分别翻译为节点(BTNode),二叉树(BinaryTree)加以区分
*/

二叉树的输入(创建)

由于二叉树是一对多结构,我们无法得知某某数据,它具体是谁的孩子节点,因此使得它不能像链表这样循环输入,而只能递归回溯输入。

所以涉及到回溯算法

★★★二叉树包含大量的回溯算法

回溯算法初步介绍

回溯算法,又称为“试探法”。解决问题时,每进行一步,都是抱着试试看的态度,如果发现当前选择并不是最好的,或者这么走下去肯定达不到目标,立刻做回退操作重新选择。这种走不通就回退再走的方法就是回溯算法。

二叉树创建代码:

//创建二叉树
void  BTCreate(BinaryTree* &root) {
	BTNode *q; //创建新节点
	q=new BTNode;//初始化节点,相当于malloc函数
	cin>>q->data;//输入数据
	if(q->data=='#') {//判断是否为'#"
		root=q=NULL; //若是,则设置虚拟节点q,并接到二叉树上
		return; //返回上一个节点
	}
    root=q; //若否,则将节点q接在二叉数上
	BTCreate(root->left); //进入左孩子
	BTCreate(root->right); //进入右孩子
	return; //返回上一个节点
}

二叉树创建图解

  

以上就是二叉树:ABC##D###的创建过程。

主要还是回溯算法,当创建了空节点的时候,就回溯返回上一个节点,不再递归分治。 

二叉树的遍历

二叉树的深度优先遍历

前序遍历,又叫先根遍历。遍历顺序:根 - > 左孩子 - >右孩子。

//前序遍历
void BTProOrder(BinaryTree* &root) {
    if(root==NULL) return;
    cout<<root->data<<" ";
    BTProOrder(root->left);
    BTProOrder(root->right);
}

中序遍历,又叫中根遍历。遍历顺序:左孩子 -> 根 -> 右孩子

//中序遍历
void BTInOrder(BinaryTree* &root) {
    if(root==NULL) return;
    BTInOrder(root->left);
    cout<<root->data<<" ";
    BTPostOrder(root->right);
}

后序遍历,又叫后根遍历。遍历顺序:左孩子 -> 右孩子 -> 根

//后序遍历
void BTPostOrder(BinaryTree* &root) {
    if(root==NULL) return;
    BTPostOrder(root->left);
    BTPostOrder(root->right);
    cout<<root->data<<" ";
}

二叉树的广度优先遍历

层序遍历。顾名思义,就是按照树的层次,从第1层到第n层,从上到下,从左到右进行遍历输出。

像这样,就是层序遍历。

//层序遍历
void BTLevelOrder(BinaryTree* &root) {
    queue<BinaryTree*>Q;
    Q.push(root);
    BTNode *q;
    while(!Q.empty()) {
        cout<<Q.front()->data;
        q=Q.front();
        Q.pop();
        if(q->left!=NULL) Q.push(q->left);
        if(q->right!=NULL) Q.push(q->right);
    }
}

二叉树的基本功能函数的实现

返回宽度和深度

深度

返回深度介绍 

int Height(BinaryTree* &root) {
    if(root==NULL) return 0;
    else return max(Height(root->left),Height(root->right))+1;//左子树或者右子树的最大值
}//max(a,b):返回a,b的最大值

宽度

返回宽度介绍 

int a[10005];//数组a表示储存第key层有几个节点
//key表示第几层,刚开始key为1,也就是第一层
//ans表示最终答案
void Wide(BinaryTree* &root,int key,int &ans) {
    if(root==NULL) return;
    else {
        a[key]++;
        ans=max(ans,a[key]);
        Wide(root->left,key+1,ans);
        Wide(root->right,key+1,ans);
    }
}

返回节点个数

返回二度节点

int node_two(BinaryTree* &root) {
    if(root==NULL) return 0;
    //同时搜索左右孩子节点
    //当左右孩子节点都不为空,说明是2度节点,值加一
    if(root->left!=NULL&&root->right!=NULL) return node_two(root->left)+node_two(root->right)+1;
    //否则直接搜索
    else return node_two(root->left)+node_two(root->right);
}

返回一度节点

int node_one(BinaryTree* &root) {
    if(root==NULL) return 0;
    //同时搜素左右孩子节点
    //当左右孩子节点有一个不为空,一个为空,说明是1度节点,值加一
    if(root->left!=NULL&&root->right==NULL || root->right!=NULL&&root->left==NULL) return node_one(root->left)+node_one(root->right)+1;
    //否则直接搜索
    else return node_one(root->left)+node_one(root->right);
}

返回叶子节点(0度)

int node_zero(BinaryTree* &root) {
    if(root==NULL) return 0;
    //同时搜素左右孩子节点
    //当左右孩子节点都为空,说明是0度节点,返回1
    if(root->left==NULL && root->right==NULL) return 1;
    //否则直接搜索
    else return node_zero(root->left)+node_zero(root->right);
}

返回空节点(NULL)

int node_NULL(BinaryTree* &root) {
    //当该节点为空,返回1
    if(root=NULL) return 1;
    //否则搜索左右孩子
    else return node_NULL(root->left)+node_NULL(root->right);
}

二叉树基本特点函数的实现

翻转二叉树

翻转二叉树可以先镜面先序遍历(根->右孩子->左孩子),并储存。然后再依次先序创建之前储存的镜面先序遍历

//创建翻转二叉树
char node[10005];
int sum2=0;
void create(BinaryTree* &root) {
    BTNode *q;
    q=new BTNode;
    q->data=node[sum2++];
    if(q->data=='#') {
        root=q=NULL;
        return;
    }
    root=q;
    create(root->left);
    create(root->right);
}
//镜面先序遍历
int sum1=0;
void sy_BTProOrder(BinaryTree* &root) {
    if(root==NULL) {
        node[sum1++]='#';
        return;
    }
    node[sum1++]=root->data;
    sy_BTProOrder(root->right);
    sy_BTProOrder(root->left); 
}

二叉树性质的判断

完全二叉树

判断是否为完全二叉树,根据定义,和宽度优先遍历(层序遍历)有点类似

bool isCompleteTree(BinaryTree* &root) {
    queue<BinaryTree*>Q;
    Q.push(root);  
    BTNode *q;
    while(!Q.empty()) {
        if(Q.front()==NULL) break;
        q=Q.front();
        Q.pop();
        Q.push(q->left);
        Q.push(q->right);
    }
    while(!Q.empty()) {
        if(Q.front()!=NULL) return false;
        Q.pop();
    }
    return true;
}

平衡二叉树

根据定义,判断左右子树深度的绝对值之差,若不大于1,并且左右子树也为平衡二叉树,则该树为平衡二叉树。

//求二叉树深度
int depth(BinaryTree* &root) {
    if(root==NULL) return 0;
    else return max(depth(root->left),depth(root->right))+1;
}
//判断是否为平衡二叉树
bool isBalanced(BinaryTree* &root) {
    if(root==NULL) return true;
    int leftDepth=depth(root->left);
    int rightDepth=depth(root->right);
    if(abs(leftDepth-rightDepth)>1) return false;
    //判断左右子树是否也为平衡二叉树
    return isBalanced(root->left) && isBalanced(root->right);
}

对称二叉树

就像照镜子一样,从根开始。整两个遍历轴,一个往左遍历,一个往右遍历,形成镜面对称。

若其中有不同,那么结束遍历,返回false。

//两个遍历轴,遍历函数
bool symmetry(BinaryTree* &rootL,BinaryTree* &rootR) {
    if(rootL==NULL&&rootR==NULL) return true;
    if(rootL==NULL||rootR==NULL) return false;
    if(rootL->data!=rootR->data) return false;
    else return (rootL->left,rootR->right) && (rootL->right,rootR->left);
}
//主判断函数
bool isSymmetryTree(BinaryTree* &root) {
    if(root==NULL) return true;
    return symmetry(root->left,root->right);
}

单值二叉树

单值二叉树是指所有节点的data都一样

bool isUnivalTree(BinaryTree* &root) {
    if(root==NULL) return true;
    if(root->data != root->left->data) return false;
    if(root->data != root->right->data) return false;
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是孤衾呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值