二叉树基础(上):什么样的二叉树适合用数组来存储?

二叉树基础(上):什么样的二叉树适合用数组来存储?

二叉树有哪几种存储方式?什么样的二叉树适合用数组来存储?

树(Tree)

每个元素就是一个节点,用来连线相邻节点之间的关系就是“父子关系”,没有父节点的节点是根结点,没有子节点的节点是叶节点

高度(Height):节点到叶子节点的最长路径(边数)

深度(Depth):根节点到这个节点所经历的边的个数

层数(level):节点的深度+1

树的高度 = 根节点的高度

即高度从下往上度量,深度是从上往下开始度量,层数的起点是1

二叉树(Binary Tree)

满二叉树和完全二叉树

如何存储一颗二叉树?

一种是基于指针或者引用的二叉链式存储法,一种是基于数组的顺序存储法

一:链式存储法,每个节点有三个字段,其中一个存储数据,另外两个是指向左右子节点的指针

二:基于数组的顺序存储法。把根节点存储在下标i=1的位置,左子节点存储在下标为 2 * i = 2 的位置,右子节点存储在2 * i +1 = 3 的位置,根节点的左子节点的的左子节点存储在 2 * i = 4 的位置,其右子节点存储在2 * i + 1 = 5的位置

总结是:节点X存储在数组中下标为i的位置,下标为2 * i的位置存储的是左子节点,下标为 2 * i +1存储的是右子节点,反过来下标为i / 2的位置存储的是其父节点,所以我们只要知道根节点存储的位置,可以通过下标计算,把整棵树串起来

堆和堆排序就是一种完全二叉树,存储方式就是数组

二叉树的遍历

前序遍历、中序遍历和后序遍历,前中后表示的是节点与它的左右子树节点遍历打印的先后顺序

前:对树中任意节点来说,先打印该节点,再打印它左子树,最后打印右子树

中:先打印其节点的左子树,再打印其节点,再打印其右子树

后:先打印左子树,再打印右子树,最后打印其节点

前中后遍历就是递归的过程,递推公式是:

前序遍历的递推公式:
preOrder(r) = print r->preOrder(r->left) ->preOrder(r->right)

中序遍历的递推公式:
inOrder(r) = inOrder(r->left) -> print r->inOder(r->right)

后序遍历的递推公式:
postOrder(r) = postOrder(r->left) ->postOrder(r->right) -> print r

代码为:

void preOrder(Node* root){
  if(root == null) return;
  print root;//为伪代码,表示打印root节点
  preOrder(root->left);
  preOrder(root->right);
}

void inOrder(Node* root){
  if(root == null) return;
  inOrder(root->left);
  print root;//打印root节点
  inOrder(root->right);
}

void postOrder(Node* root){
  if(root == null) return;
  postOrder(r->left);
  postOrder(r->right);
  print root;
}

每个节点最多会被访问两次,所以遍历操作的时间复杂度跟节点n成正比,即时间复杂度是O(n)

1.给定一组数据,1,3,5,6,9,10可以构建出多少种不同的二叉树?

(1)n个数,即n个节点,能构造出多少种不同形态的树

(2)n个数,有多少种不同的排列

(1)*(2)即为最终结果=n! 如果是完全二叉树,可以放在数组中,可以简化为数组中的元素有多少种组合方式

卡特兰数

2.如何实现按层遍历?

层序遍历,借助队列辅助即可,根节点先入队列,然后循环从队列中pop节点,将pop出来的节点的左子节点先入队列,右节点后入队列,依次循环,直到队列为空,遍历结束

vector<vector<int>> levelOrder(TreeNode* root){
  vector<vector<int>> vecRes;
  if(!root) return vecRes;
  vector<int> vecTemp;
  quene<TreeNode *> queneT1;
  queneT1.push(root);
  int nQueneSize = queneT1.size();
  while(nQueneSize > 0 ){
    for(int i = 0;i < nQueneSize;++i){
      TreeNode * pQuene = queneT1.front();
      vecTemp.push_back(pQuene->val);
      queneT1.pop();
      if(pQuene->left){
        queneT1.push(pQuene->left);
      }
      if(pQuene->right){
        queneT1.push(pQuene->right);
      }
    }
    nQueneSize = queneT1.size();
    vecRes.push_back(vecTemp);
    vecTemp.clear();
  }
  return vecRes;
}
发布了76 篇原创文章 · 获赞 9 · 访问量 9198

猜你喜欢

转载自blog.csdn.net/ywangjiyl/article/details/104333379