/*
1.节点:节点包含一个数据元素和若干点到其子树分支
2.度节点:节点的数目已成为节点的子树
3.叶节点:为0的节点称为叶结点
4.分支节点:度不为0的节点称为分支节点
5.树的度:树中全部节点的度的最大值
6.二叉树:是n(n>=0)个有限节点构成的集合。n=0的树称为空二叉树。n=1的树仅仅有一个根结点;
n〉1的二叉树由一个根节点和至多两个互不相交的,分别称为左子树和右子树的子二叉树构成
二叉树不是有序树,这是由于,二叉树中某个节点即使仅仅有一个子树也要区分是左子树还是右子树;
而对于有序树来说。假设某个节点仅仅有一个子树就必然是第一个子树
7.二叉树全部结点的形态有5种:空节点,无左右子树节点,仅仅有左子树节点。仅仅有右子树节点和左右子树均存在的节点
8.满二叉树:在一棵二叉树中。假设全部分支节点都存在左子树和右子树,而且全部叶子节点都在同一层,则这种二叉树称作满二叉树
9.全然二叉树:假设一颗具有n个节点的二叉树的结构与满二叉树的前n个节点的结构同样,这种二叉树称为全然二叉树
10二叉树的性质:
(1):若规定根节点的层数为0,则一棵非空二叉树的第i层上最多有2^i(i>=0)个节点
(2):
若规定仅仅有根节点的二叉树的深度为0,则深度为k的二叉树的最大节点数是2^(k+1)-1(k>=-1)
(3):
对于一棵非空的二叉树。假设叶节点个数为n0,度为2的节点个数为n2。则有n0=n2+1
(4):
具有n个节点的全然二叉树的深度k为大于或等于ln(n+1)-1的最小整数
(5):
对于具有n个节点的全然二叉树,假设依照从上至下和从左至右的顺序对全部节点序号从0開始顺序编号,则对于序号为i(0<=i<n)的节点有:
假设i〉0。则序号为i节点的双亲节点的序号为(i-1)/2(/为整除);假设i=0。则序号为i节点为根节点,无双亲节点
假设2i+1<n,则序号为i节点的左孩子节点的序号为2i+1;假设2i+1>=n,则序号为i节点无左孩子
假设2i+2<n,则序号为i节点的右孩子节点的序号为2i+2;假设2i+2>=n。则序号为i节点无右孩子
11.二叉树的存储结构
1.二叉树的顺序存储结构
利用性质5,对于全然二叉树能够利用一维数组存储,假设不是全然二叉树。则能够补空节点,使成为全然二叉树在进行存储,
可是对于非全然二叉树,可能要浪费非常多的空间。
2.二叉树的链式存储结构
二叉树的链式存储结构就是用指针建立二叉树中节点之间的关系,二叉树最经常使用的链式存储结构是二叉链。二叉树的二叉链存储结构是一种经常使用的
二叉树存储结构。
二叉链存存储结构的长处时。结构简单。能够方便的构造不论什么形状的二叉树。并能够方便的实现二叉树的大多数操作。
二叉链存储结构的缺点是,查找当前节点的双亲节点操作实现比較麻烦
3.二叉树的仿真指针存储结构
利用一维数组和结构体实现。利用数组的下标进行仿真指针进行二叉树的操作
*/
<span style="font-size:18px;">#include<stdio.h> #include<malloc.h> typedef char DataType; typedef struct Node{ DataType data;//数据域 struct Node *leftChild;//左子树指针 struct Node *rightChild;//右子树指针 }BiTreeNode;//节点的结构体定义 //初始化 void Initiate(BiTreeNode **root){ *root=(BiTreeNode *)malloc(sizeof(BiTreeNode)); (*root)->leftChild=NULL; (*root)->rightChild=NULL; } //左插入节点 //若当前节点curr非空。则在curr的左子树插入元素值为x的新节点 //原curr所指节点的左子树成为新插入节点的左子树 //若插入成功。则返回新插入节点的指针,否则返回空指针 BiTreeNode *InsertLeftNode(BiTreeNode *curr,DataType x){ BiTreeNode *s,*t; if(curr==NULL){//推断当前节点是否为空 return NULL;//是空则返回NULL } t=curr->leftChild;//保存原curr所指节点的左子树 s=(BiTreeNode *)malloc(sizeof(BiTreeNode));//创建节点空间 s->data=x;//赋值 s->leftChild=t;//新插入节点的左子树为原curr的左子树 s->rightChild=NULL;//右子树为空 curr->leftChild=s;//新节点成为curr的左子树 return curr->leftChild;//返回新插入节点的指针 } //右插入节点 //若当前节点curr非空。则在curr的右子树插入元素值为x的新节点 //原curr所指节点的右子树成为新插入节点的右子树 //若插入成功,则返回新插入节点的指针,否则返回空指针 BiTreeNode *InsertRightNode(BiTreeNode *curr,DataType x){ BiTreeNode *s,*t; if(curr==NULL){//推断当前节点是否为空 return NULL;//是空则返回NULL } t=curr->rightChild;//保存原curr所指节点的右子树 s=(BiTreeNode *)malloc(sizeof(BiTreeNode));//创建节点空间 s->data=x;//赋值 s->rightChild=t;//新插入节点的右子树为原curr的右子树 s->leftChild=NULL;//右子树为空 curr->rightChild=s;//新节点成为curr的右子树 return curr->rightChild;//返回新插入节点的指针 } //左删除子树 //若curr非空,则删除curr所指节点的左子树 //若删除成功,则返回删除节点的双亲节点。否则返回空指针 BiTreeNode *DeleteLeftTree(BiTreeNode *curr){ //假设当前节点为空或者左子树为空则返回NULL if(curr==NULL||curr->leftChild==NULL){ return NULL; } //释放节点 //Destroy(&curr->leftChild); curr->leftChild=NULL;//删除后,当前节点的左子树为NULL return curr;//返回删除节点的双亲节点 } //右删除子树 //若curr非空。则删除curr所指节点的右子树 //若删除成功,则返回删除节点的双亲节点,否则返回空指针 BiTreeNode *DeleteRightTree(BiTreeNode *curr){ //假设当前节点为空或者右子树为空则返回NULL if(curr==NULL||curr->rightChild==NULL){ return NULL; } //释放节点 // Destroy(&curr->rightChild); curr->rightChild=NULL;//删除后,当前节点的右子树为NULL return curr;//返回删除节点的双亲节点 } void Visit(DataType item){ printf("%c ",item); } //前序遍历 /* 1.訪问根节点 2.前序遍历根节点的左子树 3.前序遍历根节点的右子树 */ void PreOrder(BiTreeNode *root,void Visit(DataType item)){ //前序遍历二叉树root,訪问操作为Visit()函数 if(root!=NULL){ Visit(root->data);//訪问数据 PreOrder(root->leftChild,Visit);//訪问左子树 PreOrder(root->rightChild,Visit);//反问右子树 } } //中序遍历 /* 1.中序遍历根节点的左子树 2.訪问根节点 3.中序遍历根节点的右子树 */ void InOrder(BiTreeNode *root,void Visit(DataType item)){ //中序遍历二叉树root,訪问操作为Visit()函数 if(root!=NULL){ InOrder(root->leftChild,Visit);//訪问左子树 Visit(root->data);//訪问数据 InOrder(root->rightChild,Visit);//訪问右子树 } } //后序遍历 /* 1.后序遍历根节点的左子树 2.后序遍历根节点的右子树 3.訪问根节点 */ void PostOrder(BiTreeNode *root,void Visit(DataType item)){ //中序遍历二叉树root,訪问操作为Visit()函数 if(root!=NULL){ PostOrder(root->leftChild,Visit);//訪问左子树 PostOrder(root->rightChild,Visit);//訪问右子树 Visit(root->data);//訪问根节点数据 } } //撤销二叉树操作 void Destroy(BiTreeNode **root){ if((*root)!=NULL&&(*root)->leftChild!=NULL){ Destroy(&(*root)->leftChild); } if((*root)!=NULL&&(*root)->rightChild!=NULL){ Destroy(&(*root)->rightChild); } free(*root); } void PrintBiTree(BiTreeNode *root,int n){ //逆时针旋转90度。打印二叉树root。n为缩进层数,初始值为0 int i; if(root==NULL){ return ;//递归出口 } PrintBiTree(root->rightChild,n+1);//遍历打印右子树 //訪问根节点 for(i=0;i<n-1;i++){ printf(" "); } if(n>0){ printf("---"); printf("%c ",root->data); } PrintBiTree(root->leftChild,n+1);//遍历打印右子树 } //查找数据元素 BiTreeNode *Search(BiTreeNode *root,DataType x){ //查找数据元素x是否在二叉树root中 //查找到则返回该节点指针。未查找到则返回空指针 BiTreeNode *find=NULL; if(root!=NULL){ if(root->data==x){ find=root; }else{ find=Search(root->leftChild,x);//在左子树中找 if(find==NULL){ find=Search(root->rightChild,x);//在右子树中找 } } } return find;//返回查找标志 } void main(){ BiTreeNode *root,*p,*find; char x='E'; Initiate(&root);//初始头指针 p=InsertLeftNode(root,'A');//在头结点插入左子树 p=InsertLeftNode(p,'B');//给'A'插入左子树 p=InsertLeftNode(p,'D');// p=InsertRightNode(p,'G');// p=InsertRightNode(root->leftChild,'C');//给'A'插入右子树 InsertLeftNode(p,'E');// InsertRightNode(p,'F');// PrintBiTree(root,0);//旋转90度打印树 printf("前序遍历:"); PreOrder(root->leftChild,Visit); printf(" 中序遍历:"); InOrder(root->leftChild,Visit); printf(" 后序遍历:"); PostOrder(root->leftChild,Visit); find=Search(root,x); if(find!=NULL){ printf(" 数据元素%c在二叉树中 ",x); }else{ printf(" 数据元素%c不在二叉树中 ",x); } Destroy(&root); }</span>