堆
定义
堆应满足结构性和堆序性两个条件,首先,其逻辑结构须等同于完全二叉树,此即所谓的“结构性”。如此,堆节点将与词条一一对应。其次,就优先级而言,堆顶以外的每个节点都不大(小)于其父节点,此即所谓的“堆序性”。堆的结构等同于完全二叉树的堆,n 个词条组成的堆的高度$h = \lfloor log_2n \rfloor = O(logn)$。
基本操作
此处的堆用 vector 容器实现,从索引 1 开始记录,插入算法(向上调整)的时间复杂度为$O(logn)$:
void insert(int val, vector<int>& heap){ // val 为新增的节点值 heap.push_back(val); int i = heap.size(), j = i / 2; while(j >= 1){ if(heap[j] < heap[i]){ swap(heap[j], heap[i]); i = j; j = i / 2; }else{ break; } } }
$Floyd$建堆算法和向下调整算法为,前者时间复杂度为$O(n)$:
void DownAdjust(int low, vector<int>& heap){ // low 为代调整节点 int i = low, j = i * 2; while(j <= heap.size()){ if(j + 1 <= heap.size() && heap[j + 1] > heap[j]){ j = j + 1; } if(heap[j] > heap[i]){ swap(heap[j], heap[i]); i = j; j = i * 2; }else{ break; } } } void CreateHeap(vector<int>& heap){ for(int i = n / 2; i >= 1; i--){ DownAdjust(i, heap); } }
顶节点的删除通过向下调整实现:
void DeleteTop(vector<int>& heap){ heap[1] = heap[heap.size()]; heap.pop_back(); DownAdjust(1, heap); }
并查集
定义与代码实现
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。常常在使用中以森林来表示。其中“并”、“查”对应其两个关键操作。
初始化
const int UFSetMaxn = 1000; int father[UFSetMaxn]; void UFSetinit(int n){ for(int i = 1; i <= n; i++){ father[i] = i; } }
基本并查操作:
int Find(int x){ while( x != father[x]){ x = father[x]; } return x; } void Union(int a, int b){ int faA = Find(a); int faB = Find(b); if(faA != faB){ father[faA] = faB; } }
路径压缩优化:
int FindZip(int x){ int a = x; while( x != father[x]){ x = father[x]; } while(a != father[a]){ int z = a; a = father[a]; father[z] = x; } return x; } void UnionZip(int a, int b){ int faA = FindZip(a); int faB = FindZip(b); if(faA != faB){ father[faA] = faB; } }
哈夫曼树
定义与相关代码
//哈夫曼树 struct HuffmanNode { int val; HuffmanNode *left; HuffmanNode *right; HuffmanNode *parent; HuffmanNode() : val(0), left(nullptr), right(nullptr), parent(nullptr){} HuffmanNode(int x) : val(x), left(nullptr), right(nullptr), parent(nullptr) {} HuffmanNode(int x, HuffmanNode *left, HuffmanNode *right, HuffmanNode *parent) : val(x), left(left), right(right), parent(parent) {} }; //哈夫曼节点插入堆 void insert(HuffmanNode* val, vector<HuffmanNode*>& heap){ heap.push_back(val); int i = heap.size(), j = i / 2; while(j >= 1){ if(heap[j] -> val > heap[i] -> val){ swap(heap[j], heap[i]); i = j; j = i / 2; }else{ break; } } } //哈夫曼堆向下调整 void DownAdjust(int low, vector<HuffmanNode*>& heap){ // low 为代调整节点 int i = low, j = i * 2; while(j <= heap.size()){ if(j + 1 <= heap.size() && heap[j + 1] -> val > heap[j] -> val){ j = j + 1; } if(heap[j] -> val > heap[i] -> val){ swap(heap[j], heap[i]); i = j; j = i * 2; }else{ break; } } } //哈夫曼堆删除顶节点 void DeleteTop(vector<HuffmanNode*>& heap){ heap[1] = heap[heap.size()]; heap.pop_back(); DownAdjust(1, heap); } //哈夫曼树构造合并节点 HuffmanNode* MergeNode(HuffmanNode* a, HuffmanNode* b){ HuffmanNode* root = new HuffmanNode(a -> val + b -> val); root -> left = a; root -> right = b; a -> parent = root; b -> parent = root; return root; } //哈夫曼树创建 HuffmanNode* CreateHuffmanTree(vector<int>& w){ HuffmanNode *root = new HuffmanNode(); vector<HuffmanNode*> heap; heap.push_back(root); for(int i = 0; i < w.size(); i++){ HuffmanNode *temp = new HuffmanNode(w[i]); insert(temp, heap); } for(int i = 1; i <= n - 1; i++){ HuffmanNode* a = heap[1]; DeleteTop(heap); HuffmanNode* b = heap[1]; DeleteTop(heap); root = MergeNode(a, b); insert(root, heap); } return root; }