性质
基本性质:二叉树_百度百科
关于二叉树的深度(高度)涉及到结点的层数,有的教材规定根结点在第\(0\)层,有的则规定根结点在第\(1\)层。
这里全部以《数据结构-C语言版》(严蔚敏,吴伟民版)为准:高度和深度为同一个概念,根节点在第1层,树的高度是看一共有几层。 高度为\(h\)的完全二叉树,最多有\(2^{n}-1\)个节点,第\(k\)层最多有\(2^{k-1}\)个节点。 含有\(n\)个节点的完全二叉树,高度为\(log(n)+ 1\)下取整。
完全二叉树:
如果第一个元素下标为\(1\),则第\(k\)个元素的左孩子为\(2*k\),右孩子为\(2*k+1\),父节点为 \(k / 2\) 下取整,最后一个父节点为 \(length / 2\) 下取整。
如果第一个元素下标为\(0\),则第\(k\)个元素的左孩子为\(2*k+1\),右孩子为\(2*k+2\),父节点为 \((k - 1)/ 2\) 下取整,最后一个父节点为 \(length / 2\) 下取整后减一。
二叉树的前驱后继节点,表示中序遍历时,一个节点的前一个和后一个。
高度为\(h\)的完全二叉树,最多有\(2^{h}-1\)个节点。
节点为\(n\)的完全二叉树,高度为\(log(n)\)。
二叉树的遍历
二叉树的有三种遍历方式,先中后序遍历,“先、中、后”表示根节点的遍历次序。
先序:先遍历分支的根节点,再遍历左子树,最后遍历右子树。
先序序列:\(ABDFECGHI\)
中序:先遍历分支的左子树,再遍历根节点,最后遍历右子树。
中序序列:\(DBEFAGHCI\)
后序:先遍历分支的左子树,再遍历右子树,最后遍历根节点。
后序序列:\(DEFBHGICA\)
二叉树遍历的实现
后序遍历非递归,是借用两个栈A,B,用A栈访问,压栈顺序为中左右(先序为中右左),把这些节点再存到B栈里,最后一起出栈。
//先序
void preorderUnRecur(BTree T) {
stack<BTree>s;
s.push(T);
while (!s.empty()) {
T = s.top();
s.pop();
cout << T->data << " ";
if (T->Right)
s.push(T->Right);
if (T->Left)
s.push(T->Left);
}
cout << endl;
}
//中序
void inorderUnRecur(BTree T) {
if (!T)return;
stack<BTree>s;
while (!s.empty() || T) {
if (T) {
s.push(T);
T = T->Left;
}
else {
T = s.top(); s.pop();
cout << T->data << " ";
T = T->Right;
}
}
cout << endl;
}
//后序
void postorderUnRecur(BTree T) {
if (!T)return;
stack<BTree>s1,s2;
s1.push(T);
while (!s1.empty()) {
T = s1.top(); s1.pop();
s2.push(T);
if (T->Left)s1.push(T->Left);
if (T->Right)s1.push(T->Right);
}
while (!s2.empty()) {
cout << s2.top()->data << " ";
s2.pop();
}
cout << endl;
}
递归实现,相比来说就比较简单了:
void Inorder(BTree t) {
if (!t)return;
Inorder(t->Left);
cout << t->data << " ";
Inorder(t->Right);
}
void Preorder(BTree t) {
if (!t)return;
cout << t->data << " ";
Preorder(t->Left);
Preorder(t->Right);
}
void Postorder(BTree t) {
if (!t)return;
Postorder(t->Left);
Postorder(t->Right);
cout << t->data << " ";
}
二叉树的构建
二叉树的建立一般有两种方法:
(1)用数组的方式,或者一个个输入,按照节点的顺序,用一个特殊值(比如0,# )表示当前位置没有节点。但这样总归是会出现冲突的,比如某个节点的值就是0, # 的ASCII值。就不做写了。
(2)给定包含中序序列的两个序列。以下为 给定前序、中序序列时,创建二叉树。
通过包含中序序列(只有前后序列创建出的二叉树不唯一)的两个序列可以推出唯一的二叉树。
typedef struct BTNode
{
int data;
struct BTNode* Left;
struct BTNode* Right;
}*BTree;
void PreAndInToPost(int* pre, int* in, int length) {
if (length == 0) return;
int rootIndex;
BTree BT = new BTNode;
BT->data = *pre;
for (rootIndex = 0; in[rootIndex] != *pre; rootIndex++);
PreAndInToPost(pre + 1, in, rootIndex);
PreAndInToPost(pre + rootIndex + 1, in + rootIndex + 1, length - (rootIndex + 1));
cout << BT->data << " ";
}
void PostAndInToPre(int* in, int* post, int length) {
if (length == 0) return;
int rootIndex;
BTree BT = new BTNode;
BT->data = *(post + length - 1);
for (rootIndex = length - 1; in[rootIndex] != *(post + length - 1); rootIndex--);
cout << BT->data << " ";
PostAndInToPre(in, post, rootIndex);
PostAndInToPre(in + rootIndex + 1, post + rootIndex, length - (rootIndex + 1));
}
完整测试代码如下:
#include <iostream>
using namespace std;
typedef char ElemType;
typedef struct BTNode
{
ElemType data;
struct BTNode* Left;
struct BTNode* Right;
}*BTree;
BTree creat_tree_from_pre_inorder(ElemType* pre, ElemType* in, int length) {
if (length == 0) return NULL;
int rootIndex;
BTree BT = new BTNode;
//将当前根节点入树
BT->data = *pre;
for (rootIndex = 0; in[rootIndex] != *pre; rootIndex++);
BT->Left = creat_tree_from_pre_inorder(pre + 1, in, rootIndex);
BT->Right = creat_tree_from_pre_inorder(pre + rootIndex + 1, in + rootIndex + 1, length - (rootIndex + 1));
return BT;
}
BTree creat_tree_from_post_inorder(ElemType* in, ElemType* post, int length) {
if (length == 0) return NULL;
int rootIndex;
BTree BT = new BTNode;
//将当前根节点入树
BT->data = *(post + length - 1);
for (rootIndex = length - 1; in[rootIndex] != *(post + length - 1); rootIndex--);
BT->Left = creat_tree_from_post_inorder(in, post, rootIndex);
BT->Right = creat_tree_from_post_inorder(in + rootIndex + 1, post + rootIndex/*删掉post的最后一个*/, length - (rootIndex + 1));
return BT;
}
void Inorder(BTree BT) {
if (!BT)return;
Inorder(BT->Left);
cout << BT->data << " ";
Inorder(BT->Right);
}
void Preorder(BTree BT) {
if (!BT)return;
cout << BT->data << " ";
Preorder(BT->Left);
Preorder(BT->Right);
}
void Postorder(BTree BT) {
if (!BT)return;
Postorder(BT->Left);
Postorder(BT->Right);
cout << BT->data << " ";
}
int main() {
char pre[] = "ABDGHCEIF";
char in[] = "GDHBAEICF";
char post[] = "GHDBIEFCA";
BTree T1 = creat_tree_from_pre_inorder(pre, in, strlen(in));
BTree T2 = creat_tree_from_post_inorder(in, post, strlen(in));
Postorder(T1);
cout << endl;
Preorder(T1);
cout << endl;
return 0;
}
相关小算法
获取二叉树的深度
int height(BTree T) {
if (T == NULL)
return 0;
int left = height(T->Left);
int right = height(T->Right);
return left >= right ? left + 1 : right + 1;
}