altered readme
This commit is contained in:
		@@ -1,3 +1,89 @@
 | 
			
		||||
# 左高树 Height-biased Leftist Tree 合并思路
 | 
			
		||||
 | 
			
		||||
合并两个左高树(Height-biased Leftist Tree, HBLT)是其核心操作,利用递归和左右子树的`s(x)`(通常指null path length,NPL)来保持“左高性质”和堆序。下面给你完整详细步骤和示例代码。
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## 左高树合并的基本思路
 | 
			
		||||
 | 
			
		||||
假设有两棵左高树的根节点指针 `h1` 和 `h2`,要合并它们,得到合并后的左高树根节点。
 | 
			
		||||
 | 
			
		||||
### 主要步骤
 | 
			
		||||
 | 
			
		||||
1. **处理空树情况**
 | 
			
		||||
 | 
			
		||||
   * 如果 `h1` 是空,直接返回 `h2`。
 | 
			
		||||
   * 如果 `h2` 是空,直接返回 `h1`。
 | 
			
		||||
 | 
			
		||||
2. **保证根节点的键值满足最大堆性质**
 | 
			
		||||
 | 
			
		||||
   * 如果是最大左高树(Max-Heap),令 `h1` 的键值大于等于 `h2`。
 | 
			
		||||
   * 若 `h1->key < h2->key`,交换 `h1` 和 `h2`。
 | 
			
		||||
 | 
			
		||||
3. **递归合并**
 | 
			
		||||
 | 
			
		||||
   * 将 `h2` 合并到 `h1` 的右子树。
 | 
			
		||||
   * `h1->right = merge(h1->right, h2)`
 | 
			
		||||
 | 
			
		||||
4. **保持左高性质(左子树的 null path length ≥ 右子树)**
 | 
			
		||||
 | 
			
		||||
   * 如果 `s(h1->left) < s(h1->right)`,交换左右子树指针。
 | 
			
		||||
 | 
			
		||||
5. **更新当前节点的 s 值**
 | 
			
		||||
 | 
			
		||||
   * `s(h1) = s(h1->right) + 1`
 | 
			
		||||
 | 
			
		||||
6. 返回新的根 `h1`。
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## 伪代码
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct binaryTreeNode {
 | 
			
		||||
    std::pair<int, T> data;  // 键值和负载
 | 
			
		||||
    binaryTreeNode *left;
 | 
			
		||||
    binaryTreeNode *right;
 | 
			
		||||
    int s;  // null path length (NPL)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
binaryTreeNode<std::pair<int, T>>* merge(binaryTreeNode<std::pair<int, T>>* h1,
 | 
			
		||||
                                         binaryTreeNode<std::pair<int, T>>* h2) {
 | 
			
		||||
    if (!h1) return h2;
 | 
			
		||||
    if (!h2) return h1;
 | 
			
		||||
 | 
			
		||||
    // 保证最大堆性质,根值较大
 | 
			
		||||
    if (h1->data.first < h2->data.first)
 | 
			
		||||
        std::swap(h1, h2);
 | 
			
		||||
 | 
			
		||||
    // 递归合并 h2 到 h1 的右子树
 | 
			
		||||
    h1->right = merge(h1->right, h2);
 | 
			
		||||
 | 
			
		||||
    // 保持左高性质
 | 
			
		||||
    int leftNPL = h1->left ? h1->left->s : 0;
 | 
			
		||||
    int rightNPL = h1->right ? h1->right->s : 0;
 | 
			
		||||
    if (leftNPL < rightNPL)
 | 
			
		||||
        std::swap(h1->left, h1->right);
 | 
			
		||||
 | 
			
		||||
    // 更新当前节点的 s 值
 | 
			
		||||
    h1->s = (h1->right ? h1->right->s : 0) + 1;
 | 
			
		||||
 | 
			
		||||
    return h1;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## 说明
 | 
			
		||||
 | 
			
		||||
* `s`(null path length)定义为从该节点到其最近的空外部节点(外部节点视为 `nullptr`)的路径长度。
 | 
			
		||||
* 由于左高树特性,左子树的 `s` 不小于右子树的 `s`,合并后通过交换左右子树保证这个性质。
 | 
			
		||||
* 这个合并过程保证了合并操作时间复杂度为 O(log n)。
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# 左高树合并 — 逐步图解(示例:根 50 与 根 45)
 | 
			
		||||
 | 
			
		||||
下面是你给出的两个左高树(Max-Leftist)的逐步合并图解。我把每一步的递归调用、比较、左右交换和 s 值(null path length,定义为:s(nullptr)=0,s(leaf)=1,节点 s = right.s + 1)都写清楚了。
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user