Tree = (D, H), D是具有相同特性的数据元素的集合, H是D上二元关系的集合, T满足如下定义
ADT Tree{
数据对象: D
数据关系: H
若 D=∅ D = ∅ , H也为 ∅ ∅ , 称为空树
(1) 若D中只有唯一的元素(树根),H为空
(2) 若 D′=D−root D ′ = D − r o o t 不为空, 则存在 D′ D ′ 的一个划分
对于
(3) 对于(2)的划分, H−<root,x1>,<root,x2>,....<root,xm>有唯一的一个划分H1,H2,...Hm H − < r o o t , x 1 > , < r o o t , x 2 > , . . . . < r o o t , x m > 有 唯 一 的 一 个 划 分 H 1 , H 2 , . . . H m
且
操作集: 略
H中的关系在树上就是指两结点之间边
对于 <f,s>∈H,f是s的双亲结点,s是f的孩子结点 < f , s >∈ H , f 是 s 的 双 亲 结 点 , s 是 f 的 孩 子 结 点
}
递归定义, 树根和子树的根节点满足二元关系
各结点度不超过2的树, 上述定义中每层划分数最大为2
二叉树第i层的最大结点数: 2i−1(归纳法可证) 2 i − 1 ( 归 纳 法 可 证 )
深度为k的二叉树结点数量最多为 2k−1 2 k − 1
设二叉树中度为2的结点个数为 n2 n 2 ,度为0的结点(叶子结点)个数为 n0 n 0 ,度为1的结点的个数为 n1 n 1
满二叉树: 深度为k且结点数量为 2k−1 2 k − 1 的二叉树, 即每层结点数量都是最大值
完全二叉树: 与其深度相同的满二叉树在相应位置的结点编号相同
结点数为n的完全二叉树深度: ⌊log2n⌋+1或⌈log2n+1⌉ ⌊ log 2 n ⌋ + 1 或 ⌈ log 2 n + 1 ⌉
编号为i(从1开始编号)的结点的双亲节点的编号为 ⌊i2⌋ ⌊ i 2 ⌋ ,0表示不存在双亲节点, 左右孩子结点若存在,其编号分别为 i∗2,i∗2+1 i ∗ 2 , i ∗ 2 + 1
结点数为n的二叉树有多少种(形状):
Catalan数:Cn2nn+1 C a t a l a n 数 : C 2 n n n + 1
证明: 固定一个结点rt为根, 则rt的坐子树结点数l满足 l∈[0,n−1] l ∈ [ 0 , n − 1 ] , 右子树结点数为n-1-l
设 f(n)表示n个结点二叉树种类数,则f(n)=∑n−1i=0f(i)∗f(n−1−i) f ( n ) 表 示 n 个 结 点 二 叉 树 种 类 数 , 则 f ( n ) = ∑ i = 0 n − 1 f ( i ) ∗ f ( n − 1 − i )
且 f(0)=f(1)=1 f ( 0 ) = f ( 1 ) = 1 ,即为 Catalan C a t a l a n 数
基础
#include <stdio.h>
#include <stdlib.h>
#define Status int
#define OK 1
#define ERROR 1
typedef int ElemType;
typedef struct BiTree{ //结构定义
ElemType data;
BiTree * lch;
BiTree * rch;
}BiTree, * pTree;
pTree newNode(ElemType data){ //newNode
pTree res = (pTree)malloc(sizeof(BiTree));
res->data = data;
res->lch = NULL;
res->rch = NULL;
return res;
}
void initTree(pTree &rt){ //init
rt = NULL;
}
void destroyBiTree(pTree &rt){ //destory
if(rt != NULL) {
destroyBiTree(rt->lch);
destroyBiTree(rt->rch);
free(rt);
rt = NULL;
}
}
Status BiTreeEmpty(pTree rt){ //isEmpty
return rt == NULL;
}
inline int max(int a, int b){
return a >= b ? a : b;
}
int BiTreeDepth(pTree rt){ //树的高度
if(rt == NULL) return 0;
return 1 + max(BiTreeDepth(rt->lch), BiTreeDepth(rt->rch));
}
pTree getTree(pTree rt, int index){ //根据2进制获取某一结点
while(index > 1){
if(index & 1) rt = rt->rch;
else rt = rt->lch;
index >>= 1;
if(rt == NULL) return rt;
}
return rt;
}
Status getValue(pTree rt, pTree e, ElemType &x){ //get
int depth = BiTreeDepth(rt);
for(int i = 1; i < 1 << depth; ++i){
pTree elem = getTree(rt, i);
if(elem == e) {
x = elem->data;
return OK;
}
}
return ERROR;
}
Status assignValue(pTree rt, pTree e, ElemType x){//set
int depth = BiTreeDepth(rt);
for(int i = 1; i < 1 << depth; ++i){
pTree elem = getTree(rt, i);
if(elem == e) {
elem->data = x;
return OK;
}
}
return ERROR;
}
pTree getParent(pTree rt, pTree e){ //获取双亲结点
int depth = BiTreeDepth(rt);
for(int i = 1; i < 1 << depth; ++i){
pTree elem = getTree(rt, i);
if(elem && (elem->lch == e || elem->rch == e)) return elem;
}
return NULL;
}
//test
int main(){
ElemType elem;
pTree rt = newNode(1);
pTree tree2 = newNode(3);
pTree tree3 = newNode(6);
pTree tree4 = newNode(5);
rt->lch = tree2;
rt->rch = tree3;
tree2->rch = tree4;
printf("Depth: %d\n", BiTreeDepth(rt));
if(getValue(rt, tree3, elem)) printf("OldValue: %d\n", elem);
else printf("Not in!\n");
assignValue(rt, tree3, 7);
if(getValue(rt, tree3, elem)) printf("NewValue: %d\n", elem);
else printf("Not in!\n");
pTree p = getParent(rt, tree3);
if(p) printf("%d\n", p->data);
destroyBiTree(rt);
if(rt == NULL) printf("Destoryed!\n");
return 0;
}
树的遍历(递归)
//先序遍历
void preOrder(pTree rt){
if(rt == NULL) return;
printf("%-3d", rt->data);
preOrder(rt->lch);
preOrder(rt->rch);
}
//中序遍历
void inOrder(pTree rt){
if(rt == NULL) return;
inOrder(rt->lch);
printf("%-3d", rt->data);
inOrder(rt->rch);
}
//后序遍历
void postOrder(pTree rt){
if(rt == NULL) return;
postOrder(rt->lch);
postOrder(rt->rch);
printf("%-3d", rt->data);
}
树的遍历(非递归)
//stack, queue借助STL
void inOrder1(pTree rt){
stack s;
s.push(rt);
while(!s.empty()){
while(s.top()) s.push(s.top()->lch);
s.pop();
if(!s.empty()){
pTree tmp = s.top();
printf("%-3d", tmp->data);
s.pop();
s.push(tmp->rch);
}
}
}
void inOrder2(pTree rt){
stack s;
while(rt || !s.empty()){
if(rt) {
s.push(rt);
rt = rt->lch;
}else{
rt = s.top();
printf("%-3d", rt->data);
s.pop();
rt = rt->rch;
}
}
}
void preOrder1(pTree rt){
stack s;
while(rt || !s.empty()){
if(rt){
printf("%-3d", rt->data);
s.push(rt);
rt = rt->lch;
}else{
rt = s.top();
s.pop();
rt = rt->rch;
}
}
}
void postOrder1(pTree rt){
pTree pre = NULL;
stack s;
s.push(rt);
while(!s.empty()){
rt = s.top();
if((rt->lch == NULL && rt->rch == NULL) ||){
printf("%-3d", rt->data);
s.pop();
pre = rt;
}else{
if(rt->rch != NULL) s.push(rt->rch);
if(rt->lch != NULL) s.push(rt->lch);
}
}
}
void display(pTree rt){
if(rt != NULL){
printf("%-3d", rt->data);
if(rt->lch || rt->rch){
printf("(");
if(rt->lch) display(rt->lch);
else printf("^");
printf(",");
if(rt->rch) display(rt->rch);
else printf("^");
printf(")");
}
}
}
void levelOrder(pTree rt){
queue que, tmp;
que.push(rt);
while(!que.empty()){
while(!que.empty()){
rt = que.front();
que.pop();
printf("%-3d", rt->data);
if(rt->lch) tmp.push(rt->lch);
if(rt->rch) tmp.push(rt->rch);
}
puts("");
que = tmp;
tmp.clear();
}
}
中序线索化及遍历:
#include <bits/stdc++.h>
using namespace std;
typedef int ElemType;
typedef struct BiThrTree{
ElemType data;
BiThrTree * lch;
BiThrTree * rch;
bool lTag;
bool rTag;
}BiThrTree, * pTree;
pTree newNode(ElemType data){ //newNode
pTree res = (pTree)malloc(sizeof(BiThrTree));
res->data = data;
res->lch = NULL;
res->rch = NULL;
res->lTag = true;
res->rTag = true;
return res;
}
void inThreading(pTree rt, pTree &pre){
if(rt){
inThreading(rt->lch, pre);
if(!pre->rch){
pre->rTag = false;
pre->rch = rt;
}
if(!rt->lch){
rt->lTag = false;
rt->lch = pre;
}
pre = rt;
inThreading(rt->rch, pre);
}
}
pTree inOrderThreading(pTree rt){//线索化
pTree res = newNode(-1);
res->lTag = true;
res->rTag = false;
res->rch = res;
if(!rt){
res->lch = res;
}else{
res->lch = rt;
pTree pre = res;
inThreading(rt, pre);
//printf("%d %d\n", pre->data, res->data);
pre->rTag = false;
pre->rch = res;
res->rch = pre;
}
return res;
}
void inOrder(pTree rt){
pTree p = rt->lch;
while(p != rt){
//printf("%d\n", p->data);
while(p->lTag == true) p = p->lch;
printf("%-3d", p->data);
while(p->rTag == false && p->rch != rt){
p = p->rch;
printf("%-3d", p->data);
}
p = p->rch;
}
puts("");
}
void inOrderReverse(pTree rt){
pTree p = rt->rch;
while(p != rt){
while(p->rTag == true) p = p->rch;
printf("%-3d", p->data);
while(p->lTag == false && p->lch != rt){
p = p->lch;
printf("%-3d", p->data);
}
p = p->lch;
}
puts("");
}
int main(){
pTree rt = newNode(1);
pTree tree2 = newNode(3);
pTree tree3 = newNode(6);
pTree tree4 = newNode(5);
rt->lch = tree2;
rt->rch = tree3;
tree2->rch = tree4;
pTree head = inOrderThreading(rt);
inOrder(head);
inOrderReverse(head);
return 0;
}
根据前序中序遍历确定后序遍历(确定二叉树的形状)
只能是前序遍历或者后序遍历和中序遍历才能确定一棵二叉树, 前序遍历和后序遍历无法确定
递归思想:
codeUp1096
#include
#include
#include
#include
using namespace std;
typedef char ElemType;
typedef struct BiTree{
ElemType data;
BiTree * lch;
BiTree * rch;
}BiTree, * pTree;
pTree newNode(ElemType data){
pTree res = (pTree)malloc(sizeof(BiTree));
res->data = data;
res->lch = NULL;
res->rch = NULL;
return res;
}
pTree getTree(string pre, string in){
ElemType fi = pre[0];
int pos = in.find(fi);
pTree res = newNode(fi);
if(pos > 0)
res->lch = getTree(pre.substr(1, pos), in.substr(0, pos));
if(pos + 1 < pre.length())
res->rch = getTree(pre.substr(pos + 1), in.substr(pos + 1));
return res;
}
void postOrder(pTree rt){
stack s;
s.push(rt);
pTree pre = NULL;
while(!s.empty()){
rt = s.top();
if((!rt->lch && !rt->rch) || (pre && (pre == rt->lch || pre == rt->rch))){
cout << rt->data;
s.pop();
pre = rt;
}else{
if(rt->rch) s.push(rt->rch);
if(rt->lch) s.push(rt->lch);
}
}
cout << endl;
}
int main(){
string pre, in;
while(cin >> pre >> in) {
pTree rt = getTree(pre, in);
postOrder(rt);
}
return 0;
}
…. 待续