树和二叉树
主要结构体定义
typedef struct BitNode
{
int/*elemtype*/ data;
struct BitNode *lchild,*rchild;
}BitNode,*BiTree;
void visit(BitNode x)
{
cout<<x->data;
}
typedef struct Linknode
{
int data;
Linknode *next;
}Linknode;
//队列定义
typedef struct {
Linknode *front ,*rear;
}Linkqueue;
先中后序遍历
//先序遍历
void Preorder(BiTree T)
{
if(T!=NULL)
{
visit(T);
Preorder(T->lchild);
Preorder(T->rchild);
}
}
//中序遍历
void Inorder(BiTree T)
{
if(!T)
{
Inorder(T->lchild);
visit(T);
Inorder(T->rchild);
}
}
//后序遍历
void lastorder(BiTree T)
{
if(!T)
{
lastorder(T->lchild);
lastorder(T->rchild);
visit(T);
}
}
求树的深度
int treeDepth(BiTree T)
{
if(!T)
return 0;
else
{
int l=treeDepth(T->lchild);
inr r=treeDepth(T->rchild);
//树的深度等于max(左子树的深度,右子树的深度)+1
return l>r?l+1:r+1;
}
}
二叉树的层次遍历,使用队列作为辅助,算法思想主要是分为以下四个步骤
1: 初始化一个辅助队列
2:根节点入队
3:若队列非空,则队头节点出队,访问该节点,然后将该节点的左右孩子入队
4:重复3一直到队列为空
void levelorder(BiTree T)
{
Linkqueue Q;
initQueue(Q);//初始化辅助队列
BiTree P;
EnQueue(Q,T);//根节点入队
while(!IsEmpty(Q))
{
DeQueue(Q,P);
visit(p);
if(p->lchild!=NULL)
EnQueue(Q,p->lchild);
if(p->rchild!=NULL)
EnQueue(Q,p->rchild);
}
}
线索二叉树的存储结构
线索二叉树结点定义
typedef struct ThreadNode
{
int data;
struct ThreadNode *lchild,*rchild;
int ltag,rtag;//左右线索标志
}ThreadNode,*ThreadTree;
tag=0表示指针指的是孩子
tag=1,表示指针指的是线索
中序线索二叉树
//全局变量pre,指向当前访问节点的前驱
ThreadNode *pre=NULL;
void CreateInthread(BiTree T)
{
pre=NULL;
Inthread(T);//中序线索化二叉树
if(pre->rchild==NULL)
pre->rtag=1;//处理遍历的最后一个结点
}
//中序遍历二叉树,一边遍历一边线索化
void Inthread(ThreadTree T)
{
if(T!=NULL)
{
Inthread(T->lchild);
threadvisit(T);
Inthread(T->rchild);
}
}
void threadvisit(ThreadNode *q)
{
if(q->lchild==NULL)
{
//如果左子树是空,建立前驱线索
q->lchild=pre;
q->ltag=1;
}
if(pre!=NULL&&pre->rchild==NULL)
{
//建立前驱结点的后继线索
pre->rchild=q;
pre->rtag=1;
}
pre=q;
}
question:为什么处理遍历的最后一个结点的时候,没有判断rchild是否是NULL?
中序遍历的最后一个结点的右孩子指针必然是空
先序线索化
先序线索化存在一种转圈的问题需要格外注意