完全二叉树

目录

一,完全二叉树

二,完全二叉树的性质

三,OJ实战

CSU 1946 A Rational Sequence

CSU 1213 二叉树结点公共祖先

力扣 222. 完全二叉树的节点个数

力扣 919. 完全二叉树插入器


一,完全二叉树

一棵有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

完全二叉树是Full Binary Tree中的一种特例,而Perfect Binary Tree又是完全二叉树中的一种特例。

FBT、PBT 满二叉树、Full Binary Tree、Perfect Binary Tree_full binary tree perfect binary tree-CSDN博客

二,完全二叉树的性质

除根节点外,节点n的父节点是节点n/2

三,OJ实战

CSU 1946 A Rational Sequence

Description
An infinite full binary tree labeled by positive rational numbers is defined by:

The label of the root is 1/1.
The left child of label p/q is p/(p+q).
The right child of label p/q is (p+q)/q.
The top of the tree is shown in the following figure:

A rational sequence is defined by doing a level order (breadth first) traversal of the tree (indicated by the light dashed line). So that:


Write a program to compute the nth element of the sequence, F(n). Does this problem sound familiar? Well it should! But we changed it a little!
Input
The first line of input contains a single integer P, (1 <= P <= 1000), which is the number of data sets that follow. Each data set should be processed identically and independently.
Each data set consists of a single line of input. It contains the data set number, K, and the index, N, of the sequence element to compute (1 <= N <= 2147483647).

Output
For each data set there is a single line of output. It contains the data set number, K, followed by a single space which is then followed by the numerator of the fraction, followed immediately by a forward slash (‘/’) followed immediately by the denominator of the fraction. Inputs will be chosen so neither the numerator nor the denominator will overflow an 32-bit unsigned integer.

Sample Input
4
1 1
2 4
3 11
4 1431655765
Sample Output
1 1/1
2 1/3
3 5/2
4 2178309/1346269


这是完全二叉树,所以可以直接找到每个节点的父亲是谁,递归即可解决本题。

代码:
 

#include<iostream>
using namespace std;
 
int a, b;
 
void f(int n)
{
	if (n == 1)
	{
		a = 1, b = 1;
		return;
	}
	f(n / 2);
	if (n % 2)a += b;
	else b += a;
}
int main()
{
	int p, n;
	cin >> p;
	while (p--)
	{
		cin >> n;
		cout << n<<' ';
		cin >> n;
		f(n);
		cout << a << '/' << b << endl;
	}
	return 0;
}

CSU 1213 二叉树结点公共祖先

题目:

Description

一个顺序存储的完全二叉树:

             1

          /     \

        2         3

      /   \     /    \

    4       5  6      7

    ...

任意给定两结点的编号,求两结点最近的公共祖先。

Input

每组数据一行,为空格隔开的两个数i和j,皆为32位有符号正整数

Output

每组数据对应一行,为编号为i和j的结点的最近公共祖先的编号

Sample Input

4 5
4 7
Sample Output

2
1

这是完全二叉树,代码:
 

#include<iostream>
using namespace std;
 
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        while(a!=b)
        {
            if(a>b)a/=2;
            else b/=2;
        }
	cout<<a<<endl;
    }
    return 0;
}

力扣 222. 完全二叉树的节点个数

题目:

给出一个完全二叉树,求出该树的节点个数。

说明:

完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例:

输入: 
    1
   / \
  2   3
 / \  /
4  5 6

输出: 6

代码:

class Solution {
public:
	int countNodes(TreeNode* root) {
		if (!root)return 0;
		return countNodes(root->left) + countNodes(root->right) + 1;
	}
};

力扣 919. 完全二叉树插入器

完全二叉树 是每一层(除最后一层外)都是完全填充(即,节点数达到最大)的,并且所有的节点都尽可能地集中在左侧。

设计一种算法,将一个新节点插入到一个完整的二叉树中,并在插入后保持其完整。

实现 CBTInserter 类:

  • CBTInserter(TreeNode root) 使用头节点为 root 的给定树初始化该数据结构;
  • CBTInserter.insert(int v)  向树中插入一个值为 Node.val == val的新节点 TreeNode。使树保持完全二叉树的状态,并返回插入节点 TreeNode 的父节点的值
  • CBTInserter.get_root() 将返回树的头节点。

示例 1:

输入
["CBTInserter", "insert", "insert", "get_root"]
[[[1, 2]], [3], [4], []]
输出
[null, 1, 2, [1, 2, 3, 4]]

解释
CBTInserter cBTInserter = new CBTInserter([1, 2]);
cBTInserter.insert(3);  // 返回 1
cBTInserter.insert(4);  // 返回 2
cBTInserter.get_root(); // 返回 [1, 2, 3, 4]

提示:

  • 树中节点数量范围为 [1, 1000] 
  • 0 <= Node.val <= 5000
  • root 是完全二叉树
  • 0 <= val <= 5000 
  • 每个测试用例最多调用 insert 和 get_root 操作 104 次

class CBTInserter {
public:
    CBTInserter(TreeNode* root) {
        this->root=root;
        num=CountNodes(root);
    }
    
    int insert(int val) {
        int len = GetBitLength(++num);
        auto p = root;
        for(int i=len-2;i;i--){
            if(num&(1<<i))p=p->right;
            else p=p->left;
        }
        if(num&1)p->right=new TreeNode(val);
        else p->left=new TreeNode(val);
        return p->val;
    }
    
    TreeNode* get_root() {
        return root;
    }
    TreeNode* root;
    int num;
};

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值