本文共 10220 字,大约阅读时间需要 34 分钟。
#include <stdio.h>
#include <stdlib.h> //为exit()提供原型 #include <string.h>//哈夫曼树结点的结构
typedef struct { char ch; //该字符域用于存放节点的关键字 int weight; int parent, lchild, rchild; }HTNode, * HuffmanTree; //动态分配数组存储哈夫曼树 typedef char** HuffmanCode; //动态分配数组存储哈夫曼编码表void Menu(); //显示菜单
void HuffmanCoding(HuffmanTree& HT, char* character, int* w, int n); //建立哈夫曼树 void select(HuffmanTree HT, int j, int* x, int* y); //从已建好的哈夫曼树中选择parent为0,weight最小的两个结点 void Init(); void Coding(); //编码 void Decoding(); //译码 void Print_code(); //打印译码好的代码 void Print_tree(); //打印哈夫曼树 int Read_tree(HuffmanTree&); //从文件中读入哈夫曼树 void find(HuffmanTree& HT, char* code, char* text, int i, int m); //译码时根据01字符串寻找相应叶子节点的递归算法 void Convert_tree(unsigned char T[100][100], int s, int* i, int j); //将内存中的哈夫曼树转换成凹凸表形式的赫夫曼树HuffmanTree HT; //全局变量
int n = 0; //全局变量,存放赫夫曼树叶子结点的数目int main()
{ char select;while (1){ Menu(); scanf("%c", &select); switch (select) //选择操作,根据不同的序号选择不同的操作 { case '1':Init(); break; case '2':Coding(); break; case '3':Decoding(); break; case '4':Print_code(); break; case '5':Print_tree(); break; case '0':exit(1); default:printf("Input error!\n"); } getchar();}return 0;
}
void Menu() //操作选择界面
{ printf(" -----------------------------------------------------\n"); printf(" – 请选择操作 --\n"); printf(" -----------------------------------------------------\n"); printf(" \n"); printf(" ---------------------1初始化哈夫曼树 ---------------\n"); printf(" ---------------------2编码 ---------------\n"); printf(" ---------------------3译码 ---------------\n"); printf(" ---------------------4打印代码文件 ---------------\n"); printf(" ---------------------5打印哈夫曼树 ---------------\n"); printf(" ---------------------0退出 ---------------\n"); printf(" -----------------------------------------------------\n"); }//初始化函数,输入n个字符及其对应的权值,根据权值建立哈夫曼树,并将其存于文件hfmtree中
void Init() { FILE* fp; int i, n, w[52]; //数组存放字符的权值 char character[52]; //存放n个字符 printf("\n输入字符个数 n:"); scanf("%d", &n); //输入字符集大小 printf(“输入%d个字符及其对应的权值:\n”, n); for (i = 0; i < n; i++) { char b = getchar(); scanf("%c", &character[i]); scanf("%d", &w[i]); //输入n个字符和对应的权值 } HuffmanCoding(HT, character, w, n); //建立赫夫曼树if ((fp = fopen("D:\\hfmtree.txt", "w")) == NULL) printf("Open file hfmtree.txt error!\n");for (i = 1; i <= 2 * n - 1; i++){ if (fwrite(&HT[i], sizeof(HTNode), 1, fp) != 1) //将建立的赫夫曼树存入文件hfmtree.txt中 printf("File write error!\n");}printf("\n赫夫曼树建立成功,并已存于文件hfmtree.txt中\n");fclose(fp);
}
//构造哈夫曼树的算法
void HuffmanCoding(HuffmanTree& HT, char* character, int* w, int n) { //w存放n个字符的权值(均>0),构造哈夫曼树HT int m, i, x, y; HuffmanTree p; if (n <= 1) return; m = 2 * n - 1; HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++character, ++w) { p->ch = *character; p->weight = *w; p->parent = 0; p->lchild = 0; p->rchild = 0; } for (; i <= m; ++i, ++p) { p->ch = 0; p->weight = 0; p->parent = 0; p->lchild = 0; p->rchild = 0; } for (i = n + 1; i <= m; ++i) { select(HT, i - 1, &x, &y); HT[x].parent = i; HT[y].parent = i; HT[i].lchild = x; HT[i].rchild = y; HT[i].weight = HT[x].weight + HT[y].weight; }}
//从HT到HT[j]中选择parent为0,weight最小的两个结点,用x和y返回其序号
void select(HuffmanTree HT, int j, int* x, int* y) { int i; //查找weight最小的结点 for (i = 1; i <= j; i++) if (HT[i].parent == 0) { *x = i; break; } for (; i <= j; i++) if ((HT[i].parent == 0) && (HT[i].weight < HT[*x].weight)) *x = i; HT[*x].parent = 1; //查找weight次小的结点 for (i = 1; i <= j; i++) if (HT[i].parent == 0) { *y = i; break; } for (; i <= j; i++) if ((HT[i].parent == 0) && (i != *x) && (HT[i].weight < HT[*y].weight)) *y = i;}
//对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中
void Coding() { FILE* fp, * fw; int i, f, c, start; char* cd; HuffmanCode HC; if (n == 0) n = Read_tree(HT);//从文件hfmtree.txt中读入赫夫曼树,返回叶子结点数//求赫夫曼树中各叶子节点的字符对应的的编码,并存于HC指向的空间中{ HC = (HuffmanCode)malloc((n + 1) * sizeof(char*)); cd = (char*)malloc(n * sizeof(char)); cd[n - 1] = '\0'; for (i = 1; i <= n; ++i) { start = n - 1; for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent) if (HT[f].lchild == c) cd[--start] = '0'; else cd[--start] = '1'; HC[i] = (char*)malloc((n - start) * sizeof(char)); strcpy(HC[i], &cd[start]); } free(cd);}if ((fp = fopen("D:\\tobetrans.txt", "rb")) == NULL) printf("Open file tobetrans.txt error!\n");if ((fw = fopen("D:\\codefile.txt", "wb+")) == NULL) printf("Open file codefile.txt error!\n");char temp;fscanf(fp, "%c", &temp); //从文件读入第一个字符while (!feof(fp)){ for (i = 1; i <= n; i++) if (HT[i].ch == temp) break; //在赫夫曼树中查找字符所在的位置 for (int r = 0; HC[i][r] != '\0'; r++) //将字符对应的编码存入文件 fputc(HC[i][r], fw); fscanf(fp, "%c", &temp); //从文件读入下一个字符}fclose(fw);fclose(fp);printf("\n已将文件hfmtree.txt成功编码,并已存入codefile.txt中!\n\n");
}
//将文件codefile中的代码进行译码,结果存入文件textfile中
void Decoding() { FILE* fp, * fw; int m, i; char* code, * text, * p;if (n == 0) n = Read_tree(HT);//从文件hfmtree.txt中读入赫夫曼树,返回叶子结点数if ((fp = fopen("D:\\codefile.txt", "rb")) == NULL) printf("Open file codefile.txt error!\n");if ((fw = fopen("D:\\textfile.txt", "wb+")) == NULL) printf("Open file textfile.txt error!\n");code = (char*)malloc(sizeof(char));fscanf(fp, "%c", code); //从文件读入一个字符for (i = 1; !feof(fp); i++){ code = (char*)realloc(code, (i + 1) * sizeof(char)); //增加空间 fscanf(fp, "%c", &code[i]); //从文件读入下一个字符 }code[i - 1] = '\0';// codefile.txt文件中的字符已全部读入,存放在code数组中text = (char*)malloc(100 * sizeof(char));p = text;m = 2 * n - 1;if (*code == '0') find(HT, code, text, HT[m].lchild, m); //从根节点的左子树去找else find(HT, code, text, HT[m].rchild, m); //从根节点的右子树去找for (i = 0; p[i] != '\0'; i++) //把译码好的字符存入文件textfile.txt中 fputc(p[i], fw);fclose(fp);fclose(fw);printf("\n已将codefile.txt文件成功译码,并已存入textfile.txt文件!\n\n");
}
//将文件codefi1e以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件codeprint中。
void Print_code() { FILE* fp, * fw; char temp; int i;if ((fp = fopen("D:\\codefile.txt", "rb")) == NULL) printf("Open file codefile.txt error!\n");if ((fw = fopen("D:\\codeprint.txt", "wb+")) == NULL) printf("Open file codeprint.txt error!\n");printf("\n文件codefi1e显示如下:\n");fscanf(fp, "%c", &temp); //从文件读入一个字符for (i = 1; !feof(fp); i++){ printf("%c", temp); if (i % 50 == 0) printf("\n"); fputc(temp, fw); //将该字符存入文件codeprint.txt中 fscanf(fp, "%c", &temp); //从文件读入一个字符}printf("\n\n已将此字符形式的编码写入文件codeprint.txt中!\n\n");fclose(fp);fclose(fw);
}
//将已在内存中的哈夫曼树显示在屏幕上,并将此字符形式的哈夫曼树写入文件treeprint中。
void Print_tree() { unsigned char T[100][100]; int i, j, m = 0; FILE* fp; if (n == 0) n = Read_tree(HT); //从文件hfmtree.txt中读入赫夫曼树,返回叶子结点数Convert_tree(T, 0, &m, 2 * n - 1); //将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中if ((fp = fopen("D:\\treeprint.txt", "wb+")) == NULL) printf("Open file treeprint.txt error!\n");printf("\n打印已建好的赫夫曼树:\n");for (i = 1; i <= 2 * n - 1; i++){ for (j = 0; T[i][j] != 0; j++) { if (T[i][j] == ' ') { printf(" "); fputc(T[i][j], fp); } else { printf("%d", T[i][j]); fprintf(fp, "%d\n", T[i][j]); } } printf("\n");}fclose(fp);printf("\n已将该字符形式的哈夫曼树写入文件treeprint.txt中!\n\n");
}
//从文件hfmtree.txt中读入赫夫曼树,返回叶子节点数
int Read_tree(HuffmanTree& HT) { FILE* fp; int i, n; HT = (HuffmanTree)malloc(sizeof(HTNode)); if ((fp = fopen(“D:\hfmtree.txt”, “r”)) == NULL) printf(“Open file hfmtree.txt error!\n”); for (i = 1; !feof(fp); i++) { HT = (HuffmanTree)realloc(HT, (i + 1) * sizeof(HTNode)); //增加空间 fread(&HT[i], sizeof(HTNode), 1, fp); //读入一个节点信息 } fclose(fp); n = (i - 1) / 2; return n; }//译码时根据01字符串寻找相应叶子节点的递归算法
void find(HuffmanTree& HT, char* code, char* text, int i, int m) {if (*code != '\0') //若译码未结束{ code++; if (HT[i].lchild == 0 && HT[i].rchild == 0) //若找到叶子节点 { *text = HT[i].ch; //将叶子节点的字符存入text中 text++; if ((*code == '0')) find(HT, code, text, HT[m].lchild, m); //从根节点的左子树找 else find(HT, code, text, HT[m].rchild, m); //从根节点的右子树找 } else //如果不是叶子节点 if (*code == '0') find(HT, code, text, HT[i].lchild, m); //从该节点的左子树去找 else find(HT, code, text, HT[i].rchild, m); //从该节点的右子树去找}else *text = '\0'; //译码结束
}
//将文件中的赫夫曼树转换成凹凸表形式的赫夫曼树打印出来
void Convert_tree(unsigned char T[100][100], int s, int* i, int j) `@欢迎使用Markdown编辑器
你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
新的改变
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
- 全新的界面设计 ,将会带来全新的写作体验;
- 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
- 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
- 全新的 KaTeX数学公式 语法;
- 增加了支持甘特图的mermaid语法 功能;
- 增加了 多屏幕编辑 Markdown文章功能;
- 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
- 增加了 检查列表 功能。
功能快捷键
撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y 加粗:Ctrl/Command + B 斜体:Ctrl/Command + I 标题:Ctrl/Command + Shift + H 无序列表:Ctrl/Command + Shift + U 有序列表:Ctrl/Command + Shift + O 检查列表:Ctrl/Command + Shift + C 插入代码:Ctrl/Command + Shift + K 插入链接:Ctrl/Command + Shift + L 插入图片:Ctrl/Command + Shift + G 查找:Ctrl/Command + F 替换:Ctrl/Command + G合理的创建标题,有助于目录的生成
直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。 以此类推,我们支持6级标题。有助于使用TOC
语法后生成一个完美的目录。 如何改变文本的样式
强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
插入链接与图片
链接: .
图片:
带尺寸的图片:
居中的图片:
居中并且带尺寸的图片:
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
如何插入一段漂亮的代码片
去页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted blockvar foo = 'bar';
生成一个适合你的列表
- 项目
- 项目
- 项目
- 项目
- 项目1
- 项目2
- 项目3
- 计划任务
- 完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
设定内容居中、居左、居右
使用:---------:
居中
:----------
居左 使用----------:
居右 第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE | ASCII | HTML |
---|---|---|
Single backticks | 'Isn't this fun?' | ‘Isn’t this fun?’ |
Quotes | "Isn't this fun?" | “Isn’t this fun?” |
Dashes | -- is en-dash, --- is em-dash | – is en-dash, — is em-dash |
创建一个自定义列表
- Markdown
- Text-to- HTML conversion tool Authors
- John
- Luke
如何创建一个注脚
一个具有注脚的文本。
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 :
Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式.
新的甘特图功能,丰富你的文章
- 关于 甘特图 语法,参考 ,
UML 图表
可以使用UML图表进行渲染。 . 例如下面产生的一个序列图:
这将产生一个流程图。:
- 关于 Mermaid 语法,参考 ,
FLowchart流程图
我们依旧会支持flowchart的流程图:
- 关于 Flowchart流程图 语法,参考 .
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。注脚的解释
转载地址:https://blog.csdn.net/m0_55673081/article/details/121988541 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!