二叉树 概念+代码

 树


空树和非空树

树是一个递归的定义,根结点除外剩余的部分都可以看作为一棵树。

子树之间是互不相交的

内部节点:除了树根和子叶节点

树根是第一层(不统一,不同书的描述不同。)

 

树的存储

  • 顺序存储
  1. 双亲表示法           优点:找双亲方便                缺点:找孩子不容易
  2. 孩子表示法           优点:找孩子方便                缺点:树的节点最大度 为开辟的空间,很浪费空间。  找双亲不方便
  3. 双亲孩子表示法     优点:找孩子和双亲方便       缺点:耗费空间
  • 链式存储
  1. 孩子链表表示法      把孩子放在头节点后面  类似于链式前向星表示
  2. 孩子兄弟表示法      左指针长子 右指针兄弟        根据孩子兄弟表示法把任何树都可以转化为二叉树(相互转化)

 森林把每颗树树根看成兄弟

 

二叉树 


 

用处比较多

每一层是上一层的2倍

任何一颗二叉树,叶子节点数为n0,度数为2的节点为n2,n0=n2+1

n=n0+n1+n2总节点数,节点数等于分支数加一;n=1*n1+2*n2+1;

1*n1+2*n2+1 = n0+n1+n2  故,得到n0=n2+1

 

二叉树存储

  • 顺序存储:
  1. 补零补成完全二叉树,然后句可以按顺序存储。        缺点   补零可能太多。
  2. 完全二叉树  可以 顺序存储
  3. l[]数组 和 r[]数组    必须指明根root节点   经常用
  • 链式存储:
  1. lchild  data  rchild 

 

二叉树遍历

先序遍历:左右         递归

中序遍历:左右         递归

后序遍历:左右根         递归

层次遍历:一层一层访问(同一层从左向右)     方法:队列         出队的同时孩子进去

 

已知先序和中序、后序和中序要得到另外一个序列其实拆解都是中序序列。

空就结束,不操作。

 

 

 

题目一:补空创建二叉树

输入:补空序列 创建二叉树

 1 #include <iostream>
 2 #include <queue>
 3 
 4 using namespace std;
 5 
 6 // 定义二叉树存储结构
 7 struct Bonde{
 8     char data;
 9     struct Bonde *lchild, *rchild;
10 };
11 typedef struct Bonde *Btree;
12 typedef struct Bonde Bonde;  // 给看结构体起的别名
13 
14 // 创建二叉树函数
15 void Createtree(Btree &T)
16 {
17     // 按先序次序输入二叉树中结点的值(一个字符,创建二叉链表表示的二叉树T)
18     char ch;
19     cin >> ch;
20     if(ch == '#')
21         T = NULL;    //递归结束,建空树
22     else{
23         T = new Bonde;
24         T->data = ch;     // 生成根结点
25         Createtree(T->lchild);   //  递归创建做子树
26         Createtree(T->rchild);   //  递归创建右子树
27     }
28 }
29 
30 int Depth(Btree T){  // 求二叉树的深度
31     int m, n;
32     if(T == NULL)  // 如果为空树,c深度为0
33         return 0;
34     else{
35         m = Depth(T->lchild);  // 递归计算左子树深度
36         n = Depth(T->rchild);  // 递归计算右子树深度
37         if(m>n)
38             return m+1;  // 返回左右子树最大值加1
39         else
40             return n+1;
41     }
42 }
43 
44 int main(){
45     Btree mytree;
46     cout << "按先序次序输入二叉树中国结点的值(孩子为空是输入#),创建一颗二叉树" << endl;
47     // ABD##E##CF#G###
48     Createtree(mytree);  // 创建二叉树
49     cout << endl;
50     cout << "二叉树的深度为:" << Depth(mytree) << endl;
51     return 0;
52 }
View Code

 

ABD##E##CF#G###
按先序次序输入二叉树中国结点的值(孩子为空是输入#),创建一颗二叉树

二叉树的深度为:4
Program ended with exit code: 0

 

 题目二:二叉树遍历     前序、中序、后序、层次遍历

 1 #include <iostream>
 2 #include <queue>
 3 using namespace std;
 4 
 5 struct Bonde{
 6     char data;
 7     struct Bonde *lchild, *rchild;
 8 };
 9 
10 typedef struct Bonde Bonde;
11 typedef struct Bonde *Btree;
12 
13 void Createtree(Btree &T){
14     char ch;
15     cin >> ch;
16     if(ch == '#')
17         T = NULL;
18     else{
19         T = new Bonde;
20         T->data = ch;
21         Createtree(T->lchild);
22         Createtree(T->rchild);
23     }
24 }
25 
26 void preorder(Btree T){  // 先序遍历
27     if(T){
28         cout << T->data << " ";
29         preorder(T->lchild);
30         preorder(T->rchild);
31     }
32 }
33 
34 void inorder(Btree T){  // 中序遍历
35     if (T) {
36         inorder(T->lchild);
37         cout << T->data << " ";
38         inorder(T->rchild);
39     }
40 }
41 
42 void posorder(Btree T){  // 后序遍历
43     if (T) {
44         posorder(T->lchild);
45         posorder(T->rchild);
46         cout << T->data << " ";
47     }
48 }
49 
50 // 只有通过指针才能调用左右孩子
51 bool Leveltraverse(Btree T){  // 层次遍历
52     Btree p;
53     if(!T)
54         return false;
55     queue<Btree> Q;  // 创建一个普通队列(先进先出),里面存放指针类型
56     Q.push(T);  // 根指针入队
57     while (!Q.empty()) {
58         p = Q.front();  // 取出对头元素作为当前扩展节点livenode
59         Q.pop();  // 队头元素出队
60         cout << p->data << " ";
61         if(p->lchild)
62             Q.push(p->lchild);   // 左孩子入队
63         if(p->rchild)
64             Q.push(p->rchild);   // 右孩子入队
65     }
66     return true;
67 }
68 
69 
70 int main(){
71     Btree mytree;
72     cout << "按先序层次输入二叉树中结点的值(孩子为空时输入#),创建一颗二叉树" << endl;
73     Createtree(mytree);  // 创建二叉树
74     cout << endl;
75     cout << "二叉树的先序遍历结果:" << endl;
76     preorder(mytree); // 先序遍历二叉树
77     cout << endl;
78     cout << "二叉树的中序遍历结果:" << endl;
79     inorder(mytree);  // 中序遍历二叉树
80     cout << endl;
81     cout << "二叉树的后序遍历结果:" << endl;
82     posorder(mytree); // 后序遍历二叉树
83     cout << endl;
84     cout << "二叉树的层次遍历结果:" << endl;
85     Leveltraverse(mytree); // 层次遍历二叉树
86     return 0;
87 }
View Code

 

按先序层次输入二叉树中结点的值(孩子为空时输入#),创建一颗二叉树
ABD##E##CF#G###

二叉树的先序遍历结果:
A B D E C F G 
二叉树的中序遍历结果:
D B E A F G C 
二叉树的后序遍历结果:
D E B G F C A 
二叉树的层次遍历结果:
A B C D E F G 
Program ended with exit code:
0

 

 

 题目三:二叉树还原  先序和中序得二叉树     后序和中序得二叉树

思路:

  1. 先序找根
  2. 中序分左右

 函数(先序序列开始位置, 中序序列开始位置, 序列长度)

  1 #include <iostream>
  2 using namespace std;
  3 
  4 typedef struct node{
  5     char data;
  6     struct node *lchild, *rchild;
  7 }BiTNode, *BiTree;
  8 
  9 // 也就是说BitNode是struct的别名,BiTree是struct的指针,指针只是指向地址对象的,不能用来创建对象,而BitNode是可以用来创建对象实体的
 10 
 11 BiTree pre_mid_createBiTree(char *pre, char *mid, int len){   // 前序中序还原建立二叉树
 12     if(len == 0)
 13         return NULL;
 14     char ch = pre[0];  // 找打先序序列中的第一个结点
 15     int index = 0;
 16     while(mid[index]!=ch){  // 在中序中
 17         index++;
 18     }
 19     BiTree T = new BiTNode; // 创建根节点
 20     T->data = ch;
 21     T->lchild = pre_mid_createBiTree(pre+1, mid, index);  // 建立右子树
 22     T->rchild = pre_mid_createBiTree(pre+index+1, mid+index+1, len-index-1);   // 建立右子树
 23     return T;
 24 }
 25 
 26 BiTree pro_mid_createBiTree(char *last, char *mid, int len){   // 后序中序还原二叉树
 27     if(len==0)
 28         return 0;
 29     char ch = last[len-1];  // 取到后序遍历顺序中最后一个结点
 30     int index = 0;  // 在中序序列中找根节点,并用index记录长度
 31     while (mid[index]!=ch)// 在中序序列中找根节点,左边边为该节点的左子树,右边为右子树
 32         index++;
 33     BiTree T = new BiTNode;  // 创建根结点
 34     T->data= ch;
 35     T->lchild = pro_mid_createBiTree(last, mid, index);  // 建立左子树
 36     T->rchild = pro_mid_createBiTree(last+index, mid+index+1, len-index-1);  // 建立右子树
 37     return T;
 38 }
 39 
 40 void pre_order(BiTree T){
 41     if(T){
 42         cout << T->data;
 43         pre_order(T->lchild);
 44         pre_order(T->rchild);
 45     }
 46 }
 47 
 48 void pro_order(BiTree T){
 49     if(T){
 50         pro_order(T->lchild);
 51         pro_order(T->rchild);
 52         cout << T->data;
 53     }
 54 }
 55 /*
 56  7
 57  A B D E C F G
 58  D B E A F G C
 59  D E B G F C A
 60  */
 61 int main(){
 62     BiTree T;
 63     int n;
 64     char pre[100], mid[100], last[100];
 65     cout << "1.前序中序还原二叉树\n";
 66     cout << "2.后序中序b还原二叉树\n";
 67     int choose = -1;
 68     while (choose!=0) {
 69         cout << "请选择:";
 70         cin >> choose;
 71         
 72         switch (choose) {
 73             case 1:
 74                 cout << "请输入节点的个数:" << endl;
 75                 cin >> n;
 76                 cout << "请输入前序序列:" << endl;
 77                 for(int i=0; i<n; i++)
 78                     cin >> pre[i];
 79                 cout << "请输入中序序列:" << endl;
 80                 for(int i=0; i<n; i++)
 81                     cin >> mid[i];
 82                 T = pre_mid_createBiTree(pre, mid, n);
 83                 cout << endl;
 84                 cout << "二叉树还原成功,输出其后序序列:" << endl;
 85                 pro_order(T);
 86                 cout << endl << endl;
 87                 break;
 88             case 2:
 89                 cout << "请输入节点的个数:" << endl;
 90                 cin >> n;
 91                 cout << "请输入后序序列:" << endl;
 92                 for(int i=0; i<n; i++)
 93                     cin >> last[i];
 94                 cout << "请输入中序序列:" << endl;
 95                 for(int i=0; i<n; i++)
 96                     cin >> mid[i];
 97                 T = pro_mid_createBiTree(last, mid, n);
 98                 cout << endl;
 99                 cout << "二叉树还原成功,输出其先序序列:" << endl;
100                 pre_order(T);
101                 cout << endl << endl;
102                 break;
103         }
104     }
105     return 0;
106 }
View Code

 

1.前序中序还原二叉树
2.后序中序b还原二叉树
请选择:1
请输入节点的个数:
7
请输入前序序列:
 A B D E C F G
请输入中序序列:
D B E A F G C

二叉树还原成功,输出其后序序列:
DEBGFCA

 

 

 题目四:二叉树的  叶子数  结点数

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 typedef struct Bnode{
 5     char data;
 6     struct Bnode *lchild, * rchild;
 7 }Bnode, *Btree;
 8 
 9 void Createtree(Btree &T){  // 引用传递 需要对T的进行修改的时候使用Btree &T, 不需要修改时候使用Btree T
10     char ch;
11     cin >> ch;
12     if(ch == '#')
13         T = NULL;
14     else
15     {
16         T = new Bnode;
17         T->data = ch;
18         Createtree(T->lchild);
19         Createtree(T->rchild);
20     }
21 }
22 
23 int NodeCount(Btree T){
24     // 求二叉树的结点个数
25     if(T == NULL)
26         return 0;
27     else
28         return NodeCount(T->lchild)+NodeCount(T->rchild)+1;  // 递归计算左右子树结点数之和
29 }
30 
31 int LeafCount(Btree T){
32     if(T == NULL)
33         return 0;
34     else
35         if(T->lchild==NULL && T->rchild==NULL)  // 左右子树均为空为子叶节点,则叶子数为1
36             return 1;
37         else
38             return LeafCount(T->lchild)+LeafCount(T->rchild); // 递归计算左右子树叶子节点之和
39 }
40 
41 int main(){
42     Btree mytree;
43     cout << "按先序输入二叉树结点的值(孩子为空时输入#),创建一颗二叉树" << endl;
44     // AB##E##CF#G###
45     Createtree(mytree);
46     cout << endl;
47     cout << "二叉树结点是为:" << NodeCount(mytree) << endl;
48     cout << "二叉树叶子数为:" << LeafCount(mytree) << endl;
49     return 0;
50 }
View Code

 

转载于:https://www.cnblogs.com/JCcodeblgos/p/11401423.html

<think>好的,用户想了解二叉树相关的概念、实现或算法。首,我需要明确二叉树的基本定义和特点,确保用户对基础概念有清晰的理解。接下来,根据用户提供的引用内容,特别是引用[1]中的分类,我应该详细说明二叉树的类型,比如满二叉树、完全二叉树、平衡二叉树等,每个类型都需要简明扼要的解释。 然后,关于实现部分,引用[3]和[4]提到了C++中的结构体或类定义,以及构造函数的实现。我需要用代码示例来展示如何创建二叉树节点,可能包括结构体定义和简单的创建方法。同时,用户可能对不同的遍历算法感兴趣,如前序、中序、后序和层序遍历,这些在引用[1]中有详细列举,需要分别说明它们的递归和非递归实现,并给出代码示例。 在算法方面,引用[2]提到了判断平衡二叉树的方法,这里需要解释其时间复杂度和空间复杂度。同时,用户可能还关心其他常见算法,如求深度、节点数目、搜索树的构建和操作等,这些都需要一一涵盖,并结合引用中的内容进行说明。 此外,用户可能希望了解二叉树的应用场景和优化方法,比如在数据结构中的实际应用或性能优化的技巧。需要确保回答结构清晰,分点列出,便于用户逐步理解。最后,根据用户的要求生成相关问题,这些问题应覆盖二叉树的不同方面,帮助用户进一步深入学习。 需要注意的是,所有数学表达式和公式必须正确使用LaTeX格式,行内公式用$...$,独立公式用$$...$$。同时,引用标识要自然地添加在相关内容末尾,确保引用来源准确无误。整个回答需要保持口语化,避免使用专业术语过于密集,适当分段,使用标题和代码块提高可读性。</think>### 二叉树详解算法实现 #### 一、基本概念 二叉树是每个节点最多有两个子节点的树结构,称为**左子树****右子树**。其核心性质包括层次结构、递归定义和路径唯一性[^1]。 #### 二、二叉树类型 1. **二叉树**:所有非叶子节点都有两个子节点,且所有叶子节点在同一层[^1] $$ \text{叶子节点数} = 2^{h-1} \quad (h为树的高度) $$ 2. **完全二叉树**:除最后一层外,其他层节点数达到最大值,最后一层节点左对齐 3. **平衡二叉树**:任意节点的左右子树高度差不超过1[^2] 4. **二叉搜索树**:左子树所有节点值小于根节点,右子树所有节点值大于根节点 #### 三、数据结构实现(C++示例) ```cpp struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; // 创建二叉搜索树示例 TreeNode* insertBST(TreeNode* root, int val) { if (!root) return new TreeNode(val); if (val < root->val) root->left = insertBST(root->left, val); else root->right = insertBST(root->right, val); return root; } ``` #### 四、核心算法 1. **遍历算法** - 前序遍历(根左右) ```python def preorder(root): if root: print(root.val) preorder(root.left) preorder(root.right) ``` - 层序遍历(队列实现) ```cpp void levelOrder(TreeNode* root) { queue<TreeNode*> q; q.push(root); while (!q.empty()) { TreeNode* node = q.front(); q.pop(); cout << node->val << " "; if (node->left) q.push(node->left); if (node->right) q.push(node->right); } } ``` 2. **平衡性判断** ```cpp bool isBalanced(TreeNode* root) { return checkHeight(root) != -1; } int checkHeight(TreeNode* node) { if (!node) return 0; int left = checkHeight(node->left); int right = checkHeight(node->right); if (left == -1 || right == -1 || abs(left-right) > 1) return -1; return max(left, right) + 1; } ``` 时间复杂度:$O(n)$,空间复杂度:$O(h)$(h为树高度) 3. **二叉搜索树操作** - 插入:时间复杂度$O(\log n)$(平衡情况下) - 删除:需处理三种情况(无子节点、单子节点、双子节点) #### 五、应用场景 1. 数据库索引(B树/B+树) 2. 表达式树(编译器设计) 3. 哈夫曼编码(数据压缩) 4. 决策树(机器学习)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值