标签:tor 指南 val 数据 lib 清空 name print i++
1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 7 using namespace std; 8 /* 9 1. 哈夫曼编码-顺序存储方式 10 2. 优先队列存储——堆存储 11 */ 12 13 void huffmanTree(int huffman[][5],int n) 14 { 15 16 for (int i=0;i<n;i++) 17 { 18 huffman[i][0] = i; 19 cin >> huffman[i][1]; 20 huffman[i][2] = -1; 21 huffman[i][3] = -1; 22 huffman[i][4] = -1; 23 } 24 int num1 = 0,num2 = 0; 25 float min1 = 9999,min2 = 9999; 26 27 for (int i=0;i<n-1;i++) 28 { 29 num1 = 0; 30 num2 = 0; 31 min1 = 9999; 32 min2 = 9999; 33 for (int j=0;j<n+i;j++) 34 { 35 // 找到一组数中未被排序(没有父节点)的的最小值和次小值,最小值优先判断,判断完最小值后判断次小值 36 if (huffman[j][2] == -1 && huffman[j][1] < min1 ) 37 { 38 if (min1 < min2) 39 { 40 min2 = min1; 41 num2 = num1; 42 } 43 min1 = huffman[j][1]; 44 num1 = j; 45 } 46 else if (huffman[j][2] == -1 && huffman[j][1] < min2) 47 { 48 min2 = huffman[j][1]; 49 num2 = j; 50 } 51 } 52 huffman[n+i][0] = n+i; 53 huffman[n+i][1] = huffman[num1][1]+huffman[num2][1]; 54 huffman[n+i][2] = -1; 55 huffman[n+i][3] = num1; 56 huffman[n+i][4] = num2; 57 huffman[num1][2] = n+i; 58 huffman[num2][2] = n+i; 59 60 } 61 } 62 void printTree(int huffman[][5],int n) 63 { 64 for (int i=0;i<2*n-1;i++) 65 { 66 for (int j=0;j<5;j++) 67 cout << huffman[i][j] << ‘ ‘; 68 cout << endl; 69 } 70 } 71 void huffmanCode(int huffman[][5],int n) 72 { 73 // 自顶向下法:找到根到所有孩子的路径,每条路径均对应一个孩子 74 // 自底向上法:遍历每个叶子结点,往上寻找直到找到根为止 75 char code[20]; 76 int q,parent; 77 int j = 0; 78 for (int i=0;i<n;i++) 79 { 80 q = i; 81 parent = huffman[q][2]; 82 j = 0; 83 while (parent!=-1) 84 { 85 if (huffman[parent][3] == q) 86 { 87 // q是parent的左孩子 88 code[j] = ‘0‘; 89 } 90 if (huffman[parent][4] == q) 91 { 92 code[j] = ‘1‘; 93 } 94 j++; 95 q = parent; 96 parent = huffman[q][2]; 97 } 98 code[j] = ‘\0‘; 99 cout << huffman[i][1] << " : " << code << endl; 100 } 101 } 102 char code[10]; 103 void printPath(int huffman[][5],int n,int root,int level) 104 { 105 // 打印从根节点到所有叶子结点的路径 106 level ++; 107 if (huffman[root][3] != -1 && huffman[root][4]!=-1) 108 { 109 // 如果root不为根节点时 110 code[level] = ‘0‘; 111 printPath(huffman,n,huffman[root][3],level); 112 code[level] = ‘1‘; 113 printPath(huffman,n,huffman[root][4],level); 114 } 115 else { 116 code[level] = ‘\0‘; 117 for (int i=1;i<=level;i++) 118 cout << code[i]; 119 cout << ‘ ‘ << huffman[root][1] <<endl; 120 } 121 122 } 123 124 // 课本上的代码方法,结构体数组封装一个结点而不是二维数组 125 typedef struct HuffmanNode 126 { 127 int weight; 128 int parent,lchild,rchild; 129 }HuffmanNode,**HuffmanTree; 130 131 typedef char ** HuffmanCode ; // 动态分配数组存储哈夫曼编码表 132 133 134 void select_2(HuffmanTree t,int n,int &s1,int &s2) 135 { 136 int min1 = 9999,min2 = 9999; 137 int num1=1,num2 = 1; 138 for (int i=1;i<=n;i++) 139 { 140 if (t[i]->weight < min1) 141 { 142 if ( min2 > min1 ) 143 { // 在替换min1之前判断min1舍弃的值是不是比min2小,如果是的话min2就占着大便宜! 144 min2 = min1; 145 num2 = num1; 146 } 147 num1 = i; 148 min1 = t[i]->weight; 149 }else if (t[i]->weight) 150 { 151 min2 = t[i]->weight; 152 num2 = i; 153 } 154 } 155 s1 = num1; 156 s2 = num2; 157 } 158 void HuffmanCoding(HuffmanTree &t,HuffmanCode &c,int *w,int n) 159 { 160 if (n<=1) 161 return; 162 163 int m = 2*n-1; 164 t = (HuffmanTree)malloc(sizeof(HuffmanNode)*(m+1)); // m+1是因为0号单元未用 165 for (int i=1;i<=n;i++) 166 { 167 t[i]->weight = w[i]; 168 t[i]->parent = 0; 169 t[i]->lchild = 0; 170 t[i]->rchild = 0; 171 } 172 // 下面的循环可省略,因为遍历过程中一定会重新写一遍 173 for (int i=n+1;i<=m;i++) 174 { 175 t[i]->weight = 0 ; 176 t[i]->parent = 0 ; 177 t[i]->lchild = 0 ; 178 t[i]->rchild = 0 ; 179 } 180 int s1,s2; 181 // 建立哈夫曼树的循环 182 for (int i = n+1;i<=m;i++) 183 { 184 //找到1-i-1中的最小值和次小值 185 select_2(t,i-1,s1,s2); 186 t[s1]->parent = i; 187 t[s2]->parent = i; 188 t[i]->weight = t[s1]->weight+t[s2]->weight; 189 t[i]->lchild = s1; 190 t[i]->rchild = s2; 191 } 192 193 // 计算哈弗曼编码值,从叶子到根逆向求 194 c = (char **)malloc(sizeof(char*)*(n+1));//n个字符的头指针向量,从1开始 195 char *cd = (char *)malloc(n*sizeof(char));// 哈弗曼树的高度不会超过n 196 cd[n-1] = ‘\0‘; 197 for (int i=1;i<=n;i++) 198 { 199 int start = n-1;//倒着存储编码 200 for (int c = i,f = t[i]->parent;f!=0;c=f,f = t[f]->parent) 201 if (t[f]->lchild == c) 202 cd[--start] = ‘0‘; 203 else 204 cd[--start] = ‘1‘; 205 206 c[i] = (char *)malloc(sizeof(char)*(n-start)); 207 strcpy(c[i],&cd[start]); // 复制编码 208 /* 209 char *p = (char *)malloc(sizeof(char)*10); 210 p = "helloworld"; 211 cout << p << endl; 212 char *q = (char *)malloc(sizeof(char)*5); 213 strcpy(q,&p[5]);//两个参数都是地址,从起始地址到\0终止符之间的内容复制过去 214 cout << q; 215 */ 216 } 217 218 // // 无栈非递归遍历哈夫曼树,求哈夫曼编码 219 220 c = (HuffmanCode)malloc((n+1)*sizeof(char *)); 221 int p = m; 222 int cdlen = 0; 223 for (int i=1;i<=m;i++) 224 t[i]->weight = 0; // 遍历哈夫曼树时用作结点状态标志 225 while (p){ 226 if (t[p]->weight == 0 ) 227 { 228 t[p]->weight = 1; 229 if (t[p]->lchild!=0) 230 { // 左右孩子均不为0的状况 231 p = t[p]->lchild; 232 cd[cdlen++] = "0"; 233 } 234 else if (t[p]->rchild == 0 ) 235 { 236 // 左右孩子均为0,P结点为叶节点,登记字符编码 237 c[p] = (char *)malloc((cdlen+1)*sizeof(char)); 238 cd[cdlen] = ‘\0‘; 239 strcpy(hc[p],cd); 240 } 241 } 242 else if (t[p]->weight == 1){ 243 t[p]->weight = 2; 244 if (t[p]->rchild != 0) 245 { 246 p = t[p]->rchild; 247 cd[cdlen++] = ‘1‘; 248 }else 249 { 250 t[p]->weight = 0; 251 p = t[p]->parent; 252 --cdlen; //退回父节点,编码长度减一 253 } 254 } 255 } 256 } 257 258 259 int main() 260 { 261 int n; 262 cout << "n:" <<endl; 263 cin >> n; 264 // int huffman[2*n-1][5]; 265 // huffmanTree(huffman,n); 266 // printTree(huffman,n); 267 // huffmanCode(huffman,n); 268 // int level = 0; 269 // printPath(huffman,n,2*n-2,level); 270 HuffmanTree t; 271 HuffmanCode c; 272 int *w; 273 for (int i=0;i<n;i++) 274 cin >> w[i]; 275 HuffmanCoding(t,c,w,n); 276 return 0; 277 }
优先队列的用法:
(1)priority_queue 默认设置大顶堆
(2)priority_queue
struct node { friend bool operator< (node n1, node n2) { return n1.priority < n2.priority; } int priority; int value; };
运算符重载:
用于对对象的运算符操作
box operator+(const box a,const box b) { box c; c.weight = a.weight+b.weight; return c; }
友元函数:
1)C++中引入友元函数,是为在该类中提供一个对外(除了他自己意外)访问的窗口;
2)这个友元函数他不属于该类的成员函数,他是定义在类外的普通函数,只是在类中声明该函数可以直接访问类中的private或者protected成员。
3)友元函数可以访问类中的私有成员和其他数据,但是访问不可直接使用数据成员,需要通过对对象进行引用。
// 输出哈夫曼树树顶元素
1 int main() 2 { 3 int n; 4 priority_queue<int,vector<int>,greater<int> > q; 5 while (cin >> n) 6 { 7 while (!q.empty()) 8 q.pop(); // 清空小顶堆元素 9 10 for (int i=1;i<=n;i++) 11 { 12 int d; 13 cin >> d; 14 q.push(d); 15 } 16 int ans = 0; 17 while (q.size() > 1 ) 18 { 19 int a = q.top(); 20 q.pop(); 21 int b = q.top(); 22 q.pop(); 23 q.push(a+b); 24 25 } 26 ans = q.top(); 27 cout << ans << endl; 28 } 29 30 return 0; 31 }
1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <queue> 6 #include <vector> 7 8 using namespace std; 9 /* 10 搬水果 11 */ 12 13 14 int main() 15 { 16 int n; 17 priority_queue<int,vector<int>,greater<int> > q; 18 while (cin >> n) 19 { 20 while (!q.empty()) 21 q.pop(); // 清空小顶堆元素 22 23 for (int i=1;i<=n;i++) 24 { 25 int d; 26 cin >> d; 27 q.push(d); 28 } 29 int ans = 0; 30 int sum = 0; 31 while (q.size() > 1 ) 32 { 33 int a = q.top(); 34 q.pop(); 35 int b = q.top(); 36 q.pop(); 37 ans = a+b; 38 q.push(ans); 39 sum += ans; 40 41 } 42 cout << sum << endl; 43 } 44 45 46 return 0; 47 }
标签:tor 指南 val 数据 lib 清空 name print i++
原文地址:https://www.cnblogs.com/twomeng/p/9509583.html