数据结构——二叉树
Posted クトリ・ノタ・セニオリス
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构——二叉树相关的知识,希望对你有一定的参考价值。
树的一些基本术语:(针对我个人觉得要必要列出来的
- 结点的度:结点拥有的子树数。
- 树的度:树内各结点度的最大值。
- 非终端结点:度不为0的结点称为非终端结点或分支结点。除根结点外,非终端结点也称为内部结点。
- 层次:根为第一层,不是第零层。
- 树的深度:树中结点的最大层次,深度也称为高度。
- 森林:是m(m>=0)棵互不相交的树的集合。对树中每个结点而言,其子树的集合即为森林。对森林加上一个根,森林即成为树;删去根,树即成为森林。
二叉树的一些性质:
- 在二叉树的第i层上至多有2i-1个结点(i>=1)。
- 深度为k的二叉树至多有2k-1个结点(k>=1)。
- 在任意一棵二叉树中,若终端结点(叶子结点)的个数为n0,度为2的结点数为n2,则n0=n2+1。
- 包含n个结点的二叉树的高度至少为log2 (n+1)。
- 具有n个结点的完全二叉树的深度为
二叉树的一些概念:
- 满二叉树:深度为k且含有2k-1个结点的二叉树。(即除叶子结点外,所有结点都有左儿子和右儿子。
- 完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
满二叉树
完全二叉树
非完全二叉树
补充:
根据遍历序列确定一棵二叉树:
先序序列+中序序列 >>>
先:根左右 → 第一个一定是根
中:左根右 → 根据先序找到一个根后,把序列由根划分成左子树和右子树
对左子树和右子树进行同样的操作,直到子树为空。(可见也是一种递归思想。
中序序列+后序序列 >>>
后:左右根 → 序列的最后一个为根
中:左根右 → 根据后序找到一个根后,把序列由根划分成左子树和右子树
对左子树和右子树进行同样的操作,直到子树为空。(递归
先序加后序是无法确定一颗二叉树的,因为由上可见,中序由先序或后序提供的根来确定左右子树,没有中序是无法完成这个递归过程的,也就无法确定一颗二叉树。
接下来就是二叉树的代码了,它实现了二叉树的基本存储结构和一些基本的操作:
ps:这里注意一下先序遍历建立二叉树时的数据输入,要按根左右的顺序注意-1结束符的输入。
例:1 2 3 -1 -1 4 5 -1 6 -1 -1 7 -1 -1 -1
1 #include<iostream> 2 #include<stdlib.h> 3 #include<queue> //层次遍历时要用到队列 4 using namespace std; 5 6 #define MAXSIZE 100 7 typedef int ElemType; 8 typedef int Status; 9 10 //二叉链表存储表示 11 typedef struct BiTNode 12 { 13 ElemType data; //结点数据域 14 struct BiTNode *lchild, *rchild; //左右孩子指针 15 }BiTNode, *BiTree; 16 17 //初始化,构造一个空树 18 void InitBT(BiTree &T) 19 { 20 T = NULL; 21 } 22 23 //先序遍历建立二叉树 24 void CreateBT(BiTree &T) 25 { 26 ElemType ch; 27 cin >> ch; 28 if (ch == -1) //输入元素,以-1结束 29 T = NULL; 30 else 31 { 32 T = (BiTNode *)malloc(sizeof(BiTNode)); //分配内存空间 33 T->data = ch; 34 CreateBT(T->lchild); //递归建立其左子树 35 CreateBT(T->rchild); //递归建立其右子树 36 } 37 } 38 39 //检查二叉树是否为空,空返回1,非空返回0 40 int EmptyBT(BiTree T) 41 { 42 if (T == NULL) 43 return 1; 44 else 45 return 0; 46 } 47 48 //二叉树的深度 49 int DepthBT(BiTree T) 50 { 51 if (T == NULL) //空树深度为0 52 return 0; 53 else 54 { 55 int a = DepthBT(T->lchild); //递归求左子树深度 56 int b = DepthBT(T->rchild); //递归求右子树深度 57 return (a > b ? (a + 1) : (b + 1)); //取最大的即为树的深度,注意加1 58 } 59 } 60 61 //查找二叉树BT中值为x的结点,若查找成功返回1,否则返回0 62 int FindBT(BiTree T, ElemType x) 63 { 64 if (T == NULL) 65 return 0; 66 if (T->data == x) 67 return 1; 68 if (FindBT(T->lchild, x) || FindBT(T->rchild, x)) //递归在它的左子树和右子树里面找 69 return 1; 70 else 71 return 0; 72 } 73 74 //先序遍历,根左右 75 void PreOrder(BiTree T) 76 { 77 if (T) //树非空 78 { 79 cout << T->data << " "; 80 PreOrder(T->lchild); 81 PreOrder(T->rchild); 82 } 83 } 84 85 //中序遍历,左根右 86 void InOrder(BiTree T) 87 { 88 if (T) 89 { 90 InOrder(T->lchild); 91 cout << T->data << " "; 92 InOrder(T->rchild); 93 } 94 } 95 96 //后序遍历,左右根 97 void PostOrder(BiTree T) 98 { 99 if (T) 100 { 101 InOrder(T->lchild); 102 InOrder(T->rchild); 103 cout << T->data << " "; 104 } 105 } 106 107 //层次遍历 108 void LevelOrder(BiTree T) 109 { 110 BiTree p; 111 if (T) 112 { 113 queue<BiTree>Q; //创建一个队列Q 114 Q.push(T); //将树入队 115 while (!Q.empty()) //队列非空 116 { 117 p = Q.front(); 118 Q.pop(); 119 cout << p->data << " "; 120 if (p->lchild) //先左子树出队 121 Q.push(p->lchild); 122 if (p->rchild) //后右子树出队 123 Q.push(p->rchild); 124 } 125 } 126 } 127 128 //叶子结点个数 129 int LeafCount(BiTree T) 130 { 131 if (!T) 132 return 0; 133 int count = 0; //计数器 134 if (!T->lchild && !T->rchild) //左右子树都为空,则为一个叶子结点 135 { 136 count++; 137 } 138 int a = LeafCount(T->lchild); //递归求其左子树叶子结点数 139 int b = LeafCount(T->rchild); //递归求其右子树叶子结点数 140 count += (a + b); 141 return count; 142 } 143 144 //总结点数 145 int NodeCount(BiTree T) 146 { 147 if (!T) 148 return 0; 149 else 150 return NodeCount(T->lchild) + NodeCount(T->rchild) + 1; //加一个根节点 151 } 152 153 //清除二叉树 154 void ClearBTree(BiTree &T) 155 { 156 if (T) 157 { 158 ClearBTree(T->lchild); 159 ClearBTree(T->rchild); 160 delete T; 161 T = NULL; 162 } 163 } 164 165 int main() 166 { 167 BiTree T; 168 int x; 169 170 T = NULL; 171 172 cout << "1.建立二叉树\\n"; 173 174 cout << "2.先序遍历二叉树\\n"; 175 176 cout << "3.中序遍历二叉树\\n"; 177 178 cout << "4.后序遍历二叉树\\n"; 179 180 cout << "5.层次遍历二叉树\\n"; 181 182 cout << "6.查找二叉树中元素\\n"; 183 184 cout << "7.计算二叉树的深度\\n"; 185 186 cout << "8.计算二叉树的叶子结点个数\\n"; 187 188 cout << "9.计算二叉树的结点总个数\\n"; 189 190 cout << "10.清除二叉树\\n"; 191 192 cout << "0.退出\\n"; 193 194 int choose = 0; 195 196 while (choose != -1) 197 { 198 cout << "请选择你要执行的操作:"; 199 cin >> choose; 200 switch (choose) 201 { 202 case 1: //先序遍历建立二叉树 203 cout << "请输入二叉树中元素,以-1结束:"; 204 CreateBT(T); 205 cout << "二叉树建立成功!" << endl; 206 break; 207 case 2: //先序遍历输出二叉树 208 PreOrder(T); 209 cout << endl; 210 break; 211 case 3: //中序遍历输出二叉树 212 InOrder(T); 213 cout << endl; 214 break; 215 case 4: //后序遍历输出二叉树 216 PostOrder(T); 217 cout << endl; 218 break; 219 case 5: //层次遍历输出二叉树 220 LevelOrder(T); 221 cout << endl; 222 break; 223 case 6: //查找二叉树中是否存在元素x 224 cout << "请输入要查找的元素x:"; 225 cin >> x; 226 if (FindBT(T, x)) 227 cout << "查找成功!" << endl; 228 else 229 cout << "查找失败!" << endl; 230 break; 231 case 7: //二叉树深度 232 cout << DepthBT(T) << endl; 233 break; 234 case 8: //叶子结点数 235 cout << LeafCount(T) << endl; 236 break; 237 case 9: //总结点数 238 cout << NodeCount(T) << endl; 239 break; 240 case 10://清除二叉树 241 ClearBTree(T); 242 cout << "清除成功!" << endl; 243 break; 244 case 0: //退出 245 exit(0); 246 break; 247 } 248 } 249 system("pause"); 250 return 0; 251 }
以上是关于数据结构——二叉树的主要内容,如果未能解决你的问题,请参考以下文章