二 叉 树

概念

二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。
二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树二叉树。
特点是每个节点最多只能有两棵子树,且有左右之分 。

特殊的二叉树

1、满二叉树如果一棵二叉树只有度为0的节点和度为2的节点,并且度为0的节点在同一层上,则这棵二叉树为满二叉树 。
2、完全二叉树深度为k,有n个节点的二叉树当且仅当其每一个节点都与深度为k的满二叉树中编号从1到n的节点一一对应时,称为完全二叉树 。
完全二叉树的特点是叶子节点只可能出现在层序最大的两层上,并且某个节点的左分支下子孙的最大层序与右分支下子孙的最大层序相等或大1 。
3.二叉排序树
4.平衡二叉树
5.红黑树

性质

  • 规定根节点的高度为1,度为i的节点个数为 ni:
    • n0=n2+1;
    • 高为h的非空叉树 :
      • 最多有 2 h − 1 2^h -1 2h1 个节点。
      • 第h层有 2 ( h − 1 ) 2 ^ ( h - 1 ) 2(h1) 个节点。
    • 高为h的非空完全二叉树:
      • 前h-1 层的节点个数和为 2 ( h − 1 ) − 1 2^(h-1)-1 2(h1)1
      • 总节点个数范围为 2 ( h − 1 ) 2^ (h-1) 2(h1) ~ 2 h − 1 2^h-1 2h1
      • 从上到下,从左到右依次编号,根节点序号为0 ,序号为i,(i>0)
        • 其双亲节点 =(孩子节点序号-1)/2,
        • 其左孩子节点=双亲序号*2+1,
        • 其右孩子节点=双亲序号*2+2。
        • 具有n个节点的的高度是 l o n g 2 ( n + 1 ) long2^(n+1) long2(n+1)向上取整,或 l o n g 2 n + 1 long2^n+1 long2n+1向下取整。

顺序存储结构

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

堆的实现

链式存储结构

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。

typedef struct tree
{
	int val;//值域
	struct tree *left;//它的左节点
	struct tree *right;//它的右节点
}tree; 

二叉树的创建和销毁

typedef struct tree
{
	int val;
	struct tree *l;
	struct tree *r;
}tree;

int res[] = { 1, 2, 3 ,0, 0, 4, 5, 0, 6, 0, 0, 7, 0, 0, 0 };
//根据一颗二叉树的先序创建树。

tree* get(int key)
{
	tree* temp = (tree*)malloc(sizeof(tree));
	if (temp == NULL) exit(1);
	temp->val = key;
	temp->l = NULL;
	temp->r = NULL;
	return temp;
}

tree* create(int* index)
{
	if (*n >= sizeof(res) / sizeof(res[0])) return;
	if (res[*index] == 0) 
	{
		(*index)++; 
		return NULL;
	}
	tree *root = buy(res[(*index)++]);
	root->l = create(index);
	root->r = create(index);
	return root;
}

void destory(tree* root)
{
	if (root == NULL)
	{
		return;
	}
	destory(root->l);
	destory(root->r);
	free(root);
	root = NULL;
}

二叉树的遍历(先,中,后,层)

非空二叉树:
先序=后序:只有一个根节点
先序和后序相反:高度=节点数的数
先序=中序:右单枝树
先序和中序相反:左单枝树
中序=后序:左单枝树
中序和后序相反:右单枝树

先序遍历(根,左,右)

递归
    void preorder(TreeNode* root, vector<int>& res) 
    {
        if (!root) return;
        res.push_back(root->val);
        preorder(root->left, res);
        preorder(root->right, res);
    }
    vector<int> preorderTraversal(TreeNode* root) 
    {
        vector<int> res;
        preorder(root, res);
        return res;
    }
非递归
vector<int> preorderTraversal(TreeNode* root) 
{
        vector<int>a;//用于保存遍历的结果
        stack<TreeNode*>s;//用于保存遍历时的中间节点
        if(root==nullptr) return a;
        TreeNode* p=root;
        while(!s.empty()||p)
        {
            while(p)
            {
                s.push(p);
                a.push_back(p->val);
                p=p->left;
            }
            p=s.top();s.pop();
            p=p->right;
        }
        return a;
    }

中序遍历(左,根,右)

递归
    void inorder(TreeNode* root, vector<int>& res) 
    {
        if (!root) return;
        inorder(root->left, res);
        res.push_back(root->val);
        inorder(root->right, res);
    }
    vector<int> inorderTraversal(TreeNode* root) 
    {
        vector<int> res;
        inorder(root, res);
        return res;
    }
非递归
vector<int> inorderTraversal(TreeNode* root) 
{
        vector<int> a;//用于保存遍历的结果
        stack<TreeNode*> s;//用于保存遍历时的中间节点
        if(!root) return a;
        TreeNode* p =root;
        while(!s.empty()||p)
        {
            while(p)
            {
                s.push(p);
                p=p->left;
            }
            p=s.top();s.pop();
            a.push_back(p->val);
            p=p->right;
        }
        return a;
}

后序遍历(左,右,根)

递归
    void postorder(TreeNode* root, vector<int>& res) 
    {
        if (!root) return;
        postorder(root->left, res);
        postorder(root->right, res);
        res.push_back(root->val);
    }
    vector<int> postorderTraversal(TreeNode* root) 
    {
        vector<int> res;
        postorder(root, res);
        return res;
    }
非递归
vector<int> postorderTraversal(TreeNode* root) 
{
        vector<int> a;//用于保存遍历的结果
        if(!root) return a;
        stack<TreeNode*> s;//用于保存遍历时的中间节点
        TreeNode* p=root,*t=nullptr;
        while(!s.empty()||p)
        {
            while(p)
            {
                s.push(p);
                p=p->left;
            }
            t=s.top();p=t->right;
            if(p) 
            {
            	t->right=nullptr;//一定要记得断开右子树,不然会死循环
            	continue;
            }
            a.push_back(t->val);
            s.pop();
        }
        return a;
    }
层序遍历
class Solution {
public:
vector<int> vec;
queue<TreeNode*> qu;
    vector<int> PrintFromTopToBottom(TreeNode* root) 
    {
		if(!root) return vec;
		qu.push(root);
		while(!qu.empty())
		{
			TreeNode* temp=qu.front();
			if(temp) 
			{
				vec.push_back(temp->val);
				qu.push(temp->left);
				qu.push(temp->right);
			}
			qu.pop();
		}
		return vec;
    }
};

若有误点,朋友请赐教
》 继续拓展///

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值