c语言sscanf函数的用法是什么
226
2022-09-13
【复习笔记】二叉排序树、平衡二叉树、哈夫曼树
文章目录
一、二叉排序树(Binary Search Tree)
二叉树结点定义1. 插入结点2. 构造二叉排序树3. 查找结点4. 删除结点
二、平衡二叉树(AVL树)
调整最小不平衡子树A
1. 在A的左孩子的左子树中插入导致不平衡(LL)2. 在A的右孩子的右子树中插入导致不平衡(RR)3. 在A的左孩子的右子树中插入导致不平衡(LR)4. 在A的右孩子的左子树中插入导致不平衡(RL)
判断平衡二叉树
三、哈夫曼树
1. 一些基本概念2. 构造哈夫曼树3. 哈夫曼树的基本性质4. 哈夫曼编码
一、二叉排序树(Binary Search Tree)
定义: 二叉排序树又称二叉查找树,对于任何一个结点满足条件:左子树结点值<根节点值<右子树结点值。二叉排序树中序遍历结果是一个升序序列。
以下便是一棵二叉排序树:
二叉树结点定义
struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {}};
1. 插入结点
无论是否插入成功,都返回原来树的跟结点。并用布尔值isInserted返回是否插入成功。
非递归插入(BFS)
* insertIntoBST(TreeNode* root, int val, bool* isInserted) { if (root == nullptr) return new TreeNode(val); TreeNode* head = root; while (root) { //插入的值太小,往左边深入 if (val < root->val) { if (root->left == nullptr) { root->left = new TreeNode(val); *isInserted= true; return head; //成功插入结点 } else root = root->left; } //插入的值太大,往右边深入 else { if (root->right == nullptr) { root->right = new TreeNode(val); *isInserted= true; return head; //成功插入结点 } else root = root->right; } } return head; //没插入结点}/* 调用方式: bool isInserted = false; insertIntoBST(root, val, &isInserted);*/
递归插入(DFS)
TreeNode* insertIntoBST(TreeNode* root, int val, bool* isInserted) { if (root == nullptr) { *isInserted= true; return new TreeNode(val); //当前深入的结点为空,生成(new)新结点,挂上(return) }else if (val < root->val) { root->left = insertIntoBST(root->left, val, isInserted); //插入值比当前结点小,往左边深入 }else if(val > root->val){ root->right = insertIntoBST(root->right, val, isInserted);//插入值比当前结点大,往右边深入 } return root; // 传入的哪个结点,就在哪个结点挂上,再返回}/* 调用方式: bool isInserted= false; insertIntoBST(root, val, &isInserted);*/
2. 构造二叉排序树
所谓构造,就是按照顺序一个一个插入。
TreeNode* insertIntoBST(TreeNode* root, int val) { if (root == nullptr) { TreeNode* root = new TreeNode(val); return root; }else if (val < root->val) { root->left = insertIntoBST(root->left, val); }else if(val > root->val){ root->right = insertIntoBST(root->right, val); } return root;}TreeNode* Create_BST(vector
注:对于元素相同但顺序不同的数组,构造的二叉排序树也可能不同
3. 查找结点
找到则值为key的结点,找不到则返回nullptr
非递归查找:
TreeNode* BST_Search(TreeNode* node, int key){ while(node != nullptr && node->val != key){ if(node->val < key){ node = node->right; //查找的值过大,在右节点查找 }else{ node = node->left; //查找的值过小,在左节点查找 } } return node; //找到了key,或不存在值为key的结点}
注:由于每次只会访问一个结点,最坏时间复杂度为O(1)
递归查找:
TreeNode* BST_Search(TreeNode* node, int key){ if(node == nullptr){ return nullptr; } if(node->val == key){ return node; }else if(node->val < key){ BST_Search(node->right, key); }else{ BST_Search(node->left, key); }}
注:空间复杂度和二叉树的深度有关,每层的递归都会在函数调用栈里多分配一片空间,所以最坏时间复杂度为O(h)
4. 删除结点
这时需要在右子树中找到一个最小的结点(30),或在左子树中找到一个最大的结点(60),将该结点的值赋给被删除结点的值。然后再删除我们找到的这个结点即可(这时的删除操作就转换成前两种删除操作了)。
二、平衡二叉树(AVL树)
满足条件: 树上任一结点左子树和右子树高度之差不大于1结点平衡因子: 左子树高 - 右子树高,取值范围为[-1,1]最小不平衡子树: 从插入点往回找到第一个不平衡结点,以该结点为根的子树
在一棵BST树上插入新结点之后如何保持平衡性?
我们只需要调整最小不平衡子树即可。因为当插入新结点后,若破坏了二叉树的平衡性,则整个二叉树高度必加1。只要恢复从插入点往回找到第一个不平衡结点的高度,则上面所有结点的平衡因子全部恢复。调整结果如下:
调整最小不平衡子树A
1. 在A的左孩子的左子树中插入导致不平衡(LL)
可以看到,结点A的平衡因子变成了2,此时最小不平衡子树就是以A为根节点的二叉树。此时对于这棵最小不平衡子树上结点的值有:BL
恢复平衡的方法: 右旋,调整根结点的左孩子。将A的左孩子 B向右上旋转代替A成为根结点,将A结点向右下旋转成为B的右子树的根节点,而B的原右子树(BR)则成为A结点的左子树,其他结点不变。
2. 在A的右孩子的右子树中插入导致不平衡(RR)
发表评论
暂时没有评论,来抢沙发吧~