【堆合并】左式堆
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <vector> 7 #include <iterator> 8 #include <stack> 9 #include <algorithm> 10 11 using namespace std; 12 13 const int N = 100010; 14 15 typedef struct LeftHeap *Lefh; 16 17 Lefh Merge_node(Lefh, Lefh); // 驱动Merge 18 static Lefh Merge(Lefh, Lefh); // 实际Merge 19 Lefh inst(int, Lefh); // 插入操作 视为 单节点堆与左式堆Merge 20 Lefh DelteMin(Lefh); // 删除最小元 视为 删掉根而得到两个堆,再把两者Merge 21 void print(Lefh) // bfs打印堆 22 23 struct LeftHeap 24 { 25 int val; 26 Lefh l; 27 Lefh r; 28 int npl; 29 }; 30 31 Lefh q[N]; 32 33 Lefh Merge_node(Lefh h1, Lefh h2) 34 { 35 if (h1 == NULL) return h2; 36 if (h2 == NULL) return h1; 37 if (h1 -> val < h2 -> val) 38 return Merge(h1, h2); 39 else 40 return Merge(h2, h1); 41 } 42 43 static Lefh Merge(Lefh h1, Lefh h2) 44 { 45 if (h1 -> l == NULL) h1 -> l = h2; // 由此可以看出 Merge为O(logN)---合并堆的过程中,递归的次数取决于最右路径的长度,根据左式堆的结构性其最右路径最长为logN 46 else 47 { 48 h1 -> r = Merge_node(h1 -> r, h2); 49 if (h1 -> l -> npl < h1 -> r -> npl) // 交换左右儿子 50 { 51 Lefh tmp = h1 -> l; 52 h1 -> l = h1 -> r; 53 h1 -> r = tmp; 54 } 55 56 h1 -> npl = h1 -> r -> npl + 1; // 左式堆:根节点及其左右儿子中,必定是 右儿子的npl最小,则根的npl 多1 57 } 58 59 return h1; 60 } 61 62 Lefh inst(int x, Lefh h) 63 { 64 Lefh t = (struct LeftHeap*) malloc(sizeof (LeftHeap)); 65 66 t -> val = x; 67 t -> npl = 0; 68 t -> l = t -> r = NULL; 69 h = Merge_node(t, h); // 单节点当成一棵子树插入 70 71 return h; 72 } 73 74 Lefh DelteMin(Lefh h) 75 { 76 Lefh t = h; 77 if (h -> l && !(h -> r)) h = h -> l; // 只有左儿子 78 else h = Merge_node(h -> l, h -> r); 79 free(t); 80 return h; 81 } 82 83 void print(Lefh h) 84 { 85 // bfs遍历树 86 87 // 标记法:方便判断节点的顺序(徒手画图) 表示当前节点不存在左儿子或右儿子 就将 左儿子或右儿子标记为-1 88 Lefh ept = (struct LeftHeap*) malloc(sizeof (LeftHeap)); 89 ept -> val = -1; 90 ept -> l = ept -> r = NULL; 91 ept -> npl = -1; 92 93 int hh = 1, tt = 0; 94 q[++ tt] = h; 95 96 while (hh <= tt) 97 { 98 Lefh t = q[hh ++]; 99 printf("(%d,%d) ", t -> val, t -> npl); 100 101 if (t -> val == -1) continue; 102 if (t -> l) q[++ tt] = t -> l; else q[++ tt] = ept; 103 if (t -> r) q[++ tt] = t -> r; else q[++ tt] = ept; 104 }puts(""); 105 } 106 107 int main() 108 { 109 int n, m, x; 110 cin >> n >> m; 111 Lefh h1 = NULL, h2 = NULL; 112 for (int i = 0; i < n; i ++) 113 { 114 scanf("%d", &x); 115 h1 = inst(x, h1); 116 } 117 for (int i = 0; i < m; i ++) 118 { 119 scanf("%d", &x); 120 h2 = inst(x, h2); 121 } 122 print(h1); 123 print(h2); 124 125 Lefh H = Merge_node(h1, h2); 126 print(H); 127 128 H = DelteMin(H); 129 print(H); 130 131 132 return 0; 133 }