forked from mmc-maodun/Data-Structure-And-Algorithm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9edfc57
Showing
55 changed files
with
4,663 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
#include<stdio.h> | ||
#include<stdlib.h> | ||
#include<string.h> | ||
#include"data_structure.h" | ||
|
||
/* | ||
根据给定的n个权值构造一棵赫夫曼树,wet中存放n个权值 | ||
*/ | ||
HuffmanTree create_HuffmanTree(int *wet,int n) | ||
{ | ||
//一棵有n个叶子节点的赫夫曼树共有2n-1个节点 | ||
int total = 2*n-1; | ||
HuffmanTree HT = (HuffmanTree)malloc(total*sizeof(HTNode)); | ||
if(!HT) | ||
{ | ||
printf("HuffmanTree malloc faild!"); | ||
exit(-1); | ||
} | ||
int i; | ||
|
||
//以下初始化序号全部用-1表示, | ||
//这样在编码函数中进行循环判断parent或lchild或rchild的序号时, | ||
//不会与HT数组中的任何一个下标混淆而造成误判 | ||
|
||
//HT[0],HT[1]...HT[n-1]中存放需要编码的n个叶子节点 | ||
for(i=0;i<n;i++) | ||
{ | ||
HT[i].parent = -1; | ||
HT[i].lchild = -1; | ||
HT[i].rchild = -1; | ||
HT[i].weight = *wet; | ||
wet++; | ||
} | ||
|
||
//HT[n],HT[n+1]...HT[2n-2]中存放的是中间构造出的每棵二叉树的根节点 | ||
for(;i<total;i++) | ||
{ | ||
HT[i].parent = -1; | ||
HT[i].lchild = -1; | ||
HT[i].rchild = -1; | ||
HT[i].weight = 0; | ||
} | ||
|
||
int min1,min2; //用来保存每一轮选出的两个weight最小且parent为0的节点 | ||
//每一轮比较后选择出min1和min2构成一课二叉树,最后构成一棵赫夫曼树 | ||
for(i=n;i<total;i++) | ||
{ | ||
select_minium(HT,i,min1,min2); | ||
HT[min1].parent = i; | ||
HT[min2].parent = i; | ||
//这里左孩子和右孩子可以反过来,构成的也是一棵赫夫曼树,只是所得的编码不同 | ||
HT[i].lchild = min1; | ||
HT[i].rchild = min2; | ||
HT[i].weight =HT[min1].weight + HT[min2].weight; | ||
} | ||
return HT; | ||
} | ||
|
||
/* | ||
从HT数组的前k个元素中选出weight最小且parent为-1的两个,分别将其序号保存在min1和min2中 | ||
*/ | ||
void select_minium(HuffmanTree HT,int k,int &min1,int &min2) | ||
{ | ||
min1 = min(HT,k); | ||
min2 = min(HT,k); | ||
} | ||
|
||
/* | ||
从HT数组的前k个元素中选出weight最小且parent为-1的元素,并将该元素的序号返回 | ||
*/ | ||
int min(HuffmanTree HT,int k) | ||
{ | ||
int i = 0; | ||
int min; //用来存放weight最小且parent为-1的元素的序号 | ||
int min_weight; //用来存放weight最小且parent为-1的元素的weight值 | ||
|
||
//先将第一个parent为-1的元素的weight值赋给min_weight,留作以后比较用。 | ||
//注意,这里不能按照一般的做法,先直接将HT[0].weight赋给min_weight, | ||
//因为如果HT[0].weight的值比较小,那么在第一次构造二叉树时就会被选走, | ||
//而后续的每一轮选择最小权值构造二叉树的比较还是先用HT[0].weight的值来进行判断, | ||
//这样又会再次将其选走,从而产生逻辑上的错误。 | ||
while(HT[i].parent != -1) | ||
i++; | ||
min_weight = HT[i].weight; | ||
min = i; | ||
|
||
//选出weight最小且parent为-1的元素,并将其序号赋给min | ||
for(;i<k;i++) | ||
{ | ||
if(HT[i].weight<min_weight && HT[i].parent==-1) | ||
{ | ||
min_weight = HT[i].weight; | ||
min = i; | ||
} | ||
} | ||
|
||
//选出weight最小的元素后,将其parent置1,使得下一次比较时将其排除在外。 | ||
HT[min].parent = 1; | ||
|
||
return min; | ||
} | ||
|
||
/* | ||
从叶子节点到根节点逆向求赫夫曼树HT中n个叶子节点的赫夫曼编码,并保存在HC中 | ||
*/ | ||
void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n) | ||
{ | ||
//用来保存指向每个赫夫曼编码串的指针 | ||
HC = (HuffmanCode)malloc(n*sizeof(char *)); | ||
if(!HC) | ||
{ | ||
printf("HuffmanCode malloc faild!"); | ||
exit(-1); | ||
} | ||
|
||
//临时空间,用来保存每次求得的赫夫曼编码串 | ||
//对于有n个叶子节点的赫夫曼树,各叶子节点的编码长度最长不超过n-1 | ||
//外加一个'\0'结束符,因此分配的数组长度最长为n即可 | ||
char *code = (char *)malloc(n*sizeof(char)); | ||
if(!code) | ||
{ | ||
printf("code malloc faild!"); | ||
exit(-1); | ||
} | ||
|
||
code[n-1] = '\0'; //编码结束符,亦是字符数组的结束标志 | ||
//求每个字符的赫夫曼编码 | ||
int i; | ||
for(i=0;i<n;i++) | ||
{ | ||
int current = i; //定义当前访问的节点 | ||
int father = HT[i].parent; //当前节点的父节点 | ||
int start = n-1; //每次编码的位置,初始为编码结束符的位置 | ||
//从叶子节点遍历赫夫曼树直到根节点 | ||
while(father != -1) | ||
{ | ||
if(HT[father].lchild == current) //如果是左孩子,则编码为0 | ||
code[--start] = '0'; | ||
else //如果是右孩子,则编码为1 | ||
code[--start] = '1'; | ||
current = father; | ||
father = HT[father].parent; | ||
} | ||
|
||
//为第i个字符的编码串分配存储空间 | ||
HC[i] = (char *)malloc((n-start)*sizeof(char)); | ||
if(!HC[i]) | ||
{ | ||
printf("HC[i] malloc faild!"); | ||
exit(-1); | ||
} | ||
//将编码串从code复制到HC | ||
strcpy(HC[i],code+start); | ||
} | ||
|
||
free(code); //释放保存编码串的临时空间 | ||
} | ||
|
||
/* | ||
从根节点到叶子节点无栈非递归遍历赫夫曼树HT,求其中n个叶子节点的赫夫曼编码,并保存在HC中 | ||
*/ | ||
void HuffmanCoding2(HuffmanTree HT,HuffmanCode &HC,int n) | ||
{ | ||
//用来保存指向每个赫夫曼编码串的指针 | ||
HC = (HuffmanCode)malloc(n*sizeof(char *)); | ||
if(!HC) | ||
{ | ||
printf("HuffmanCode malloc faild!"); | ||
exit(-1); | ||
} | ||
|
||
//临时空间,用来保存每次求得的赫夫曼编码串 | ||
//对于有n个叶子节点的赫夫曼树,各叶子节点的编码长度最长不超过n-1 | ||
//外加一个'\0'结束符,因此分配的数组长度最长为n即可 | ||
char *code = (char *)malloc(n*sizeof(char)); | ||
if(!code) | ||
{ | ||
printf("code malloc faild!"); | ||
exit(-1); | ||
} | ||
|
||
int cur = 2*n-2; //当前遍历到的节点的序号,初始时为根节点序号 | ||
int code_len = 0; //定义编码的长度 | ||
|
||
//构建好赫夫曼树后,把weight用来当做遍历树时每个节点的状态标志 | ||
//weight=0表明当前节点的左右孩子都还没有被遍历 | ||
//weight=1表示当前节点的左孩子已经被遍历过,右孩子尚未被遍历 | ||
//weight=2表示当前节点的左右孩子均被遍历过 | ||
int i; | ||
for(i=0;i<cur+1;i++) | ||
{ | ||
HT[i].weight = 0; | ||
} | ||
|
||
//从根节点开始遍历,最后回到根节点结束 | ||
//当cur为根节点的parent时,退出循环 | ||
while(cur != -1) | ||
{ | ||
//左右孩子均未被遍历,先向左遍历 | ||
if(HT[cur].weight == 0) | ||
{ | ||
HT[cur].weight = 1; //表明其左孩子已经被遍历过了 | ||
if(HT[cur].lchild != -1) | ||
{ //如果当前节点不是叶子节点,则记下编码,并继续向左遍历 | ||
code[code_len++] = '0'; | ||
cur = HT[cur].lchild; | ||
} | ||
else | ||
{ //如果当前节点是叶子节点,则终止编码,并将其保存起来 | ||
code[code_len] = '\0'; | ||
HC[cur] = (char *)malloc((code_len+1)*sizeof(char)); | ||
if(!HC[cur]) | ||
{ | ||
printf("HC[cur] malloc faild!"); | ||
exit(-1); | ||
} | ||
strcpy(HC[cur],code); //复制编码串 | ||
} | ||
} | ||
|
||
//左孩子已被遍历,开始向右遍历右孩子 | ||
else if(HT[cur].weight == 1) | ||
{ | ||
HT[cur].weight = 2; //表明其左右孩子均被遍历过了 | ||
if(HT[cur].rchild != -1) | ||
{ //如果当前节点不是叶子节点,则记下编码,并继续向右遍历 | ||
code[code_len++] = '1'; | ||
cur = HT[cur].rchild; | ||
} | ||
} | ||
|
||
//左右孩子均已被遍历,退回到父节点,同时编码长度减1 | ||
else | ||
{ | ||
HT[cur].weight = 0; | ||
cur = HT[cur].parent; | ||
--code_len; | ||
} | ||
|
||
} | ||
free(code); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
赫夫曼树的存储结构,它也是一种二叉树结构, | ||
这种存储结构既适合表示树,也适合表示森林。 | ||
*/ | ||
typedef struct Node | ||
{ | ||
int weight; //权值 | ||
int parent; //父节点的序号,为-1的是根节点 | ||
int lchild,rchild; //左右孩子节点的序号,为-1的是叶子节点 | ||
}HTNode,*HuffmanTree; //用来存储赫夫曼树中的所有节点 | ||
typedef char **HuffmanCode; //用来存储每个叶子节点的赫夫曼编码 | ||
|
||
|
||
//根据给定数量的权值构造一棵赫夫曼树 | ||
HuffmanTree create_HuffmanTree(int *,int); | ||
|
||
//从所有节点中选出权值最小的根节点,并将其在数组中的序号返回 | ||
//该函数主要是供select_minium函数调用 | ||
int min(HuffmanTree ,int); | ||
|
||
//从所有节点中选出权值最小的两个根节点,并将其序号分别保存在后两个参数中 | ||
void select_minium(HuffmanTree,int,int &,int &); | ||
|
||
//从叶子节点到根节点逆向求每个字符的赫夫曼编码 | ||
void HuffmanCoding(HuffmanTree,HuffmanCode &,int); | ||
|
||
//从根节点到叶子节点无栈非递归遍历赫夫曼树,并求叶子节点的赫夫曼编码 | ||
void HuffmanCoding2(HuffmanTree,HuffmanCode &,int); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#include<stdio.h> | ||
#include<stdlib.h> | ||
#include<string.h> | ||
#include"data_structure.h" | ||
|
||
int main() | ||
{ | ||
int n; //需要编码的字符的个数 | ||
printf("请输入需要编码的字符的个数(>1):"); | ||
scanf("%d",&n); | ||
while(n<=1) | ||
{ | ||
printf("字符个数必须大于1,请重新输入:"); | ||
scanf("%d",&n); | ||
} | ||
|
||
int i; | ||
int *wet = (int *)malloc(n*sizeof(int)); //存放每个字符的权值 | ||
printf("请依次输入这%d个字符的权值(整型):",n); | ||
for(i=0;i<n;i++) | ||
{ | ||
scanf("%d",wet+i); | ||
} | ||
|
||
HuffmanCode HC; //保存赫夫曼编码 | ||
HuffmanTree HT = create_HuffmanTree(wet,n); //生成赫夫曼树 | ||
HuffmanCoding(HT,HC,n); //第一种方法求每个字符的赫夫曼编码 | ||
// HuffmanCoding2(HT,HC,n); //第二种方法求每个字符的赫夫曼编码 | ||
|
||
for(i=0;i<n;i++) | ||
{ | ||
puts(HC[i]); | ||
} | ||
free(wet); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#define MAX 26 //字符集的大小 | ||
|
||
/* | ||
字典树的存储结构 | ||
*/ | ||
typedef struct Node | ||
{ | ||
struct Node *next[MAX]; //每个节点下面可能有MAX个字符 | ||
int count; //以从根节点到当前节点的字符串为公共前缀的字符串数目 | ||
}TrieNode,*TrieTree; | ||
|
||
//创建一课只有根节点的字典树 | ||
TrieTree create_TrieTree(); | ||
|
||
//向字典树中插入字符串 | ||
void insert_TrieTree(TrieTree,char *); | ||
|
||
//统计字典树中有给定公共前缀的字符串的数目 | ||
int count_TrieTree(TrieTree ,char *); | ||
|
||
//销毁字典树 | ||
void destroy_TrieTree(TrieTree); |
Oops, something went wrong.