二叉树的创建
- 在创建这个树时一定要以数据形式创建,若以指针形式创建,则该树一直是地址形式,没有具体的数值,在后续操作中也无法对树进行具体值的创建。
typedef struct node
{
char data;
struct node *lchild;
struct node*rchild;
}*PNODE,NODE;
typedef struct TREE
{
PNODE root;
char ref;
}*PTREE,TREE;
void init(PTREE t);
void create1(PTREE ptree,NODE** t);
PNODE create2(PTREE ptree);
PNODE create3(PTREE ptree,char*str)
int main()
{
TREE tree;
init(&tree);
(&tree)->root=create2(&tree);
fronttraverse((&tree)->root);
}
二叉树的创建方法
方法一
- ptree->root本身为PNODE类型,为了改变它的值必须使变量为它的引用类型,即为&(ptree->root),因此形参为PNODE类型,而形参中的t=ptree->root.
void init(PTREE t)
{
t->root=NULL;
t->ref='#';
}
void create1(PTREE ptree,PNODE* t)
{
char item;
scanf("%c",&item);
if(ptree->ref==item)
{
(*t)=NULL;
}
else{
(*t)=(PNODE)malloc(sizeof(NODE));
(*t)->data=item;
create1(ptree,&((*t)->lchild));
create1(ptree,&((*t)->rchild));
}
}
方法二
- 这个创建方法形参中不含根节点,不需要改变根结点的值,而在返回值中直接将返回值返回给根节点。而else中创建的t在函数中充当该树的根节点的作用,最后将它返回给原树的根节点。
这个方法比上个容易理解,以后可以多用这个。
PNODE create2(PTREE ptree)
{
char item;
scanf("%c",&item);
if(ptree->ref==item)
{
return NULL;
}
else{
PNODE t=(PNODE)malloc(sizeof(NODE));
t->data=item;
t->lchild=create2(ptree);
t->rchild=create2(ptree);
return t;
}
}
二叉树的中序遍历
void fronttraverse(PNODE root)
{
if(root!=NULL)
{
printf("%c",root->data);
fronttraverse(root->lchild);
fronttraverse(root->rchild);
}
}
求二叉树的基本属性
int Size(PNODE root)
{
if(root==NULL)
return 0;
else
return Size(root->lchild)+Size(root->rchild)+1;
}
int Height(PNODE root)
{
if(root=NULL)
return 0;
else{
int lheight=Height(root->lchild);
int rheight=Height(root->rchild);
return(lheight>rheight?lheight:rheight)+1;
}
}
二叉树的查询方法
PNODE search(PNODE root,char a)
{
if(root==NULL)
return NULL;
if(root->data==a)
return root;
PNODE p=search(root->lchild,a);
if(p!=NULL)return p;
return search(root->rchild,a);
}
PNODE parent(PNODE root,PNODE p)
{
if(root==NULL||P==NULL)
return NULL;
if(root->lchild==p||root->rchild==p)
return root;
PNODE q=parent(root->lchild,p);
if(q!=NULL)return q;
return parent(root->rchild,p);
}
二叉树的拷贝和清空
void Copy(PNODE p,PNODE q)
{
if(q==NULL)return NULL;
p->data=q->data;
p->lchild=Copy(q->lchild);
p->rchild=Copy(q->rchild);
}
void Clear(PNODE root)
{
if(root!=NULL)
{
Clear(root->lchild);
Clear(root->rchild);
free(root);
root=NULL;
}
}
二叉树的非递归遍历
1.前序非递归遍历(利用链式栈):
- 先将根节点放进栈中,再得到栈顶元素,将它取出,判断他的右子树是否为空,不为空就放进栈中,在判断左子树是否为空,不为空就放进栈中。(这块要先判断右子树再判断左子树)再次得到栈顶元素,取出输出,直至栈为空时停止循环。
void fronttraverse1(PSTACK ps,PTREE pt)
{
PNODE root=pt->root;
push(ps,root->data);
if(!is_empty(ps))
{
PNODE p=getpop(ps);
pop(ps);
printf("%c",p->data);
if(p->rchild!=NULL)
push(ps,p->rchild);
if(p->lchild!=NULL)
push(ps,p->lchild);
}
}
2.中序非递归遍历二叉树:
- 先通过循环得到最左下的节点,将其输出,再判断它是否有右子树,有就放入栈中,不断循环。循环终止条件是栈为空,因此循环前要将根节点先放进去,再次利用循环找到最左下的节点,之后找一个右子树,再次找到它最左下的节点。
void inordertraverse(PSTACK ps,PTREE pt)
{
PNODE p=pt->root;
if(p!=NULL)
{
push(ps,p);
PNODE t;
while(!is_empty(ps))
{
while(p!=NULL&&p->lchild!=NULL)
{
p=p->lchild;
push(ps,p);
}
t=getpop(ps);
printf("%c",t->data);
pop(ps,t);
if(t->rchild!=NULL)
{
push(ps,t->rchild);
}
}
}
}
4.后序非递归遍历二叉树:
- 后序遍历时先找到最左下的节点,然后判断它右子树是否存在,有就入栈。而因为根节点是最后输出的,所以在输出时要判断是从左子树返回还是从右子树返回,因此在栈中的元素应该是一个结构体,包含了enum形式的{L,R}以及相应的节点,从左子树判断完成后,先判断栈中元素是L还是R,若是L则在判断它的右子树是否为空,若为空则输出该节点,若不为空,则进入循环继续找到最左下的节点进行判断。
void postorder(PSTACK ps,PTREE pt)
{
PNODE p=pt->root;
TAG T;
while(p!=NULL)
{
T.tag=L;
T.ptr=p;
push(ps,T);
p=p->lchild;
}
bool flag=true;
while(!is_empty(ps))
{
TAG A=getpop(ps);
pop(ps,A);
r=A.ptr;
switch(A.tag)
{
case L:
A.tag=R;
push(ps,A);
flag=false;
p=p->rchild;
break;
case R:
printf("%c",r->data);
break;
}
}
}