c++二叉树

二叉树

满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。 //深度为k,有2^k-1个节点的二叉树。
完全二叉树:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。  //堆就是一棵完全二叉树,同时保证父子节点的顺序。   
image-20210805102531455 image-20210805103015119

1、二叉搜索树:二叉搜索树是有数值的了,二叉搜索树是一个有序树

1、若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2、若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3、它的左、右子树也分别为二叉排序树
image-20210805103621987

2、 平衡二叉搜索树: (AVL树)

1、一棵空树或它的左右两个子树的高度差的绝对值不超过1
2、并且左右两个子树都是一棵平衡二叉树

C++中map、set、multimap,multiset的底层实现都是平衡二叉搜索树

3、二叉树的存储方式:

1、链式存储方式就用指针 链式存储则是通过指针把分布在散落在各个地址的节点串联一起

image-20210805104742772

2、顺序存储方式就用数组 顺序存储的元素在内存是连续分布的

image-20210805104814738

数组实现存储二叉树的遍历:

如果父节点的数组下表是i,那么它的左孩子就是i * 2 + 1,右孩子就是 i * 2 + 2。

4、二叉树遍历方式

1、深度优先遍历:先往深走,遇到叶子节点再往回走。

  • - 前序遍历(递归法,迭代法)   中左右
    - 中序遍历(递归法,迭代法)   左中右
    - 后序遍历(递归法,迭代法)   左右中
    //前中后,其实指的就是中间节点的遍历顺序
    //栈其实就是递归的一种是实现结构
    //前中后序遍历的逻辑,可以借助栈使用非递归的方式来实现的
    

2、广度优先遍历:一层一层的去遍历 实现一般使用队列来实现

5、二叉树的定义

struct TreeNode {
    int val;
    TreeNode *right;
    TreeNode *left;
    TreeNode(int x) :val(x), left(NULL) ,right(NULL) {}   //构造函数
};

//链表定义
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) :val(x),next(NULL) {}   //构造函数
};
ListNode* head = new ListNode(5);
//ListNode* head = new ListNode();
//head->val = 5;

5、二叉树的递归遍历

1、确定递归函数的参数和返回值
2、确定终止条件
3、确定单层递归的逻辑
clss Solution {
public:
        void traversal(TreeNode *cur,vector<int> &vec) {  //前序遍历
            if(cur == NULL) return ;
            vec.push_back(cur->val);
            traversal(cur->left,vec);
            traversal(cur->right,vec);
        }
        void travesal(TreeNode *cur,vector<int> &vec) {   //中序遍历
            if(cur == NULL) return;
            travesal(cur->left,vec);
            vec.push_back(cur->val);
            travesal(cur->right,vec);
        }
        void travesal(TreeNode *cur,vector<int> &vec) {   //后序遍历
            if(cur == NULL) return;
            travesal(cur->left,vec);
            travesal(cur->right,vec);
            vec.push_back(cur->val);
        }
    
        vector<int> preorderTraverasl(TreeNode * root) {
            vector<int> result;
            travelsal(root,result);
            return result;
        }

};
//用栈实现二叉树遍历 
//栈先进后出 队列先进先出
//前序遍历是中左右,每次先处理的是中间节点,那么先将跟节点放入栈中,然后将右孩子加入栈,再加入左孩子。
class solution {
public:
        vector<int> preorderTraversal(TreeNode *root) {
            stack<TreeNode*> st;  //定义一个栈,每个节点的类型为 树节点指针
            vector<int> result;
            if(root == NULL ) return result;
            st.push(root);   // 先将根节点入栈
            //一直执行,直到栈为空,然后将左节点出栈,然后右节点。
            while(!st.empty()) {
                TreeNode* node = st.top(); //定义一个栈顶指针
                st.pop();                  //弹出根节点
                result.push_back(node->val); //将结果存在vector容器中
                if(node->right)  st.push_back(node->right); //右  (空节点不如栈)
                if(node->left)   st.push_back(node->left);  //左   
            }
            return result;
        }
};

//中序遍历(迭代法)
//处理:将元素放到result数组中
//遍历节点      指针的遍历来帮助访问节点,栈则用来处理节点上的元素。
//中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点  
class solution {
public:
    vector<int> inorderTraversal(TreeNode *root) {
        vector<int> result;
        stack<TreeNode*> st;    
        TreeNode* cur =root;   //curr定义为将要入栈的结点,初始化为root
        while(cur != NULL || !st.empty()) {
            if(cur != NULL) {  //指针访问节点,访问到最底层
                st.push(cur);  //将访问的节点放进栈
                cur = cur->left;
            }
            else {
                cur = st.top(); //从栈弹出数据,就是要放进数组的数据  
                st.pop();
                result.push_back(cur->val);  //中
                cur = cur ->right;           //右
            }
        }
        return result;
    }
};

//后序遍历
 if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
 if (node->right) st.push(node->right); // 空节点不入栈  
 reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了
        return result;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值