动态数组引论:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
//1MB = 1024*1024
typedef struct {
char name[995];
int id;
}node;
typedef struct Vectorst {
int size;
int maxSize;
node* data;
}* Vector;
Vector VectorNew(void);
void VectorPushBack(Vector v, node e);
node VectorPopBack(Vector v);
node VectorGet(Vector v, int index);
int VectorSize(Vector v);
int VectorMaxSize(Vector v);
void VectorRm(Vector v, int index);
void VectorDelete(Vector v);
Vector VectorNew(void) {
Vector v = (Vector)malloc(sizeof(struct Vectorst));
assert(v != NULL);
v->size = 0;
v->maxSize = 32;
v->data = (node*)malloc(sizeof(node)*v->maxSize);
assert(v->data != NULL);
return v;
}
void VectorPushBack(Vector v, node e) {
assert(v != NULL);
if (v->size >= v->maxSize) {
v->maxSize *= 2;
v->data = (node*)realloc(v->data, v->maxSize * sizeof(node));
assert(v->data != NULL);
}
v->data[v->size++] = e;
}
node VectorPopBack(Vector v) {
assert(v != NULL && v->size > 0);
return v->data[--v->size];
}
node VectorGet(Vector v, int index) {
assert(v != NULL && index >= 0 && index < v->size);
return v->data[index];
}
int VectorSize(Vector v) {
assert(v != NULL);
return v->size;
}
int VectorMaxSize(Vector v) {
assert(v != NULL);
return v->maxSize;
}
void VectorRm(Vector v, int index) {
assert(v != NULL || index <= v->size - 1);
int i;
if (index < v->size - 1) {
for (i = index;i < v->size - 1;i++) {
v->data[i] = v->data[i + 1];
}
v->size--;
}
else {
v->size--;
}
}
void VectorDelete(Vector v) {
assert(v != NULL && v->data != NULL);
free(v->data);
free(v);
}
int main(void) {
//node MyArr[1024*2];
/*node e;
e.id = 1;
strcpy(e.name, "laoxia");
node e1;
e1.id = 2;
strcpy(e1.name, "laoding");
printf("id=%d,name=%s\n", e.id, e.name);
printf("id=%d,name=%s\n", e1.id, e1.name);*/
/*MyArr[0].id = 1000;
strcpy(MyArr[0].name, "C++");
printf("id=%d,name=%s\n", MyArr[0].id, MyArr[0].name);*/
Vector v = VectorNew();
node e;
for (int i = 0;i < 1024 * 2;i++) {
e.id = i;
VectorPushBack(v, e);
}
printf("size of Vector=%d\n", VectorSize(v));
for (int i = 0;i < 1024 * 2;i++) {
printf("%d,", VectorGet(v, i).id);
}
system("pause");
return 0;
}
综合 哈夫曼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//以字节形式读入目标文件,统计字符频度作为临时节点
typedef struct {
unsigned char uch;//以8位为单元作为无符号的字符
unsigned long weight;//每一个以二进制进行区分的字符出现的频度
}TmpNode;
//Huffman树的节点
typedef struct {
unsigned char uch;//无符号字符
unsigned long weight;
char* code;//字符对应的huffman编码(动态分配存储空间)
int parent, lchild, rchild;
}HufNode,*HufTree;
//建立Huffman树
void select(HufNode* huf_tree, unsigned int n, int *s1, int *s2) {
//找最小
unsigned int i;
unsigned long min = ULONG_MAX;
for (i = 0;i < n;i++) {
if (huf_tree[i].parent == 0 && huf_tree[i].weight < min) {
min = huf_tree[i].weight;
*s1 = i;
}
}
huf_tree[*s1].parent = 1;//此节点已经选中
//找次小
min = ULLONG_MAX;
for (i = 0;i < n;i++) {
if (huf_tree[i].parent == 0 && huf_tree[i].weight < min) {
min = huf_tree[i].weight;
*s2 = i;
}
}
}
//建立huffman树
void CreateTree(HufNode *huf_tree, unsigned int char_kinds, unsigned int node_num) {
unsigned int i;
int s1, s2;
for (i = char_kinds;i < node_num;i++) {
select(huf_tree, i, &s1, &s2);
huf_tree[s1].parent = huf_tree[s2].parent = i;
huf_tree[i].lchild = s1;
huf_tree[i].rchild = s2;
huf_tree[i].weight = huf_tree[s1].weight + huf_tree[s2].weight;
}
}
//生成huffman编码
void HufCode(HufNode* huf_tree, unsigned char_kinds) {
unsigned int i;
int cur, next, index;
char* code_tmp = (char*)malloc(256 * sizeof(char));//暂存编码,最多256个叶子,编码不超过255
code_tmp[255] = '\0';
for (i = 0;i < char_kinds;i++) {
//从叶子向根反向遍历求解
index = 255;//索引
for (cur = i, next = huf_tree[i].parent;next != 0;cur = next, next = huf_tree[next].parent) {
if (huf_tree[next].lchild == cur)
code_tmp[--index] = '0';//左0
else
code_tmp[--index] = '1';
}
//为第i个字符编码动态分配空间
huf_tree[i].code = (char*)malloc((256 - index) * sizeof(char));
strcpy(huf_tree[i].code, &code_tmp[index]);//正向保存编码到树节点响应的域
}
free(code_tmp);
}
//compress
int compress(char* ifname,char* ofname){
unsigned int i, j;
unsigned int char_kinds;//字符的种类
unsigned char char_temp;//暂存8位的字符
unsigned long file_len = 0;
FILE* infile, *outfile;
TmpNode node_temp;
unsigned int node_num;
HufTree huf_Tree;
char code_buf[256] = { '\0' };//待存编码缓冲区
unsigned int code_len;
//动态分配256个节点,暂存字符频度
//统计并拷贝到树节点后立即释放
TmpNode* tmp_nodes = (TmpNode*)malloc(256 * sizeof(TmpNode));
//初始化暂存节点
for (i = 0;i < 256;i++) {
tmp_nodes[i].weight = 0;
tmp_nodes[i].uch = (unsigned char)i;//数组的256个角标与256种字符对应
}
//遍历文件获取字符频度
infile = fopen(ifname, "rb");
if (infile == NULL)
return -1;
fread((char*)&char_temp, sizeof(unsigned char), 1, infile);//读入一个字符
while(!feof(infile)){
//统计下标对应的字符权重
++tmp_nodes[char_temp].weight;
++file_len;
fread((char*)&char_temp, sizeof(unsigned char), 1, infile);
}
fclose(infile);
//排序,将频度为0的放到最后,剔除
for (i = 0;i < 255;i++) {
for (j = i + 1;j < 256;j++) {
if (tmp_nodes[i].weight < tmp_nodes[j].weight) {
node_temp = tmp_nodes[i];
tmp_nodes[i] = tmp_nodes[j];
tmp_nodes[j] = node_temp;
}
}
}
//统计实际的字符种类
for (i = 0;i < 256;i++) {
if (tmp_nodes[i].weight == 0)
break;
}
char_kinds = i;
if (char_kinds == 1) {
outfile = fopen(ofname, "wb");
fwrite((char*)&char_kinds, sizeof(unsigned int), 1, outfile);
fwrite((char*)&tmp_nodes[0].uch, sizeof(unsigned char), 1, outfile);
fwrite((char*)&tmp_nodes[0].weight, sizeof(unsigned long), 1, outfile);
free(tmp_nodes);
fclose(outfile);
}
else {
//根据字符种类数,计算建立Huffman树所有需要的节点
node_num = 2 * char_kinds - 1;
huf_Tree = (HufNode*)malloc(node_num * sizeof(HufNode));
//初始化前char_kinds的节点
for (i = 0;i < char_kinds;i++) {
huf_Tree[i].uch = tmp_nodes[i].uch;
huf_Tree[i].weight = tmp_nodes[i].weight;
huf_Tree[i].parent = 0;
}
free(tmp_nodes);
//初始化后面的node_num-char_kinds
for (;i < node_num;i++)
huf_Tree[i].parent = 0;
//建树
CreateTree(huf_Tree, char_kinds, node_num);
//生Huffman
HufCode(huf_Tree, char_kinds);
//写入字符和相应的权重,以便解压的时候,我们重建huffman树
outfile = fopen(ofname, "wb");
fwrite((char*)&char_kinds, sizeof(unsigned int), 1, outfile);
for (i = 0;i < char_kinds;i++) {
fwrite((char*)&huf_Tree[i].uch, sizeof(unsigned char), 1, outfile);
fwrite((char*)&huf_Tree[i].weight, sizeof(unsigned long), 1, outfile);
}
//接下来,将字符和权重信息后面写入文件长度和字符编码
fwrite((char*)&file_len, sizeof(unsigned long), 1, outfile);
infile = fopen(ifname, "rb");
fread((char*)&char_temp, sizeof(unsigned char), 1, infile);
while (!feof(infile)) {
//匹配字符对应编码
for (i = 0;i < char_kinds;i++)
if (char_temp == huf_Tree[i].uch)
strcat(code_buf, huf_Tree[i].code);
//以8位为一个处理单元
while (strlen(code_buf) >= 8) {
char_temp = '\0';
for (i = 0;i < 8;i++) {
char_temp <<= 1;
if (code_buf[i] == '1') {
char_temp |= 1;
}
}
fwrite((char*)&char_temp, sizeof(unsigned char), 1, outfile);
strcpy(code_buf, code_buf + 8);
}
fread((char*)&char_temp, sizeof(unsigned char), 1, infile);
}
//处理一下不足8位
code_len = strlen(code_buf);
if (code_len > 0) {
char_temp = '\0';
for (i = 0;i < code_len;i++) {
char_temp <<= 1;
if (code_buf[i] == '1')
char_temp != 1;
}
char_temp <<= 8 - code_len;
fwrite((char*)&char_temp, sizeof(unsigned char), 1, outfile);
}
fclose(infile);
fclose(outfile);
for (i = 0;i < char_kinds;i++)
free(huf_Tree[i].code);
free(huf_Tree);
}
}
int extract(char* ifname, char* ofname)
{
unsigned int i;
unsigned long file_len;
unsigned long writen_len = 0;//控制文件的写入长度
FILE* infile, *outfile;
unsigned int char_kinds;//存储字符种类
unsigned int node_num;
HufTree huf_tree;
unsigned char code_temp;//暂存8位的编码
//构建huffman树,因此,定义根节点的索引
unsigned int root;
infile = fopen(ifname, "rb");
if (infile == NULL)
return -1;
//重建haffman树
fread((char*)&char_kinds, sizeof(unsigned int), 1, infile);
if (char_kinds == 1) {
fread((char*)&code_temp, sizeof(unsigned char), 1, infile);
fread((char*)&file_len, sizeof(unsigned long), 1, infile);
outfile = fopen(ofname, "wb");//打开压缩后的文件
while (file_len--)
fwrite((char*)&code_temp, sizeof(unsigned char), 1, outfile);
fclose(infile);
fclose(outfile);
}
else {
node_num = 2 * char_kinds - 1;//左孩子,和右孩子重建huffman树
huf_tree = (HufNode*)malloc(node_num * sizeof(HufNode));
//读取字符以及对应的权重
for (i = 0;i < char_kinds;i++) {
fread((char*)&huf_tree[i].uch, sizeof(unsigned char), 1, infile);
fread((char*)&huf_tree[i].weight, sizeof(unsigned long), 1, infile);
huf_tree[i].parent = 0;
}
//初始化后面的每一个节点的parent
for (;i < node_num;i++) {
huf_tree[i].parent = 0;
}
CreateTree(huf_tree, char_kinds, node_num);
//读完了字符和权重的信息,再读取文件长度和编码,开始解压缩
fread((char*)&file_len, sizeof(unsigned long), 1, infile);
outfile = fopen(ofname, "wb");
root = node_num - 1;
while (1) {
fread((char*)&code_temp, sizeof(unsigned char), 1, infile);
for (i = 0;i < 8;i++) {
//从root开始到叶子节点进行恢复
if (code_temp & 128)
root = huf_tree[root].rchild;
else
root = huf_tree[root].lchild;
if (root < char_kinds) {
fwrite((char*)&huf_tree[root].uch, sizeof(unsigned char), 1, outfile);
++writen_len;
if (writen_len == file_len)
break;
root = node_num - 1;//复位根索引,匹配下一个字符
}
code_temp <<= 1;//将编码缓存的下一个移动到最高位,供匹配
}
if (writen_len == file_len)
break;
}
fclose(infile);
fclose(outfile);
free(huf_tree);
}
}
int main(void) {
//compress("d://dingst.bmp", "d://dingst.bmp.hfm");
//extract("d://dingst.bmp.hfm","d://laoxia.bmp");
{
FILE* fpSrc = fopen("d://dingst.bmp", "r");
fseek(fpSrc, 0L, SEEK_END);
printf("dinst BMP size=%d\n", ftell(fpSrc));
fclose(fpSrc);
}
///////////////////////HFM
{
FILE* fpSrc = fopen("d://dingst.bmp.hfm", "r");
fseek(fpSrc, 0L, SEEK_END);
printf("huffman压缩的 size=%d\n", ftell(fpSrc));
fclose(fpSrc);
}
/////////////////////end HFM
///////////////////////解压还原的
{
FILE* fpSrc = fopen("d://laoxia.bmp", "r");
fseek(fpSrc, 0L, SEEK_END);
printf("huffman还原的 size=%d\n", ftell(fpSrc));
fclose(fpSrc);
}
/////////////////////end 还原
system("pause");
return 0;
}