机试刷题笔记——二叉树

二叉树性质

1.二叉树的第k层至多有(2^(k-1))个节点
2.k层的二叉树至多有(2^k-1)个节点,最少有k个节点
3.对任何一颗二叉树,如果其叶节点数为n0,树中度为2的节点个数为n2,那么可以得到n0 = n2+1.

//证明过程
总节点数满足 n = n0 + n1 + n2    
除了根节点,每个节点对应一条边 e = 2n2 + n1 = n - 1
因此,有 2n2+ n1 =n0 + n1 + n2- 1
n2= n0 - 1 =>  
n0= n2 + 1
空链域:2n0 + n1 = n0 + n2 + 1 + n1 = n + 1

4.具有n个结点的完全二叉树深度为(log2(n))+1。

高度为h的二叉树最多有2{h}1个结点。反之,对于包含n个节点的二叉树的高度至少为log2(n+1)

5.对具有n个结点的完全二叉树,如果按照从上至下和从左至右的顺序对二叉树的所有结点从1开始编号,则对于任意的序号为i的结点有如下性质。
如果i>1,那么序号为i的结点的双亲节点序号为i/2。
如果i=1,那么序号为i的节点为根节点,无双亲节点。
如果2i<=n,那么序号为i的结点的左孩子结点序号为2i;
如果2i>n,那么序号为i的结点无左孩子;
如果2i+1<=n,那么序号为i的结点右孩子序号为2i+1;
如果2i+1>n,那么序号为i的结点无右孩子。

1.普通二叉树

存在不是两个子节点的节点。

2.完全二叉树

在这里插入图片描述
除了最后一层,其他各层的节点个数都达到最大,最后一层左对齐。

3.满二叉树

在这里插入图片描述

所有非叶子节点的度都是2,也就是一个节点要么没有子节点,要么就要有两个子节点。

4.完美二叉树在这里插入图片描述

完全二叉树加满二叉树。

5.二叉搜索树

所有

二叉树的遍历方式

在这里插入图片描述

前序遍历

排序CABEDGF
递归版本

void preorderTravesal(TreeNode * root,vector<int>&res)
{
if(!root)
return;
res.push_back(root->val);
if(root->left)
preorderTravesal(root->left,res);
if(root->right)
preorderTravesal(root->right,res);
}

非递归版本,使用栈进行存储

void preorderTravesal(TreeNode * root,vector<int>&res)
{
//如果为空树
if(!root)
return;
//栈
stack<TreeNode*> s;
//当前节点
TreeNode * node =root;
//判断是否存在
while(node||!s.empty())
{
//遍历到左子树
while(node)
{
s.push(node);
res.push_back(node->val);
node = node->left;
}
//栈顶节点
node = s.top();
//退出
s.pop();
//遍历右子树
node = node->right;
}
}

中序遍历

排序为ABCDEFG
递归版本

void midorderTravesal(TreeNode * root,vector<int>&res)
{
if(!root)
return;
if(root->left)
midorderTravesal(root->left,res);
res.push_back(root->val);
if(root->right)
midorderTravesal(root->right,res);
}
void midorderTravesal(TreeNode * root,vector<int>&res)
{
if(!root)
return;
stack<TreeNode*>q;
//记录当前节点
TreeNode * cur_node = root;
while(cur_node||!q.empty())
{
while(cur_node)
{
q.push(cur_node);
cur_node = cur_node->left;
}
cur_node = q.top();
q.pop();
res.push_back(cur_node->val);
cur_node = cur_node->right;
}
}

后序遍历

排序BACDFGE
递归版本

void postorderTravesal(TreeNode * root,vector<int>&res)
{
if(!root)
return;
if(root->left)
postorderTravesal(root->left,res);
if(root->right)
postorderTravesal(root->right,res);
res.push_back(root->val;
}

非递归版本

void postorderTraversal(TreeNode *root,vector<int>&res)
{
if(!root)
return;
stack<TreeNode*> s;
TreeNode *flag =NULL;
TreeNode *cur_node = root;
while(cur_node||!s.empty())
{
while(cur_node)
{
s.push(cur_node);
cur_node = cur_node->left;
}
cur_node = s.top();
if(!cur_node->right||flag == cur_node->right)
{
res.push_back(cur_node->val);
flag = cur_node;
s.pop();
cur_node = NULL;
}
else
{
cur_node = cur_node->right;
}
}
}

层序遍历

排序CAEBDGF

vector<vector<int>> levelorder(TreeNode * root)
{
vector<vector<int>> res;
if(root == NULL)
return;
queue<TreeNode*>q;
q.push(root);
TreeNode * cur_node;
while(!q.empty())
{
vector<int> tempv;
int sz = q.size();
while(sz--)
{
cur_node = q.front();
tempv.push_back(cur_node->val);
q.pop();
if(cur_node->left)
q.push(cur_node->left);
if(cur_node->right)
q.push(cur_node->right);
}
res.push_back(tempv);
}
}

找第k大/小

对于二叉搜索树来说,左子树所有值小于根节点,右子树所有值大于根节点。依据这个特性,我们可以简单得出结论:二叉搜索树上的第k小的节点即为中序遍历的第k个节点,第k大的节点在这里插入图片描述
第k小的代码如下
遍历版

    int count = 0;
    TreeNode* KthNode(TreeNode* root, int k)
    {
        if(root){ 
                TreeNode *cur_ans= KthNode(root->left, k);
                if(cur_ans) 
                  return cur_ans;
                if(++count == k) 
                  return root;
                ret = KthNode(root->right,k);
                if(cur_ans) 
                  return cur_ans;
        }
        return nullptr;
    }

非遍历版

//非遍历版
    int count = 0; //计数器
    TreeNode* cur_ans;
    void dfs(TreeNode * p){
        if(!p || count < 1)
            return;
        dfs(p->left);
        if(count == 1)
            cur_ans = p;
        if(--count > 0)
            dfs(p->right);
    }
	TreeNode* KthNode(TreeNode* root, int k)
    {
        cur_ans = nullptr;
        count = k;
		dfs(root);
        return cur_ans;
    }

保研机试题笔记,持续更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值