0
点赞
收藏
分享

微信扫一扫

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

目录

二叉树定义

二叉树图解

特殊的二叉树

二叉树的性质

二叉树的基本代码实现

二叉数的定义

二叉树的输入(创建)

二叉树的遍历

二叉树的深度优先遍历

二叉树的广度优先遍历

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

返回宽度和深度

深度

宽度

返回节点个数

返回二度节点

返回一度节点

返回叶子节点(0度)

返回空节点(NULL)

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

翻转二叉树

二叉树性质的判断

完全二叉树

平衡二叉树

对称二叉树

单值二叉树


树的介绍

二叉树定义

二叉树图解

特殊的二叉树

完全二叉树:

满二叉树:

二叉搜索树:

二叉平衡树(AVL):

B树,B+树:

红黑树:

二叉树的性质

(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);
}

举报

相关推荐

0 条评论