4.1 基本知识
树叶、深度、高度
树叶:没有儿子的节点
深度:从根到该节点的长度
高度:从该节点到一片树叶的最长路径的长
树的实现
兄弟法
struct TreeNode{
datatype data;
TreeNode *FirstChild; //第一个孩子
TreeNode *NextSibling; //下一兄弟
}
数组法
class Node {
public:
int val;
vector<Node*> children;
Node() {}
Node(int _val) {
val = _val;
}
Node(int _val, vector<Node*> _children) {
val = _val;
children = _children;
}
};
树的遍历及应用
目录
UNIX,VAX/VMX和DOS内的许多常用操作系统中的目录结构。
遍历目录(先序遍历)
4.2 二叉树
定义
二叉树是一棵树,每个节点都不能有多于两个的儿子。
实现
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
表达式数
因为很多操作都是二元的。所以刚好用二叉树来表示。
4.3 二叉查找树
定义
每个节点的左子树中所有值小于该节点的值,右子树所有关键字值大于该节点的值。
实现
重点关注insert和delete的实现
#include<iostream>
using namespace std;
class TreeNode {
public:
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int num):val(num), left(NULL), right(NULL){}
};
class BST {
public:
BST():m_root(NULL){}
void insert(int val);
void remove(int val);
TreeNode* findMin();
TreeNode* findMax();
void _insert(TreeNode *&root, int val);
void _remove(TreeNode *&root, int val);
TreeNode* _findMin(TreeNode *root);
TreeNode* _findMax(TreeNode *root);
private:
TreeNode* m_root;
};
void BST::insert(int val) {
_insert(m_root, val);
}
//这里需要传入指针的引用,当我们把一个指针做为参数传一个函数时,其实是把指针的副本传递给了函数,
//需要改变传入的指针指向的地址,所以需要引用
void BST::_insert(TreeNode *&root, int val) {
if (root == NULL) {
root = new TreeNode(val);
return;
}
if (val > root->val)
_insert(root->right, val);
else if (val < root->val)
_insert(root->left, val);
//相等则不变
}
void BST::remove(int val) {
_remove(m_root, val);
}
void BST::_remove(TreeNode *&root, int val) {
if (root == NULL) {
cerr << "二叉搜索树为空" << endl;
exit(1);
}
if (val < root->val)
_remove(root->left, val);
else if(val > root->val)
_remove(root->right, val);
//等于根节点时
else {
//如果左右节点都在,用右节点的最小值代替
if (root->left && root->right) {
TreeNode *tmp = _findMin(root->right);
root->val = tmp->val;
_remove(root->right, root->val);
}
//1/0个孩子
else {
//要保存
TreeNode* tmp = root;
if (root->left == NULL)
root = root->right;
if (root->right == NULL)
root = root->left;
delete(tmp);
}
}
}
TreeNode* BST::findMax() {
return _findMax(m_root);
}
TreeNode* BST::_findMax(TreeNode *root) {
if (root == NULL) {
cerr << "二叉搜索树为空" << endl;
exit(1);
}
//要保证root->right存在,如果while(root)会返回空
while (root->right) {
root = root->right;
}
return root;
}
TreeNode* BST::findMin() {
return _findMin(m_root);
}
TreeNode* BST::_findMin(TreeNode *root) {
if (root == NULL) {
cerr << "二叉搜索树为空" << endl;
exit(1);
}
//要保证root->left存在,如果while(root)会返回空
while (root->left) {
root = root->left;
}
return root;
}
int main() {
BST my_bst;
int i = 10;
while (i--) {
my_bst.insert(i);
}
my_bst.remove(9);
cout << my_bst.findMax()->val << endl;
}
缺点
容易失去平衡,操作耗时增加。可以添加“平衡”作为附加条件来解决这个问题,即任何节点的深度均不得过深。
4.4 AVL树
定义
左右子树高度最多差1的二叉搜索树。
单旋转双旋转
见书
4.6 树的遍历
见整理