PQ Tree

PQ树是一种数据结构,用于处理序列全排列问题,确保关键点排列在一起。PQ树上的节点分为P和Q两类,P类节点的儿子顺序不限,Q类节点的儿子必须左右有序。通过调整树的形态,保证关键节点排列合法。文章详细阐述了PQ树的操作和调整策略,包括节点分类、旋转函数等,并提供了相关习题。
摘要由CSDN通过智能技术生成
                          PQ Tree
                        philipsweng

PQ树是用来解决将序列全排列,使得某些关键点排列在一起的问题的数据结构。

具体操作。
我们将PQ树上的点分为P,Q两种类型,P类型表示其儿子可以任意顺序排列,Q类型表示其儿子可以以从左到右排列或者从右到左排列。
并且PQ树上的一个叶子表示的就是全排列中的一个元素。
最终的可行方案是PQ树的先序遍历

当我们接受到一组新的点集S,表示我们需要将S中的点紧凑地排列在一起。
我们对于每个点维护一个值Bel,若此点的子树的叶子全都为关键点,则Bel= 1,若子树中没有关键点则为0,否则为2

我们考虑如何调整树的形态使得当前约束合法。
我们对当前节点的状态分类讨论。
我们的目的是要让节点子树中的关键节点都排列在一起。
若为Q类节点,
则我们从左到右判断Q的儿子的信息,
我们继续分类讨论儿子的信息
设当前节点的边集为E(E有顺序)设新排列为E1
0:若我们之前有一个儿子不为0,则之前的关键节点到这里已经结束了。E1中加入此节点
1:若之前已经关键节点排列结束了,我们现在又多一个关键节点,则非法。否则在E1中加入此节点。
2:非法情况同1.值得注意的是,假如出现了2,且之前出现过非0点,我们关键节点的排列也要结束。同时,我们在E1中加入此节点的儿子靠左(或靠右)的顺序(此步递归处理,因为我们需要其子树都要靠左(或靠右))

若当前为P类节点,
我们需要新建一个Q类节点T,设T的边集为L。
我们先找到第一个2号节点P,此节点要

好的,以下是C++实现HuffmanTree和编码表的示例代码: ```c++ #include <iostream> #include <queue> #include <unordered_map> using namespace std; struct Node { char ch; int freq; Node* left; Node* right; Node(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {} }; struct cmp { bool operator() (Node* a, Node* b) { return a->freq > b->freq; } }; Node* buildHuffmanTree(string s) { unordered_map<char, int> freqMap; for (char c : s) { freqMap[c]++; } priority_queue<Node*, vector<Node*>, cmp> pq; for (auto p : freqMap) { pq.push(new Node(p.first, p.second)); } while (pq.size() > 1) { Node* left = pq.top(); pq.pop(); Node* right = pq.top(); pq.pop(); Node* parent = new Node('$', left->freq + right->freq); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } void buildEncodingTable(Node* root, string code, unordered_map<char, string>& encodingTable) { if (!root) { return; } if (root->ch != '$') { encodingTable[root->ch] = code; } buildEncodingTable(root->left, code + "0", encodingTable); buildEncodingTable(root->right, code + "1", encodingTable); } int main() { string s = "This is a test string."; Node* root = buildHuffmanTree(s); unordered_map<char, string> encodingTable; buildEncodingTable(root, "", encodingTable); for (auto p : encodingTable) { cout << p.first << ": " << p.second << endl; } return 0; } ``` 在这个例子中,我们首先通过遍历字符串计算每个字符的出现频率,然后将每个字符和对应的频率构建成一个节点,并用一个优先队列来维护这些节点。每次从队列中取出频率最小的两个节点,将它们合并成一个节点,并将这个新节点加入队列中。当队列中只有一个节点时,我们就构建好了Huffman Tree。接下来,我们对Huffman Tree进行前序遍历,同时记录每个字符对应的编码(向左为0,向右为1),并将其存放在一个哈希表中。最后,我们输出这个哈希表,即得到了编码表。 需要注意的是,这个示例代码中使用了unorderd_map来存放编码表。如果你的编译器不支持C++11的哈希表,可以使用STL库中的map来代替,但需要将编码表的类型改为map<char, string>。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值