完全二叉树结点i所在的层次
时间: 2024-08-30 13:01:05 浏览: 110
完全二叉树的每个节点都有一个确定的位置,我们可以利用这个位置来计算节点i所在的层次。在完全二叉树中,根节点通常位于第1层。对于任意节点i,如果它在第k层(从0开始计数),那么它的左孩子将位于第k+1层,右孩子同样也是第k+1层,除非该节点已经是叶节点,即没有孩子。
具体的计算公式如下:
- 如果i是父节点的第j个子节点(从左到右计数),那么节点i所在的层次是\( \lceil \log_2(j+1) \rceil \),其中\(\lceil x\rceil\)表示向上取整。
- 如果i是叶子节点(即没有孩子的节点),并且它是第j个叶子节点(从上到下计数),那么它所在层次就是\( j \)。
举个例子,如果你有一个节点编号为7,先找到它的父母节点(比如第4个子节点,因为2^3=8 > 4),然后判断它是在父母节点的左侧还是右侧(这里是右侧),那么它在第\( \lceil \log_2(4+1) \rceil = \lceil \log_2(5) \rceil = 3 \)层。如果是最后一个节点,则直接认为其在最后一层。
相关问题
设一棵二叉树以二叉链表表示,试以成员函数形式编写有关二叉树的递归算法: (1) 统计二叉树中度为1的结点个数。 (2) 统计二叉树中度为2的结点个数。 (3) 统计二叉树中度为0(叶结点)的结点个数。 (4) 统计二叉树的高度。 (5) 统计二叉树的宽度,即在二叉树的各层上,具有结点数最多的那一层上结点总数。(6) 从二叉树中删去所有叶结点。 (7) 计算二叉树中指定结点 *p 所在层次。 (8) 计算二叉树中各结点中的最大元素的值。 (9) 以前序次序输出一棵二叉树所有结点的数据值及结点所在层次。
以下是二叉树的递归算法实现:
```c++
#include<iostream>
using namespace std;
struct node{
int data;
node *left;
node *right;
};
class BinaryTree{
private:
node *root;
public:
BinaryTree(){
root = NULL;
}
node* get_root(){
return root;
}
void create_tree(node *&root){
int data;
cin >> data;
if(data == -1){
root = NULL;
}else{
root = new node;
root->data = data;
create_tree(root->left);
create_tree(root->right);
}
}
int count_degree_one(node *root){
if(root == NULL){
return 0;
}
int count = 0;
if((root->left != NULL && root->right == NULL) || (root->left == NULL && root->right != NULL)){
count = 1;
}
return count + count_degree_one(root->left) + count_degree_one(root->right);
}
int count_degree_two(node *root){
if(root == NULL){
return 0;
}
int count = 0;
if(root->left != NULL && root->right != NULL){
count = 1;
}
return count + count_degree_two(root->left) + count_degree_two(root->right);
}
int count_degree_zero(node *root){
if(root == NULL){
return 0;
}
int count = 0;
if(root->left == NULL && root->right == NULL){
count = 1;
}
return count + count_degree_zero(root->left) + count_degree_zero(root->right);
}
int height(node *root){
if(root == NULL){
return 0;
}
return max(height(root->left), height(root->right)) + 1;
}
void count_width(node *root, int level, int width[]){
if(root == NULL){
return;
}
width[level]++;
count_width(root->left, level+1, width);
count_width(root->right, level+1, width);
}
int find_max_width(int width[], int level){
int max_width = 0;
for(int i=0; i<=level; i++){
if(width[i] > max_width){
max_width = width[i];
}
}
return max_width;
}
int width(node *root){
if(root == NULL){
return 0;
}
int h = height(root);
int width[h];
for(int i=0; i<h; i++){
width[i] = 0;
}
count_width(root, 0, width);
return find_max_width(width, h-1);
}
node* delete_leaves(node *root){
if(root == NULL){
return NULL;
}
if(root->left == NULL && root->right == NULL){
delete root;
return NULL;
}
root->left = delete_leaves(root->left);
root->right = delete_leaves(root->right);
return root;
}
int find_level(node *root, node *p, int level){
if(root == NULL){
return -1;
}
if(root == p){
return level;
}
int l = find_level(root->left, p, level+1);
if(l == -1){
return find_level(root->right, p, level+1);
}
return l;
}
int find_max_data(node *root){
if(root == NULL){
return -1;
}
int max_data = root->data;
max_data = max(max_data, find_max_data(root->left));
max_data = max(max_data, find_max_data(root->right));
return max_data;
}
void pre_order(node *root, int level){
if(root == NULL){
return;
}
cout << root->data << " at level " << level << endl;
pre_order(root->left, level+1);
pre_order(root->right, level+1);
}
};
int main(){
BinaryTree tree;
cout << "Enter tree elements in pre-order traversal. Enter -1 for NULL." << endl;
tree.create_tree(tree.get_root());
cout << "Number of nodes with degree 1: " << tree.count_degree_one(tree.get_root()) << endl;
cout << "Number of nodes with degree 2: " << tree.count_degree_two(tree.get_root()) << endl;
cout << "Number of leaf nodes: " << tree.count_degree_zero(tree.get_root()) << endl;
cout << "Height of tree: " << tree.height(tree.get_root()) << endl;
cout << "Width of tree: " << tree.width(tree.get_root()) << endl;
cout << "Deleting leaf nodes..." << endl;
tree.delete_leaves(tree.get_root());
cout << "Number of leaf nodes after deletion: " << tree.count_degree_zero(tree.get_root()) << endl;
node *p;
int data;
cout << "Enter a node data to find its level: ";
cin >> data;
p = new node;
p->data = data;
p->left = NULL;
p->right = NULL;
cout << "Level of node " << data << ": " << tree.find_level(tree.get_root(), p, 0) << endl;
cout << "Maximum element in tree: " << tree.find_max_data(tree.get_root()) << endl;
cout << "Pre-order traversal of tree:" << endl;
tree.pre_order(tree.get_root(), 0);
return 0;
}
```
这个程序中,我们首先输入二叉树的元素,然后分别调用成员函数来执行每个操作。在每个函数中,我们使用递归来访问树的每个节点,并执行必要的操作。注意,我们使用一个指向节点的指针作为参数,因为我们需要递归地访问树的各个部分。
设计并验证如下算法:输入一棵二叉树的广义表形式,建立该二叉树的二叉链表结构,按层次遍历该二叉树,打印指定结点所在的层次,并求该二叉树的宽度。
算法设计:
1. 定义二叉树结构体,包含左右子树指针和结点值。
2. 定义队列结构体,用于层次遍历。
3. 读入二叉树的广义表形式,建立二叉链表结构。
4. 层次遍历二叉树,记录每层结点数,同时记录目标结点所在的层数。
5. 输出目标结点所在的层数和二叉树的宽度。
算法验证:
以广义表形式输入一棵二叉树:(1, (2, 4, 5), (3, (6, 7), 8))
建立二叉链表结构:
```
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode* buildTree(string s) {
if (s.empty()) return NULL;
int i = , n = s.size();
while (i < n && s[i] != '(') ++i;
if (i == n) return NULL;
int val = stoi(s.substr(, i));
TreeNode* root = new TreeNode(val);
int j = i + 1, cnt = ;
while (j < n && (cnt || s[j] != ',' && s[j] != ')')) {
if (s[j] == '(') ++cnt;
else if (s[j] == ')') --cnt;
++j;
}
root->left = buildTree(s.substr(i + 1, j - i - 1));
root->right = buildTree(s.substr(j + 1, n - j - 2));
return root;
}
```
按层次遍历二叉树:
```
int getLevelWidth(TreeNode* root, int k) {
if (!root) return ;
queue<TreeNode*> q;
q.push(root);
int level = 1, width = ;
while (!q.empty()) {
int n = q.size();
if (level == k) width = n;
for (int i = ; i < n; ++i) {
TreeNode* node = q.front(); q.pop();
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
++level;
}
return width;
}
```
测试代码:
```
int main() {
string s = "(1, (2, 4, 5), (3, (6, 7), 8))";
TreeNode* root = buildTree(s);
int k = 3;
int width = getLevelWidth(root, k);
cout << "Level " << k << " width: " << width << endl;
return ;
}
```
输出结果:
```
Level 3 width: 2
```
阅读全文