您现在的位置是:首页 >技术杂谈 >【数据结构】树,二叉树,满二叉树,完全二叉树的定义和二叉树的基本操作网站首页技术杂谈

【数据结构】树,二叉树,满二叉树,完全二叉树的定义和二叉树的基本操作

在下小吉. 2024-06-17 10:47:09
简介【数据结构】树,二叉树,满二叉树,完全二叉树的定义和二叉树的基本操作

?专栏【数据结构

?喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。

?音乐分享【勋章

大一同学小吉,欢迎并且感谢大家指出我的问题?

目录

⭐树

?️‍?定义

 ?️‍?注意

?树的基本术语

⭐二叉树

?️‍?定义

?二叉树和树的区别

?️‍?二叉树的性质

⭐满二叉树

⭐完全二叉树

?遍历二叉树

?先序遍历二叉树

?中序遍历二叉树

?后序遍历二叉树

?构建二叉树

?算法步骤

?代码

?复制二叉树

?算法步骤

?代码

?计算二叉树的深度

?算法步骤

?代码

?统计二叉树中结点的总数

?算法步骤

?代码

?统计二叉树中叶子结点的个数

?算法步骤

?代码

?完整代码 


 

⭐树

?️‍?定义

树是n(n>=0)个结点的有限集

n=0:称为空树

n>0:称为非空树

✨对于非空树,有下面两个特点

(1)有且只有一个称为根的结点

(2)除根节点之外的其余结点可以分为m(m>0)个互不相交的有限集,对于每一个有限集本身又是一棵树,并且称为根的子树

树可以有多种表示方法,如下图所示 

 ?️‍?注意

如下图所示

 

?树的基本术语

结点:树的一个独立单元(比如上图的ABCD)

结点的度:结点拥有的子树(比如上图中,A的度为3,B的度为2)

树的度:树内各结点度的最大值(比如上图的树的度为3)

叶子(终端结点):度为0的结点

层次:结点的层次从根开始定义,根为第一层,根的孩子为第二层

树的深度(高度):树中结点的最大层次

森林:m棵互不相交的树的集合。对于树的每个结点而言,其子树的集合就是森林

⭐二叉树

?️‍?定义

树是n(n>=0)个结点的有限集

n=0:称为空树

n>0:称为非空树

✨对于非空树,有下面两个特点

(1)有且只有一个称为根的结点

(2)除根节点之外的其余结点可以分为2个互不相交的子集,分别称为T的左子树T1和右子树T2,且T1T2都是二叉树

?二叉树和树的区别

?二叉树中不存在度>2的结点?

二叉树的左右子树有左右之分,不能随意颠倒


二叉树也有多种表示方法,如下图所示

 

?️‍?二叉树的性质

?第i层上至多有2^(i-1)(i>=1)个结点

?深度为k的二叉树至多有2^k-1(k>=1)个结点

?对于任何一颗二叉树T,如果其终端结点树为n0,度为2的结点树为n2

那么n0=n2+1

⭐满二叉树

深度为k且有2^k-1个结点的二叉树,每一层的结点数都是最大结点数

⭐完全二叉树

 

深度为k,有n个结点的二叉树,当且仅当每一个结点都与深度为k的满二叉树 中编号从1到n的结点一一对应时,为完全二叉树


文末有完整代码


 

?遍历二叉树

?定义

typedef struct BiNode{				
    char data;
    struct BiNode *lchild,*rchild;
}BiNode,*BiTree;

?先序遍历二叉树

操作定义如下:若二叉树为空,则操作为空;否则
(1)访问根结点;
(2)先序遍历左子树;
(3)先序遍历右子树。

void preorder_traversal(BiTree root) {
    if (!root) {
        return;
    }

    cout << root->data << " "; // 访问根节点
    preorder_traversal(root->lchild); // 递归访问左子树
    preorder_traversal(root->rchild); // 递归访问右子树
}


?中序遍历二叉树

操作定义如下:若二叉树为空,则操作为空;否则
(1)中序遍历左子树;
(2)访问根结点;
(3)中序遍历右子树。

void inorder_traversal(BiTree root) {
    if (!root) {
        return;
    }

    inorder_traversal(root->lchild); // 递归访问左子树
    cout << root->data << " "; // 访问根节点
    inorder_traversal(root->rchild); // 递归访问右子树
}

?后序遍历二叉树

操作定义如下:若二叉树为空,则操作为空;否则
(1)后序遍历左子树;
(2)后序遍历右子树;
(3)访问根结点;

void postorder_traversal(BiTree root) {
    if (!root) {
        return;
    }

    postorder_traversal(root->lchild); // 递归访问左子树
    postorder_traversal(root->rchild); // 递归访问右子树
    cout << root->data << " "; // 访问根节点
}

?构建二叉树

法一:

比如根据  ABC##DE#G##F###  这一段来构建

?算法步骤

1.读取字符序列,读入字符ch

2.如果ch是“#”,表明该二叉树为空树,即T为NULL,否则执行下面的操作

(1)申请一个内存空间T

(2)将ch赋给T->data

(3)递归创建T的左子树

(4)递归创建T的右子树

?代码

void CreateBiTree(BiTree &T){	
	
	char ch;
	cin >> ch;
	if(ch=='#')  T=NULL;			
	else{							
		T=new BiTNode;
		T->data=ch;					//生成根结点
		CreateBiTree(T->lchild);	//递归创建左子树
		CreateBiTree(T->rchild);	//递归创建右子树
	}								
}					

法二:

 // 构建二叉树
    BiTree root = new BiNode{'A', nullptr, nullptr};
    root->lchild = new BiNode{'B', nullptr, nullptr};
    root->lchild->lchild = new BiNode{'C', nullptr, nullptr};
    root->lchild->rchild = new BiNode{'D', nullptr, nullptr};
    root->lchild->rchild->lchild = new BiNode{'E', nullptr, nullptr};
    root->lchild->rchild->lchild->rchild = new BiNode{'G', nullptr, nullptr};
    root->lchild->rchild->rchild = new BiNode{'F', nullptr, nullptr};

?复制二叉树

?算法步骤

1.为空树,递归结束

2.不为空树,那么执行下面的操作

(1)申请一个新结点空间,复制根节点

(2)递归复制左子树

(3)递归复制右子树

?代码

void Copy(BiTree T,BiTree &NewT)
{
	if(T==NULL){
		NweT=NULL;
		return;
	}else{
		NewT=new BiTree;		//复制根节点
		NewT->data=T->data;
		Copy(T->lchild,NewT->lchild);
		Copy(T->rchild,NewT->rchild);
	}
}

?计算二叉树的深度

?算法步骤

1.为空树,递归结束

2.不为空树,那么执行下面的操作

(1)递归计算左子树的深度为m

(2)递归计算右子树的深度为n

(3)如果m>n,那么二叉树深度为m+1,否则为n+1

?代码

int Depth(BiTree T)
{ 
	int m,n;
	if(T == NULL ) return 0;        //如果是空树,深度为0,递归结束
	else 
	{							
		m=Depth(T->lchild);			//递归计算左子树的深度记为m
		n=Depth(T->rchild);			//递归计算右子树的深度记为n
		if(m>n) return(m+1);		//二叉树的深度为m 与n的较大者加1
		else return (n+1);
		//+1,所以可以计算出来
	}
}

?统计二叉树中结点的总数

?算法步骤

如果是空树,那么结点个数为0,递归结束

否则,结点个数=左子树结点个数+右子树结点个数+1

?代码

int NodeCount(BiTree T)
{
     if(T==NULL) return 0;  			// 如果是空树,则结点个数为0,递归结束
     else return NodeCount(T->lchild)+ NodeCount(T->rchild) +1;
     //否则结点个数为左子树的结点个数+右子树的结点个数+1
     
     //+1,所以可以计算出来//
} 

?统计二叉树中叶子结点的个数

?算法步骤

如果是空树,那么结点个数为0,递归结束

否则,遍历到NULL,即叶子节点

?代码

int LeafCount(BiTree T){
 	if(T==NULL) 	//如果是空树返回0
		return 0;
	if (T->lchild == NULL && T->rchild == NULL)
		return 1; //如果是叶子结点返回1
		
		// 1,所以可以计算出来
		
	else return LeafCount(T->lchild) + LeafCount(T->rchild);
}

?完整代码 

#include<iostream>
using namespace std;
typedef struct BiNode{				
	char data;
	struct BiNode *lchild,*rchild;
}BiTNode,*BiTree;


void CreateBiTree(BiTree &T){	
	
	char ch;
	cin >> ch;
	if(ch=='#')  T=NULL;			
	else{							
		T=new BiTNode;
		T->data=ch;					//生成根结点
		CreateBiTree(T->lchild);	//递归创建左子树
		CreateBiTree(T->rchild);	//递归创建右子树
	}								
}									


void PreOrderTraverse(BiTree T)
{  
   if (T) {
      cout<<T->data;            // 访问结点
      PreOrderTraverse(T->lchild); // 遍历左子树
      PreOrderTraverse(T->rchild);// 遍历右子树  
   }
}



void InOrderTraverse(BiTree T){  
	
	if(T){
		InOrderTraverse(T->lchild);
		cout << T->data;
		InOrderTraverse(T->rchild);
	}
}


void PostOrderTraverse(BiTree T)
{ 
   if (T) {
      PostOrderTraverse(T->lchild); // 遍历左子树
      PostOrderTraverse(T->rchild);// 遍历右子树
      cout << T->data;           // 访问结点
    }
}



int NodeCount(BiTree T)
{
     if(T==NULL) return 0;  			// 如果是空树,则结点个数为0,递归结束
     else return NodeCount(T->lchild)+ NodeCount(T->rchild) +1;
     //否则结点个数为左子树的结点个数+右子树的结点个数+1
     
     //+1,所以可以计算出来//
} 


//计算二叉树中叶子结点的个数
int LeafCount(BiTree T){
 	if(T==NULL) 	//如果是空树返回0
		return 0;
	if (T->lchild == NULL && T->rchild == NULL)
		return 1; //如果是叶子结点返回1
		
		// 1,所以可以计算出来
		
	else return LeafCount(T->lchild) + LeafCount(T->rchild);
}


//计算二叉树的深度	
int Depth(BiTree T)
{ 
	int m,n;
	if(T == NULL ) return 0;        //如果是空树,深度为0,递归结束
	else 
	{							
		m=Depth(T->lchild);			//递归计算左子树的深度记为m
		n=Depth(T->rchild);			//递归计算右子树的深度记为n
		if(m>n) return(m+1);		//二叉树的深度为m 与n的较大者加1
		else return (n+1);
		//+1,所以可以计算出来
	}
}

int main(){
	BiTree tree;
	int nodecount=0,leafcount=0,depth=0;
	cout<<"请输入建立二叉链表的序列:
";
	CreateBiTree(tree);
	cout<<endl;
	cout<<"先序遍历的结果为:
";
	PreOrderTraverse(tree);
	cout<<endl;
	cout<<"中序遍历的结果为:
";
	InOrderTraverse(tree);
	cout<<endl;
	cout<<"后序遍历的结果为:
";
	PostOrderTraverse(tree);
	cout<<endl;
	cout<<"该二叉树中结点总数为:";
	cout<<NodeCount(tree)<<endl;
	cout<<"该二叉树中叶子结点总数为:";
	cout<<LeafCount(tree)<<endl;
	cout<<"该二叉树的深度为:";
	cout<<Depth(tree)<<endl;
	return 0;
}

?如果大家有不明白的地方,或者文章有问题,欢迎大家在评论区讨论,指正? 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。