您的位置:首页 > 理论基础 > 数据结构算法

数据结构之二叉树练习

2014-10-09 09:49 155 查看
1.四种二叉树的遍历方式(前序/中序/后序/层序遍历)

/*
* @description:前序遍历二叉树
*/
Status PreOrderTraverse(BiTree T,Status (*visit) (TElemType elem)) {
if(T) {
if(visit(T->data))
if(PreOrderTraverse(T->lchild,visit))
if(PreOrderTraverse(T->rchild,visit))
return OK;
return ERROR;
}

return OK;
}

/*
* @description:中序遍历二叉树
*/
Status InOrderTraverse(BiTree T,Status (*visit)(TElemType elem)) {
if(T) {
if(InOrderTraverse(T->lchild,visit))
if(visit(T->data))
if(InOrderTraverse(T->rchild,visit))
return OK;
return ERROR;
}

return OK;
}

/*
* @description:后序遍历二叉树
*/
Status PostOrderTraverse(BiTree T,Status (*visit)(TElemType elem)) {
if(T) {
if(PostOrderTraverse(T->lchild,visit))
if(PostOrderTraverse(T->rchild,visit))
if(visit(T->data))
return OK;
return ERROR;
}

return OK;
}

/*
* @description:层序遍历
* @more:利用队列,将每个节点的左右孩子入队,
由于队列的性质,可按层遍历二叉树
*/
Status LevelOrderTraverse(BiTree T,Status (*visit) (TElemType elem)) {
if(T == NULL)
return ERROR;

LinkQueue TreeQueue;
ElemType p;

InitQueue(&TreeQueue);
p = T;

EnQueue(&TreeQueue,p);

while(!QueueEmpty(TreeQueue)) {
DeQueue(&TreeQueue,&p);

if(p) {
visit(p->data);
EnQueue(&TreeQueue,p->lchild);
EnQueue(&TreeQueue,p->rchild);
}
}

return OK;
}


2.求树的深度

/*
* @description:二叉树的深度
* @param BiTree T
* @return int depth
*/
int BiTreeDepth(BiTree T) {
int l,r;

if(T) {
l = BiTreeDepth(T->lchild);
r = BiTreeDepth(T->rchild);
return (l > r ? l : r) + 1;
}

return 0;
}


3.非递归实现前序遍历

/*
* @param BiTree T
* @param Status (*Visit) (TElemType)
* @description:非递归实现前序遍历
* @more:这里使用栈来实现,在这个实现中其实
最关键是要想到先到右孩子进栈,再把左孩子进栈
*/
Status PreTraverse(BiTree T,Status (*Visit) (TElemType)) {
LinkStack S;
BiTree p;
p = T;

if(T != NULL)
InitStack(&S);
else
return ERROR;

//将根节点进栈
Push(&S,p);

//栈不为空
while(! StackEmpty(S)) {
Pop(&S,&p);

if(p) {
Visit(p->data);
//注意先将右孩子进栈,再将左孩子进栈,顺序不能变
if(p->rchild)
Push(&S,p->rchild);

if(p->lchild)
Push(&S,p->lchild);
}
}

return OK;
}


4.非递归遍历实现中序遍历

/*
* @description:非递归遍历实现中序遍历
* @more:这个对我来说真心想不出来,网上看到的让我幡然醒悟
其实感觉还是有一点递归的思想在里面的-->想象一下遍历
完左边的后,根节点右边的遍历思路是不是一样的
>>主要思路在于一直往左走到尽头,遇到空节点则弹出,遍历,
接着往右走
*/
Status InTraverse(BiTree T,Status (*Visit) (TElemType)) {
if(T == NULL)
return ERROR;

BiTree p;
LinkStack S;

p = T;
InitStack(&S);
//注意结束循环的条件-->当指针为空且栈为空时在跳出循环
while(p || !StackEmpty(S)) {
if(p) {
//当左孩子的指针不为空时,一直往左走下去,并且将所走过的节点进栈
Push(&S,p);
p = p->lchild;
}
else {
//遇到的的节点为空则将现在的栈顶元素弹出打印,并往右走
Pop(&S,&p);
Visit(p->data);
p = p->rchild;
}
}

return OK;
}


5.非递归实现后序遍历

/*
* @description:非递归实现后序遍历
*/
Status PostTraverse(BiTree T,Status (*Visit) (TElemType)) {
if(T == NULL)
return ERROR;

BiTree p,pre;
//pre是用来标记上一个访问的位置的,忘记这个很容易是程序陷入死循环
pre = NULL;

LinkStack S;

p = T;
InitStack(&S);
//注意结束循环的条件-->当指针为空且栈为空时在跳出循环
while(p || !StackEmpty(S)) {
if(p) {
//当左孩子的指针不为空时,一直往左走下去,并且将所走过的节点进栈
Push(&S,p);
p = p->lchild;
}
else {
//获取栈顶元素但是不弹出
GetTop(S,&p);
//如果右边有元素且右边的节点不是刚才访问过的就往右边走
if(p->rchild != NULL && pre != p->rchild)
p = p->rchild;
else {
Pop(&S,&p);
pre = p;
Visit(p->data);
p = NULL;
}

}
}
}


6.求二叉树中第k层的节点个树

/*
* @description:求二叉树中第k层的节点个树
* @more:递归思想
1.当k == 0时,节点个数为零
2.当k == 1时,节点个数为1
3,当k > 1时,节点个数为左子树的节点个数和游子树的节点个数之和
*/
int NodeNumKth(BiTree T,int k) {
if(k == 0)
return 0;
if(k == 1)
return 1;

return NodeNumKth(T->lchild,k - 1) + NodeNumKth(T->rchild, k - 1);
}


7.判断一个元素值是否在二叉树中
/*
* @param BiTree T
* @param TElemType elem;
* @description:判断一个元素值是否在二叉树中
* @more:在则返回真,否则返回假-->可知在比较过程中(比较两颗树是否等)
可先比较当前节点,再比较左子树,最后比较右子树
*/
Status Locate(BiTree T,TElemType elem) {
if(NULL == T)
return ERROR;
else {
if(T->data == elem)
return TRUE;
else {
if(! Locate(T->lchild,elem))
return Locate(T->rchild,elem);
else
return TRUE;
}
}
}


8.递归求二叉树的节点数

/*
* @param BiTree T
* @return int nodenum
* @description:递归求二叉树的节点数
*/
int NodeNum(BiTree T) {
if(NULL == T)
return 0;
//证明树不空则至少有一个根节点
else
return NodeNum(T->lchild) + NodeNum(T->rchild) + 1;

}


9.判断两个二叉树是否相等

/*
* @param BiTree T1
* @param BiTree T2
* @return Status
* @description:判断两个二叉树是否相等
* @more:主要树为空的情况
*/
Status EqualBiTree(BiTree T1,BiTree T2) {
int flag;
//请初始化,否则当为假时,返回值未知
flag = 0;

if(NULL == T1 && NULL == T2)
flag = TRUE;
else {
if(T1 != NULL && T2 != NULL) {
//当前节点相等
if(T1->data == T2->data)
//左孩子相等
if(EqualBiTree(T1->lchild,T2->lchild))
//真假情况决定于右孩子
flag = EqualBiTree(T1->rchild,T2->rchild);
}
}

return flag;
}


10.统计树中节点数目

/*
* @param BiTree T
* @description:统计二叉树中叶子节点的数目
* @more:所谓叶子节点即即没有左子树和右子树的节点(度为0)
*/
int LevesNum(BiTree T) {
if(T) {
//发现叶子节点
if(T->lchild == NULL && T->rchild == NULL)
return 1;

//递归实现查找左右子树
return LevesNum(T->lchild) + LevesNum(T->rchild);
}

return 0;
}


11.交换左右子树

/*
* @param BiTree T
* @return void
* @description:递归算法将二叉树的左右子树交换
*/
void Exchange(BiTree T) {
BiTree temp;

if(T) {
//交换必须从最深层开始
Exchange(T->lchild);
Exchange(T->rchild);
//交换左右孩子节点的指针
temp = T->lchild;
T->lchild = T->rchild;
T->rchild = temp;
}
}


总结:除了要求非递归实现的,无不使用到了递归思想(再次看到了递归的强大和威力)

完整源码:GitHub
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: