二叉树的创建
二叉树的创建用到了辅助队列,通过辅助队列来创建二叉树;
void buildBinaryTree(PTree_Node* root, PTree_Queue* phead, PTree_Queue* ptail,Tree_Element val) {
PTree_Node newTree = (PTree_Node)calloc(1, sizeof(Tree_Node));
PTree_Queue newQueue = (PTree_Queue)calloc(1, sizeof(Tree_Queue));
newTree -> val = val;
newQueue -> insertPos = newTree;
PTree_Queue cur = *phead;
//根节点为空,说明树是空的
if (NULL == *root) {
*root = newTree;
*phead = newQueue;
*ptail = newQueue;
} else {
(*ptail) -> snext = newQueue;
*ptail = newQueue;
//左孩子为空,赋给左孩子
if (NULL == cur -> insertPos -> left) {
cur -> insertPos -> left = newTree;
//右孩子为空,赋给右孩子
} else if (NULL == cur -> insertPos -> right) {
cur -> insertPos -> right = newTree;
//左右孩子都设置完成的结点,从队列里移除
*phead = cur -> snext;
free(cur);
cur = NULL;
}
}
}
二叉树的遍历
前(先)序遍历
1、递归实现
void pre_order(PTree_Node root) {
if(NULL == root) {
return;
}
visit(root);
pre_order(root -> left);
pre_order(root -> right);
}
2、非递归实现
void pre_order(BiTree root) {
Stack< BiTreeNode> s;
//初始化一个栈
init_stack(s);
BiTree p = root;
//栈中有数据,就需要遍历
while(p || !isEmpty(s)){
if(p) {
//根节点先访问
visit(p);
//访问后push到栈中,为了遍历右结点使用
push(s, p);
//访问完根结点后,就该访问左结点了
p = p -> left;
} else {
//到这里说明当前结点没有左结点,因此该弹出结点访问右结点
pop(s, p);
//访问当前结点的右结点,如果右结点还有左结点又回进行上门的循环
//直到所有结点都被访问后结束
p = p -> right;
}
}
}
中序遍历
1、递归实现
void in_order(BiTree root) {
if (NULL == root) {
return;
}
in_order(root -> left);
visit(root);
in_order(root -> right);
}
2、非递归实现
void in_order(BiTree root) {
Stack<BiTreeNode> s;
init_stack(s);
BiTree p root;
while (p || !isEmpty(s)) {
if (p) {
push(s, p);
p = p -> left;
} else {
pop(s, p);
visit(p);
p = p -> right;
}
}
}
后序遍历
1、递归实现
void post_order(BiTree root) {
if (NULL == root) {
return;
}
post_order(root -> left);
post_order(root -> right);
visit(root);
}
2、非递归实现
void post_order(BiTree root) {
Stack<BiTree> s;
init_stack(s);
BiTree p = root;
while(p || !isEmpty(s)) {
BiTree visitFlag;
if(p) {
push(s, p);
p = p -> left;
} else {
//这里需要注意的是一个结点如果有右结点被访问后,由于当前结点还在栈中
//所以会造成死循环,所以这里需要标识,避免死循环
top(s, p);
if (p -> right && p -> right != visitFlag) {
p = p -> right;
} else {
pop(s, p);
visit(p);
//出栈后记录一下,防止重复入栈,避免死循环
visit_flag = p;
p = NULL;
}
}
}
}
层次遍历
1、顺序遍历
//层次遍历整体比较简单就是借助队列,
//先访问根结点,如果有左孩子就入栈,有右孩子再入栈,一次扫描栈,直至为空
void levelOrder(BiTree root) {
BiTree p;
Queue<BiTree> q;
initQueue(q);
enQueue(q, root);
while (!isEmpty(q)) {
deQueue(q, p);
if (p -> left) {
enQueue(p -> left);
}
if (p -> right) {
enQueue(p -> right);
}
}
}
2、逆序遍历
void levelOrderReverse (BiTree root) {
if (NULL == root) {
return;
}
BiTree cur = root;
//定义栈,将各结点放入栈中,然后遍历
Stack<BiTree> s;
//队列用于层序的正向遍历
Queue<BiTree> q;
initStack(s);
initQueue(s);
//将树的根结点先入栈
enQueue(q, cur);
//将顺序入队的数据,放入栈中
while (!isEmpty(q)) {
//出栈
deQueue(q, cur);
//放入栈
push(s, cur);
if (cur -> left) {
enQueue(q, cur -> left);
}
if (cur -> right) {
enQueue(q, cur -> right);
}
}
//将栈中数据出栈分别访问
while (!isEmpty(s)) {
pop(s, p);
visit(p);
}
}
网友评论