sincerit 二叉树

树的基本术语
结点的度:结点拥有的子树的数目。
叶子:度为零的结点。
分支结点:度不为零的结点。
树的度:树中结点的最大的度。

层次:根结点的层次为1,其余结点的层次等于该结点的双亲结点的层次加1。
树的高度:树中结点的最大层次。
无序树:如果树中结点的各子树之间的次序是不重要的,可以交换位置。
有序树:如果树中结点的各子树之间的次序是重要的, 不可以交换位置。
森林:0个或多个不相交的树组成。对森林加上一个根,森林即成为树;删去根,树即成为森林。

二叉树是树的特殊一种,具有如下特点:
1、每个结点最多有两颗子树,结点的度最大为2。
2、左子树和右子树是有顺序的,次序不能颠倒。
3、即使某结点只有一个子树,也要区分左右子树。

满二叉树
定义:所有的分支结点都存在左子树和右子树,并且所有的叶子结点都在同一层上,这样就是满二叉树
在这里插入图片描述
由满二叉树的定义,得到其特点为:
叶子只能出现在最下一层。
非叶子结点度一定是2.
在同样深度的二叉树中,满二叉树的结点个数最多,叶子树最多。
性质:

  1. 如果一颗树深度为h,最大层数为k,且深度与最大层数相同,即k=h;
  2. 它的叶子数是: 2^(h-1)
  3. 第k层的结点数是: 2^(k-1)
  4. 总结点数是: 2^k-1 (2的k次方减一)
  5. 总节点数一定是奇数。
  6. 树高:h=log2(n+1)。

完全二叉树
完全二叉树:除了最大的层次即成为一颗满二叉树且层次最大那层所有的结点均向左靠齐,即集中在左面的位置上,不能有空位置。
自己的话说就是除了最后一层,剩下的是满二叉树,最后一层如果有叶子结点,也是先满足左结点,不存在只有右结点
在这里插入图片描述
由完全二叉树定义得到其特点:
叶子结点只能出现在最下一层(满二叉树继承而来)
最下层叶子结点一定集中在左 部连续位置。
倒数第二层,如有叶子节点,一定出现在右部连续位置。
同样结点树的二叉树,完全二叉树的深度最小(满二叉树也是对的)。

性质
二叉树有以下几个性质:TODO(上标和下标)
性质1:二叉树第k层上的结点数目最多为 2^(k-1) (k≥1)。
性质2:深度为k的二叉树至多有2^k-1个结点(k≥1)。
性质3:包含n个结点的二叉树的高度至少为log2 (n+1)。
性质4:在任意一棵二叉树中,设一个结点为i(从1开始编号)则其父节点为i/2,2i为左子节点,2i+1为右子节点.

链表实现

1.二叉树的构建
https://blog.csdn.net/fansongy/article/details/6798278/

#include <stdio.h>
#include <cstring>
struct Node {
  char data; // 数据域
  Node* Lc; // 左子树 
  Node* Rc; // 右子树 
};
typedef Node node;
// 递归构建二叉树
node* buildBinaryTree(node* Root) {
  char ch;
  scanf("%c", &ch);
  if (ch == '#') return NULL;
  Root = new node();
  Root->data = ch;
  Root->Lc = buildBinaryTree(Root->Lc);
  Root->Rc = buildBinaryTree(Root->Rc);
  return Root;
} 
// 前序输出验证
void preorder(node* root) {
  if (root) {
    printf("%c", root->data);
    preorder(root->Lc);
    preorder(root->Rc);
  }
} 
 
int main() {
  node* root;
  root = buildBinaryTree(root); // 为啥函数是node*而不是node  
  preorder(root);
} 
// 例子  ABD##E##CF##G##
//             A 
//          /      \
//         B        C
//        / \       / \
//       D   E     F   G
//      / \  / \  / \ / \
//     #  # #  #  # ##   #

2.二叉树的前序,中序,后序,层序遍历
前序遍历:根节点->左子树->右子树
中序遍历:左子树->根节点->右子树
后序遍历:左子树->右子树->根节点
在这里插入图片描述
前序:abdefgc
中序:debgfac
后序:edgfbca

#include <stdio.h>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
struct Node {
  char data; // 数据域
  Node* Lc; // 左子树 
  Node* Rc; // 右子树 
};
typedef Node node;
// 递归构建二叉树
node* buildBinaryTree(node* Root) {
  char ch;
  scanf("%c", &ch);
  if (ch == '#') return NULL;
  Root = new node();
  Root->data = ch;
  Root->Lc = buildBinaryTree(Root->Lc);
  Root->Rc = buildBinaryTree(Root->Rc);
  return Root;
} 
// 前序输出验证
void preorder(node* root) {
  if (root) {
    printf("%c", root->data);
    preorder(root->Lc);
    preorder(root->Rc);
  }
} 
 
void midorder(node* root) {
  if (root) {
    midorder(root->Lc);
    printf("%c", root->data);
    midorder(root->Rc);
  }
}

void lastorder(node* root) {
  if (root) {
    lastorder(root->Lc);
    lastorder(root->Rc);
    printf("%c", root->data);
  }
}
// 层次遍历:即每一层从左向右输出
void levelorder(node* root) {
  queue<node*> que;
  if (root) que.push(root);
  while (que.size()) {
    node* t = que.front();
    printf("%c", t->data);
    if (t->Lc != NULL) que.push(t->Lc);
    if (t->Rc != NULL) que.push(t->Rc);
    que.pop();
  }
}
 
int main() {
  node* root;
  root = buildBinaryTree(root); // 为啥函数是node*而不是node  
  preorder(root);
  printf("\n");
  midorder(root);
  printf("\n");
  lastorder(root);
  printf("\n");
  levelorder(root);
} 
// 例子  ABD##E##CF##G##

数组实现
二叉树的构建
https://blog.csdn.net/qq_36459536/article/details/78238826

#include <stdio.h>
#include <math.h>
#include <cstring>
int node[100];
void buildTree(int root) {
  int k;
  scanf("%d", &k);
  if (k) {
    node[root] = k;
    buildTree(root*2);
    buildTree(root*2+1);
  } else return;
} 
// https://blog.csdn.net/qq_36459536/article/details/78238826
void print(int root) {
  if (node[root] != 0) {
    printf("%d", node[root]);
    print(root*2);
    print(root*2+1);
  }
}
int main() {
  buildTree(1);
  printf("ok\n");
  print(1);
}
// 1 2 3 4 5 0 0 0 0 0 0

二叉树的前序,中序,后序,层序遍历

#include <stdio.h>
#include <math.h>
#include <queue>
#include <cstring>
#include<iostream>
using namespace std;
int node[100];
void buildTree(int root) {
  int k;
  scanf("%d", &k);
  if (k) {
    node[root] = k;
    buildTree(root*2);
    buildTree(root*2+1);
  } else return;
} 

void preorder(int root) {
  if (node[root] != 0) {
    printf("%d ", node[root]);
    preorder(root*2);
    preorder(root*2+1);
  }
}
void midorder(int root) {
  if (node[root] != 0) {
    midorder(root*2);
    printf("%d ", node[root]);
    midorder(root*2+1);
  }
}

void lastorder(int root) {
  if (node[root] != 0) {
    lastorder(root*2);
    lastorder(root*2+1);
    printf("%d ", node[root]);
  }
}


void levelorder(int root) {
  queue<int> que;
  if (node[root]) que.push(root);
  while (que.size()) {
    int t = que.front();
    printf("%d ", node[t]);
    if (node[2*t]) que.push(2*t);
    if (node[2*t+1]) que.push(2*t+1);
    que.pop();
  }
}
int main() {
  int root = 1;
  memset(node, 0, sizeof(node));
  buildTree(root);
  preorder(root);
  printf("\n");
  midorder(root);
  printf("\n");
  lastorder(root);
  printf("\n");
  levelorder(root);
}
// 1 2 3 4 5 0 0 0 0 0 0
// 1 2 4 0 0 5 0 0 3 6 0 0 7 0 0

二叉树已知两个遍历的顺序求第三个顺序
已知前序中序求后序
已知前序后序求中序
已知后序中序求前序
已知后序中序求层序

猜你喜欢

转载自blog.csdn.net/sincerit/article/details/84503149