二叉树的链式存储结构
typedef struct BinTr{
int data; // 数据域
struct BinTr *left, *right; // 左右指针域
// int loc; // 附加:记录结点所在的层号
}*BinTree, BinNode;
取最大值max函数的实现
int max(int a, int b){
return a > b ? a : b;
}
0.由二叉树的顺序存储结构序列生成二叉树(的链式存储结构)
给定二叉树的顺序存储结构,结构中每个元素代表二叉树中结点的数据;
存储从下标idx为1的位置开始,其中下标为2 * idx存储的是idx结点的左孩子,2 * idx+1存储idx结点的右孩子,0为NULL;用该序列来生成二叉树(的链式存储)。
int createSeq[] = {-1, 1, 2, 3, 0, 4, 0, 5, 0, 0, 6, 0};
BinTree bt = createBinTree(createSeq, sizeof(createSeq) / sizeof(createSeq[0]), 1);
BinTree createBinTree(int createSeq[], int size, int u){
if(u >= size || createSeq[u] == 0) return NULL;
BinNode* node = (BinNode* )malloc(sizeof(BinNode));
node -> data = createSeq[u];
node -> left = createBinTree(createSeq, size, u * 2);
node -> right = createBinTree(createSeq, size, u * 2 + 1);
return node;
}
1.统计二叉树中度为1、2、0的结点个数
// 1.统计二叉树中度为1的结点个数
int countDegree1(BinTree u){
if(u == NULL) return 0;
return countDegree1(u -> left) + countDegree1(u -> right) +
(u -> left && u -> right == NULL || u -> left == NULL && u -> right);
}
// 2.统计二叉树中度为2的结点个数
int countDegree2(BinTree u){
if(u == NULL) return 0;
return countDegree2(u -> left) + countDegree2(u -> right) + (u -> left && u -> right);
}
// 3.统计二叉树中度为0的结点个数
int countDegree0(BinTree u){
if(u == NULL) return 0;
return countDegree0(u -> left) + countDegree0(u -> right) + (u -> left == NULL && u -> right == NULL);
}
2.求得二叉树的高度
int getHeight(BinTree u){
if(u == NULL) return 0;
return max(getHeight(u -> left), getHeight(u -> right)) + 1;
}
3.求得二叉树的宽度
二叉树的宽度是指含有最多节点数的对应层对应的节点数
方式:
在结构体属性中附加一个层数loc属性,用于记录每个结点对应的层数(也可以采用哈希的方式进行存储),
对二叉树进行层次遍历(需要使用队列),根结点所在的是第一层,由根结点拓展出来的是第二层,将这些结点入队;
由根结点的子节点拓展出来的是第三层,将这些结点入队,以此类推;
所以出队列时的各结点元素的层数号必定以1223…34…4这种非严格递增的顺序排列,
那么树的宽度就是出队所形成的层数号序列中的最长的重复数字序列的长度,
可以用临时变量cnt来存储某个层号下的结点个数(重复数字的个数),若出队的层号发生改变,
说明先前层号下的结点全部出队,那么将其与res(结果值)去max即可,
直至所有结点出列为止。
int getWidth(BinTree u){
BinNode* queue[105];
int head = 0, tail = 0;
u -> loc = 1;
int res = 1, cnt = 0, cur = 1;
queue[tail ++] = u;
while(head != tail){ // 队列不空
BinNode* t = queue[head ++];
if(t -> left){
queue[tail ++] = t -> left;
t -> left -> loc = t -> loc + 1; // 父结点层号更新子结点层号
cnt ++;
}if(t -> right){
queue[tail ++] = t -> right;
t -> right -> loc = t -> loc + 1; // 父结点层号更新子结点层号
cnt ++;
}
if(head != tail && queue[head] -> loc != cur){ // 层号发生变动
res = max(res, cnt);
cur = queue[head] -> loc;
cnt = 0;
}
}
return res;
}
4.从二叉树中删除所有叶节点
void delLeaves(BinTree u){
if(u -> left){
// u的左孩子是叶子结点
if(u -> left -> left == NULL && u -> left -> right == NULL){
BinNode* tmp = u -> left;
u -> left = NULL;
free(tmp);
}else
delLeaves(u -> left);
}
if(u -> right){
// u的右孩子是叶子结点
if(u -> right -> left == NULL && u -> right -> right == NULL){
BinNode* tmp = u -> right;
u -> right = NULL;
free(tmp);
}else
delLeaves(u -> right);
}
}
5.计算指定结点*p所在的层次(为易于验证正确性,这里只查看结点的数据域,因此结点的数据要保证互不相同)
// tag:所要搜寻到的目标结点, cur: 当前所在层数, 结果由res带回, res为-1表示没有找到
void getLoc(BinTree u, BinNode* tag, int cur, int *res){
if(*res != -1 || u == NULL) return;
if(u -> data == tag -> data){
*res = cur;
return;
}
getLoc(u -> left, tag, cur + 1, res);
getLoc(u -> right, tag, cur + 1, res);
}
6.计算二叉树中各结点的最大元素的值
int getMax(BinTree u){
int res = u -> data;
if(u -> left)
res = max(res, getMax(u -> left));
if(u -> right)
res = max(res, getMax(u -> right));
return res;
}
7.交换二叉树中每个结点的两个子女
void changeChild(BinTree u){
if(u == NULL) return;
changeChild(u -> left);
changeChild(u -> right);
BinNode* t = u -> left;
u -> left = u -> right;
u -> right = t;
}
8.以先序次序输出一颗二叉树中所有结点的数据值及结点所在的层次
void preOrder(BinTree u, int loc){
if(u == NULL) return;
printf("%d %d\n", u -> data, loc);
preOrder(u -> left, loc + 1);
preOrder(u -> right, loc + 1);
}