二叉树的链式存储结构:
//二叉树的链式存储
typedef struct BiTNode{
int data;//用于存储二叉树结点的值
struct BiTNode *lchild, *rchild;//两个二叉树结点指针分别二叉树的左孩子和右孩子
}BiTNode,*BiTree;
函数:先序遍历的顺序建立二叉树
输入:二叉树的结构体变量地址:BiTree &T。其成员是int data;(用于存储二叉树结点的值)struct BiTNode *lchild, *rchild;(两个二叉树结点指针分别二叉树的左孩子和右孩子)。
输出:无
优化目标:无,但我这里是以先序遍历的创建的二叉树,还可以使用中序遍历和后序遍历的方法创建
//先序遍历的顺序建立二叉树
void CreateBiTree(BiTree &T){
int ch;
if(ch == -1){
T =NULL;
}
else{
T = (BiTNode *)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
该函数的思想,主要是要明白先序(或中序、后序)遍历方法,首先判断要创建的结点是否为叶子结点,如果不是,就为该结点创建分配空间,然后就依次对其左孩子和右孩子以相同的方法创建。
函数:计算二叉树的深度
输入:二叉树的结构体变量:BiTree T。其成员是int data;(用于存储二叉树结点的值)struct BiTNode *lchild, *rchild;(两个二叉树结点指针分别二叉树的左孩子和右孩子)。
输出:树的深度
优化目标:无
//计算二叉树的深度
int Depth(BiTree T){
if(T == NULL){
return 0;
}
else{
int m = Depth(T->lchild);
int n = Depth(T->rchild);
if(m<n){
return n+1;
}
else{
return m+1;
}
}
}
该函数的思想:主要是通过递归,如果T不为空,就去递归调用该函数(其左孩子和右孩子)然后,比较两个哪个大,最大的就是该层的深度-1,所以返回最大的+1,最后就可以返回树的深度。
函数:复制二叉树
输入:一个二叉树的结构体变量:BiTree T。其成员是int data;(用于存储二叉树结点的值)struct BiTNode *lchild, *rchild;(两个二叉树结点指针分别二叉树的左孩子和右孩子)。
另一个二叉树的结构体变量地址:BiTree &NewT。其成员是int data;(用于存储二叉树结点的值)struct BiTNode *lchild, *rchild;(两个二叉树结点指针分别二叉树的左孩子和右孩子)。
输出:无
优化目标:无,同样我这里是以先序遍历的去遍历二叉树的同时进行复制,还可以使用中序遍历和后序遍历的方法复制
//复制二叉树
void Copy(BiTree T,BiTree &NewT){
if(T == NULL){
NewT = NULL;
return;
}
else{
NewT = (BiTNode *)malloc(sizeof(BiTNode));
NewT->data = T.data;
Copy(T->lchild,NewT->lchild);
Copy(T->rchild,NewT->rchild);
}
}
该函数的思想:就是在对该二叉树进行遍历的过程中,对二叉树一个结点一个结点的复制。
函数:几个统计函数,统计二叉树中结点、叶子结点、度为1、度为2的结点数量
输入:一个二叉树的结构体变量:BiTree T。其成员是int data;(用于存储二叉树结点的值)struct BiTNode *lchild, *rchild;(两个二叉树结点指针分别二叉树的左孩子和右孩子)。
输出:分别计算出二叉树中结点、叶子结点、度为1、度为2的结点的数量
优化目标:无
//统计二叉树中结点的个数
int NodeCount(BiTree T){
if(T == NULL){
return 0;
}
else{
return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
}
}
//统计二叉树中叶子结点的个数
int LeafCount(BiTree T){
if(T->lchild == NULL && T->rchild == NULL){
return 1;
}
else{
return LeafCount(T->lchild) + LeafCount(T->rchild);
}
}
//统计二叉树中度为1的结点的个数
int OneCount(BiTree T){
if(T == NULL){
return 0;
}
if((T->lchild == NULL && T->rchild != NULL) || (T->rchild == NULL &&T->lchild != NULL)){
return OneCount(T->lchild) + OneCount(T->rchild) + 1;
}
else{
return OneCount(T->lchild) + OneCount(T->rchild);
}
}
//统计二叉树中度为2的结点的个数
int TwoCount(BiTree T){
if(T == NULL){
return 0;
}
if(T->rchild != NULL && T->lchild != NULL){
return TwoCount(T->lchild) + TwoCount(T->rchild) + 1;
}
else{
return TwoCount(T->lchild) + TwoCount(T->rchild);
}
}
该函数的思想:就是利用递归,判断其是否为对应的结点,然后返回其左右孩子同样类型的结点树+1,就可以完成了。
函数:二叉树的先序和中序遍历
输入:一个二叉树的结构体变量:BiTree T。其成员是int data;(用于存储二叉树结点的值)struct BiTNode *lchild, *rchild;(两个二叉树结点指针分别二叉树的左孩子和右孩子)。
输出:无(但在遍历的过程中会将二叉树中的结点进行输出)
优化目标:无(是昨天递归的先序和中序遍历的优化)
//先序遍历(非递归)
void PreOrder(BiTree T){
InitStack(S);
BiTNode *p = T;
while(p!=NULL || !IsEmpty(S)){
if(p != NULL){
printf("%d ",p->data);
Push(S,p);
p = p->lchild;
}
else{
Pop(S,p);
p = p->rchild;
}
}
}
//中序遍历(非递归)
void InOder(BiTree T){
InitStack S;
BiTNode *p = T;
while(p!=NULL || !IsEmpty(S)){
if(p != NULL){
Push(S,p);
p = p->lchild;
}
else{
Pop(S,p);
printf("%d ",p->data);
p = p->rchild;
}
}
}
该函数的思想:利用栈的先进后出的特性写的,当我们遍历到一个结点的时候,就将其压入栈中,只要栈不空或p不为空的时候说明p还在遍历二叉树。此时如果是先序遍历的话,如果p不为空意思是p是二叉树的结点,然后将p的值输出,再将p压入栈中,p再往左孩子结点走,如果p为空,意思是已经p走到空结点了,就要往回走了,让p等于栈的最后一个结点,往该结点的右孩子结点走,然后依次先访问左孩子结点,然后访问右孩子结点,以至于访问完所有结点。而中序遍历与先序遍历类似,只是中序是在p走到空的时候,往回走的pop之后进行输出。
函数:层次遍历
输入:一个二叉树的结构体变量:BiTree T。其成员是int data;(用于存储二叉树结点的值)struct BiTNode *lchild, *rchild;(两个二叉树结点指针分别二叉树的左孩子和右孩子)。
输出:无
优化目标:无
//层次遍历(非递归)
void LevelOrder(BiTree T){
InitQueue(Q);
BiTNode *p = T;
EnQueue(Q,p);
while(!IsEmpty(S)){
DeQueue(Q,p);
printf("%d ",p->data);
if(p->lchild!=NULL){
EnQueue(Q,p->lchild);
}
if(p->rchild!=NULL){
EnQueue(Q,p->rchild);
}
}
}
函数思想:利用队列的先进先出的特性,先将首结点入队,再依次对队列的结点出队后输出,然后依次将该结点的左孩子和右孩子入队,当队列为空的时候就结束了。
今天主要是复习了一下二叉树的几个函数,在对非递归的遍历先看了别人的遍历,然后自己去写,主要是原本知道要用栈和队列,但是还以为对于栈和队列内的值是一个整型,结果是要存储二叉树的结点,所以还是需要再多学习学习。明天的打算是去做一下哈夫曼树。