typedef char datatype; // 结点属性值的类型 // 二叉树结点的类型 typedef struct node { datatype data; struct node *lchild, *rchild; // struct node *parent; // 指向双亲的指针 (无关紧要) } bintnode; typedef bintnode *bintree; bintree root; // 指向二叉树根结点的指针
前序遍历:首先访问根结点;
而后按照前序遍历的顺序访问根结点的左子树;
再按照前序遍历的顺序访问根结点的右子树node
中序遍历:首先按照中序遍历的顺序访问根结点的左子树;
而后访问根结点;最后按照中序遍历的顺序访问根结点的右子树算法
后序遍历:首先按照后序遍历的顺序访问根结点的左子树;
而后按照后序遍历的顺序访问根结点的右子树;最后访问根结点函数
图二叉树的遍历:spa
二叉树遍历的递归实现 :按照遍历规定的次序,访问根结点时就输出根结点的值设计
经常使用操做:指针
typedef char datatype; // 结点属性值的类型 // 二叉树结点的类型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; void preorder(bintree t) { if (t) { printf("%c", t->data); preorder(t->lchild); preorder(t->rchild); } }
typedef char datatype; // 结点属性值的类型 // 二叉树结点的类型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; bintree createbintree() { char ch; bintree t; if ((ch = getchar()) == '#') t = NULL; else { t = (bintnode *) malloc(sizeof(bintnode)); // 生成二叉树的根结点 t->data = ch; t->lchild = createbintree(); // 递归实现左子树的创建 t->rchild = createbintree(); // 递归实现右子树的创建 } return t; }
typedef char datatype; // 结点属性值的类型 // 二叉树结点的类型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; void preorder1(bintree t) { seqstack s; s.top = 0; // 当前处理的子树不为空或栈不为空则循环 while ((t) || (s.top != 0)) { if (t) { printf("%c ", t->data); push(&s, t); t = t->lchild; } else { t = pop(&s); t = t->rchlid; } } }
typedef char datatype; // 结点属性值的类型 // 二叉树结点的类型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; bintree locate(bintree t, dataype x) { bintree p; if (t == NULL) return NULL; else { if (t->data == x) return t; else { p = locate(t->lrchild); if (p) return p; else return locate(t->rchild) } } }
typedef char datatype; // 结点属性值的类型 // 二叉树结点的类型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; int numofnode(bintree t) { if (t == NULL) return 0; else return (numofnode(t->lchild) + numofnode(t->rchild) + 1); }
typedef char datatype; // 结点属性值的类型 // 二叉树结点的类型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; int isequal(bintree t1, bintree t2) { int t; t = 0; if (t1 == NULL && t2 == NULL) t = 1; // t1 和 t2 均为空,则两者等价 else { // 处理 t1 和 t2 均不为空的状况 if (t1 != NUll && t2 != NULL) if (t1->data == t2->data) // 若是根结点的值相等 if (isequeal(t1->lchild, t2->lchild)) // 若是 t1 和 t2 的左子树等价 t = isequeal(t1->rchild, t2->rchild); // 返回值取决于 t1 和 t2 的右子树是否等价 } return (t); }
typedef char datatype; // 结点属性值的类型 // 二叉树结点的类型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; int depth(bintree t) { int h, lh, rh; if (t == NULL) h = 0; // 处理空二叉树的状况 else { lh = depth(t->lchild); // 求左子树的高度 rh = depth(t->rchild); // 求右子树的高度 if (lh >= rh) h = lh + 1; // 求二叉树t的高度 else h = rh + 1; } return h; }
穿线二叉树的指针:结点的左、右指针指向其左、右子女code
中序穿线二叉树的线索:结点的左、右指针指向其中序遍历的前驱、后继结点blog
为了区别结点的左右指针是指针仍是线索,通常加上 \(ltag\) 和 \(rtag\) 两个标志位递归
图中序穿线二叉树:get
typedef char datatype; typedef struct node { datatype data; int ltag, rtag; // 左右标志位 struct node *lchild, *rchild; } binthrnode; typedef binthrnode *binthrtree;
typedef char datatype; typedef struct node { datatype data; int ltag, rtag; // 左右标志位 struct node *lchild, *rchild; } binthrnode; typedef binthrnode *binthrtree; // 寻找结点 p 在中序遍历下的后继结点 binthrtree insuccnode(binthrtree p) { binthrtree q; if (p->rtag == 1) // p 的右指针为线索,恰巧指向p的后继结点 return p->rchild; else { q = p->rchild; // 寻找 p 的右子树中最左下的结点 while (q->ltag == 0) q = q->lchild; // 求该右子树下中序遍历下的第一个结点 return q; } } // 中序遍历中序穿线二叉树 void inthrtree(binthrtree p) { if (p) { while (p->ltag == 0) p = p->lchild; // 求 p 中序遍历下的第一个结点 do { printf("%c ", p->data); p = insuccnode(p); // 求 p 中序遍历下的后继结点 } while (p); } }
树、森林到二叉树的转换步骤
图树到二叉树的转换:
图森林到二叉树的转换:
首先将二叉树按照逆时针方向旋转45度
若某结点是其双亲的左子女,则把该结点的右子女,右子女的右子女,……都与该结点的双亲用线连起来
最后去掉原二叉树中全部双亲到其右子女的连线
注:最后链接子结点,只能链接右子女,而不能链接左子女
图二叉树到森林的转换:
根据前序序列的第一个元素创建根结点;
在中序序列中找到该元素,肯定根结点的左右子树的中序序列;
在前序序列中肯定左右子树的前序序列;
由左子树的前序序列和中序序列创建左子树;
由右子树的前序序列和中序序列创建右子树。
如:已知一棵二叉树的先序遍历序列和中序遍历序列分别是 abdgcefh、dgbaechf,求二叉树及后序遍历序列。 先序:abdgcefh—>a bdg cefh 中序:dgbaechf—->dgb a echf 得出结论:a 是树根,a 有左子树和右子树,左子树有 bdg 结点,右子树有 cefh 结点 先序:bdg—>b dg 中序:dgb —>dg b 得出结论:b 是左子树的根结点,b 无右子树,有左子树 先序:dg—->d g 中序:dg—–>dg 得出结论:d 是 b 左子树的根节点,d 无左子树,g 是 d 的右子树 而后对于 a 的右子树相似能够推出 而后还原
如:已知一棵二叉树的后序遍历序列和中序遍历序列分别是gdbehfca、dgbaechf,求二叉树 后序:gdbehfca—->gdb ehfc a 中序:dgbaechf—–>dgb a echf 得出结论:a是树根,a有左子树和右子树,左子树有 bdg 结点,右子树有 cefh 结点 后序:gdb—->gd b 中序:dgb—–>dg b 得出结论:b 是 a 左子树的根节点,无右子树,有左子树 dg 后序:gd—->g d 中序:dg—–>d g 得出结论:d 是 b 的左子树根节点,g 是 d 的右子树 而后对于 a 的右子树相似能够推出 而后还原
分别采用递归和非递归方式编写两个函数,求一棵给定二叉树中叶子结点的个数
typedef char datatype; typedef struct node { datatype data; struct node *lchild, *rchild; } binthrnode; typedef binthrnode *bintree; // 递归方法求二叉树叶子结点的个数 int leaf1(bintree t) { if (t == NULL) return 0; else if (!t->lchild && !t->rchild) return 1; else return leaf1(t->lchild) + leaf1(t->rchild); } // 非递归方法求二叉树叶子结点的个数 int leaf2(bintree t) { seqstack s; // 顺序栈 int count = 0; // 叶子结点计数变量 init(&s); // 初始化空栈 while (t || !empty(&s)) { if (t) { if (!t->lchild && !t->rchild) count++; push(&s, t); t = t->lchild; } else { t = pop(&s); t = t->rchild; } } return count; }
试编写一个函数,返回一颗给定二叉树在中序遍历下的最后一个结点
typedef char datatype; typedef struct node { datatype data; struct node *lchild, *rchild; } binthrnode; typedef binthrnode *bintree; // 递归实现 bintree midlast(bintree t) { if (t && t->rchild) t = midlast(t->rchild); return t; } // 非递归实现 bintree midlast(bintree t) { bintree p = t; while (p && p->rchild) p = p->rchild; return p; }
前序(根左右)和中序(左根右)遍历结果相同的二叉树(去掉左都为“根右”)为(全部结点只有右子树的二叉树);前序(根左右)和后序(左右根)遍历结果相同的二叉树(哪个子树都不能够去掉)为(只有根结点的二叉树)
有 \(n\) 个结点的二叉树,已知叶结点个数为 \(n_0\),则该树中度为 \(1\) 的结点的个数为(\(n-2*n_0+1\));若此树是深度为 \(k\) 的彻底二叉树,则 \(n\) 的最小值为 (\(2^{k-1}\))
(真题)对于一颗具备 \(n\) 个结点的二叉树,该二叉树中全部结点的读书之和为(\(n-1\))
(真题)试分别画出具备 \(3\) 个结点的树和具备 \(3\) 个结点的二叉树的全部不一样形态。(此题注意树具备无序性)