一、树的定义
树(tree)是n(n>=0)个结点的有限集。
若n==0,称为空树。
若n>0,则满足如下条件:
1)有且仅有一个特色的称为根(root)的结点
2)其余结点可分为m(m>=0)个互不相交大的有限集T1,T2……Tn.集中每个集合本身又是一棵树,并称为根的子树(subTree)
根结点:非空树中无前驱结点的结点
结点的度:结点拥有子树的个数
叶结点:度为0的结点
树的度:树内各结点的度的最大值
子结点:一个结点含有的子树的根结点称为子结点,如上图B是A的子结点。
父结点:若一个结点含有子结点,则称为该节点是这个子结点的父结点。如上图A是B的父结点。
结点的层次:从根开始定义为第一层,根的子结点为第二层。
树的高度或者深度:树中结点的最大层次,如上图:高度为3.
森林:是m(m>=0)棵树互不相交的树的集合。
二、二叉树的概念
二叉树:每个结点最多只有两个叉的树,分别称为这个根的左子树与右子树。
二叉树的性质:
1)在二叉树的第i层至多有2^(i-1)个结点(i>=0)
2)在深度为k的二叉树至多有2^k-1
3)对任何一颗二叉树T,如果叶子数为n,度为2的结点数为n2,则n=n2+1
特殊的二叉树
1)满二叉树:一颗深度为k,且有2^k-1个结点的二叉树,称为满二叉树。其中的特征有每层都满,叶子结点全部在最底层。
2)完全二叉树:深度为k的具有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号1~n的结点一一对应.
二叉树的存储结构
1)顺序存储结构:按满二叉树的结点层次编号,依次存放二叉树中数据元素。
2)链式存储结构
三、二叉树的基本操作与实现
#pragma once
#include<iostream>
#include<malloc.h>
#define MaxSize 100
typedef int Elemtype;
using namespace std;
//首先讲的是顺序存储表示方式
//结点的结构
typedef struct BiNode {
int data;
struct BiNode* lchild, * rchild;
}BiNode,*Bitree;
//二叉树的建立
BiNode *CreateBitree() { //一级指针建立二叉树
Bitree T;
int ch;
cin >> ch; //输入一个值
if (ch ==0) { //如果ch这个数并没有输入
T = NULL; //根结点为空
}
else {
(T) = (BiNode*)malloc(sizeof(BiNode));
(T)->data = ch;
T->lchild=CreateBitree(); //构建左子树
T->rchild=CreateBitree(); //构建右子树
}
return T;
}
//遍历二叉树
/*遍历思想:顺着某一条搜索路径寻访二叉树的结点,是每个结点都被访问一遍*/
//方法1:先序
void Pre(Bitree T) {
if (T) {
cout << T->data;
Pre(T->lchild);
Pre(T->rchild);
}
}
/*
int PreorderTraverse(Bitree T) {
if (T == NULL) {
cout << "空";
}
else {
visit(T);
PreorderTraverse(T->lchild);
PreorderTraverse(T->rchild);
}
}*/
//计算二叉树的深度
/*思想:如果是空树深度为0,否则递归计算左子树的深度为m,右子树为n,然后二者比较大小,大的加1*/
int Depth(Bitree T){
if (T == NULL) {
return 0;
}
else {
int m = Depth(T->lchild);
int n = Depth(T->rchild);
if (m > n)
return m + 1;
else
return n + 1;
}
}
//计算结点的总数
/*思想:如果是空树,结点为0;否则结点个数左子树的结点的个数加上右子树的结点个数再加1*/
int Nodenumber(Bitree T) {
if (T == NULL) {
return 0;
}
else {
return Nodenumber(T->rchild) + Nodenumber(T->lchild) + 1;
}
}
//计算叶子结点数
//思想:叶子结点为0时,时空树;否则存在叶子结点
int Leadcount(Bitree T) {
if (T == NULL) {
return 0;
}
if (T->lchild == NULL && T->rchild == NULL) {
return 1;
}
else return Leadcount(T->lchild) + Leadcount(T->rchild);
}
//复制二叉树
//思想;如果是空树,递归结束;否则,申请新结点空间,复制根结点,递归左子树,递归右子树
void Copy(Bitree T, Bitree &T1) {
if (T == NULL) {
T1 = NULL;
}
else {
T1 = new BiNode;
T1->data = T->data;
Copy(T->lchild, T1->lchild);
Copy(T->rchild, T1->rchild);
}
}
#include "Btree.h"
int main() {
Bitree T;
T = NULL;
int i = 0;
T=CreateBitree();
Pre(T);
cout << "\n";
cout<<Depth(T)<<"\n";
cout << Nodenumber(T);
return 0;
}
建立二叉树的方法
1.一级指针,见上面的代码
2、二级指针
void CreateBitree(BiNode** T){
int ch;
cin>>ch;
if(ch==0)
(*T)=NULL;
else{
(*T)=(BiNode*)malloc(sizeof(BiNode));
(*T)->data=ch;
CreateBitree(&(*T)->lchild);
CreateBitree(&(*T)->rchild);
}
}
3、引用方式
void CreateBitree(BiNode* &T){
int ch;
cin>>ch;
if(ch==0)
T=NULL;
else{
(T)=(BiNode*)malloc(sizeof(BiNode));
(T)->data=ch;
CreateBitree((T)->lchild);
CreateBitree((T)->rchild);
}
}
四、拓展知识
引用:引用是给已存在变量取一个别名,它和它引用的变量共用一块内存空间。一旦一个变量被引用,就不能重新赋值(引用的地址不可以改变)
#include<stdio.h>
int main(){
int a=1;
int &c=a; //引用。将c作为a的别名
printf("%d\n",c) ;
printf("%d %d",&c,&a);//a c的地址
return 0;
}
/*这些是我看网课总结的,在写二叉树建立的时候发现了一些错误,我就查了一些资料拓展了一些知识。如果你们觉得有可以完善的地方,我很乐意去倾听并修改,感觉一个人在家,都变话痨了,好的,谢谢支持!*/