Skip to content

Commit 9edfc57

Browse files
committed
常用数据结构与算法
0 parents  commit 9edfc57

File tree

55 files changed

+4663
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+4663
-0
lines changed

Huffman tree/Function.cpp

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
#include<stdio.h>
2+
#include<stdlib.h>
3+
#include<string.h>
4+
#include"data_structure.h"
5+
6+
/*
7+
根据给定的n个权值构造一棵赫夫曼树,wet中存放n个权值
8+
*/
9+
HuffmanTree create_HuffmanTree(int *wet,int n)
10+
{
11+
//一棵有n个叶子节点的赫夫曼树共有2n-1个节点
12+
int total = 2*n-1;
13+
HuffmanTree HT = (HuffmanTree)malloc(total*sizeof(HTNode));
14+
if(!HT)
15+
{
16+
printf("HuffmanTree malloc faild!");
17+
exit(-1);
18+
}
19+
int i;
20+
21+
//以下初始化序号全部用-1表示,
22+
//这样在编码函数中进行循环判断parent或lchild或rchild的序号时,
23+
//不会与HT数组中的任何一个下标混淆而造成误判
24+
25+
//HT[0],HT[1]...HT[n-1]中存放需要编码的n个叶子节点
26+
for(i=0;i<n;i++)
27+
{
28+
HT[i].parent = -1;
29+
HT[i].lchild = -1;
30+
HT[i].rchild = -1;
31+
HT[i].weight = *wet;
32+
wet++;
33+
}
34+
35+
//HT[n],HT[n+1]...HT[2n-2]中存放的是中间构造出的每棵二叉树的根节点
36+
for(;i<total;i++)
37+
{
38+
HT[i].parent = -1;
39+
HT[i].lchild = -1;
40+
HT[i].rchild = -1;
41+
HT[i].weight = 0;
42+
}
43+
44+
int min1,min2; //用来保存每一轮选出的两个weight最小且parent为0的节点
45+
//每一轮比较后选择出min1和min2构成一课二叉树,最后构成一棵赫夫曼树
46+
for(i=n;i<total;i++)
47+
{
48+
select_minium(HT,i,min1,min2);
49+
HT[min1].parent = i;
50+
HT[min2].parent = i;
51+
//这里左孩子和右孩子可以反过来,构成的也是一棵赫夫曼树,只是所得的编码不同
52+
HT[i].lchild = min1;
53+
HT[i].rchild = min2;
54+
HT[i].weight =HT[min1].weight + HT[min2].weight;
55+
}
56+
return HT;
57+
}
58+
59+
/*
60+
从HT数组的前k个元素中选出weight最小且parent为-1的两个,分别将其序号保存在min1和min2中
61+
*/
62+
void select_minium(HuffmanTree HT,int k,int &min1,int &min2)
63+
{
64+
min1 = min(HT,k);
65+
min2 = min(HT,k);
66+
}
67+
68+
/*
69+
从HT数组的前k个元素中选出weight最小且parent为-1的元素,并将该元素的序号返回
70+
*/
71+
int min(HuffmanTree HT,int k)
72+
{
73+
int i = 0;
74+
int min; //用来存放weight最小且parent为-1的元素的序号
75+
int min_weight; //用来存放weight最小且parent为-1的元素的weight值
76+
77+
//先将第一个parent为-1的元素的weight值赋给min_weight,留作以后比较用。
78+
//注意,这里不能按照一般的做法,先直接将HT[0].weight赋给min_weight,
79+
//因为如果HT[0].weight的值比较小,那么在第一次构造二叉树时就会被选走,
80+
//而后续的每一轮选择最小权值构造二叉树的比较还是先用HT[0].weight的值来进行判断,
81+
//这样又会再次将其选走,从而产生逻辑上的错误。
82+
while(HT[i].parent != -1)
83+
i++;
84+
min_weight = HT[i].weight;
85+
min = i;
86+
87+
//选出weight最小且parent为-1的元素,并将其序号赋给min
88+
for(;i<k;i++)
89+
{
90+
if(HT[i].weight<min_weight && HT[i].parent==-1)
91+
{
92+
min_weight = HT[i].weight;
93+
min = i;
94+
}
95+
}
96+
97+
//选出weight最小的元素后,将其parent置1,使得下一次比较时将其排除在外。
98+
HT[min].parent = 1;
99+
100+
return min;
101+
}
102+
103+
/*
104+
从叶子节点到根节点逆向求赫夫曼树HT中n个叶子节点的赫夫曼编码,并保存在HC中
105+
*/
106+
void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n)
107+
{
108+
//用来保存指向每个赫夫曼编码串的指针
109+
HC = (HuffmanCode)malloc(n*sizeof(char *));
110+
if(!HC)
111+
{
112+
printf("HuffmanCode malloc faild!");
113+
exit(-1);
114+
}
115+
116+
//临时空间,用来保存每次求得的赫夫曼编码串
117+
//对于有n个叶子节点的赫夫曼树,各叶子节点的编码长度最长不超过n-1
118+
//外加一个'\0'结束符,因此分配的数组长度最长为n即可
119+
char *code = (char *)malloc(n*sizeof(char));
120+
if(!code)
121+
{
122+
printf("code malloc faild!");
123+
exit(-1);
124+
}
125+
126+
code[n-1] = '\0'; //编码结束符,亦是字符数组的结束标志
127+
//求每个字符的赫夫曼编码
128+
int i;
129+
for(i=0;i<n;i++)
130+
{
131+
int current = i; //定义当前访问的节点
132+
int father = HT[i].parent; //当前节点的父节点
133+
int start = n-1; //每次编码的位置,初始为编码结束符的位置
134+
//从叶子节点遍历赫夫曼树直到根节点
135+
while(father != -1)
136+
{
137+
if(HT[father].lchild == current) //如果是左孩子,则编码为0
138+
code[--start] = '0';
139+
else //如果是右孩子,则编码为1
140+
code[--start] = '1';
141+
current = father;
142+
father = HT[father].parent;
143+
}
144+
145+
//为第i个字符的编码串分配存储空间
146+
HC[i] = (char *)malloc((n-start)*sizeof(char));
147+
if(!HC[i])
148+
{
149+
printf("HC[i] malloc faild!");
150+
exit(-1);
151+
}
152+
//将编码串从code复制到HC
153+
strcpy(HC[i],code+start);
154+
}
155+
156+
free(code); //释放保存编码串的临时空间
157+
}
158+
159+
/*
160+
从根节点到叶子节点无栈非递归遍历赫夫曼树HT,求其中n个叶子节点的赫夫曼编码,并保存在HC中
161+
*/
162+
void HuffmanCoding2(HuffmanTree HT,HuffmanCode &HC,int n)
163+
{
164+
//用来保存指向每个赫夫曼编码串的指针
165+
HC = (HuffmanCode)malloc(n*sizeof(char *));
166+
if(!HC)
167+
{
168+
printf("HuffmanCode malloc faild!");
169+
exit(-1);
170+
}
171+
172+
//临时空间,用来保存每次求得的赫夫曼编码串
173+
//对于有n个叶子节点的赫夫曼树,各叶子节点的编码长度最长不超过n-1
174+
//外加一个'\0'结束符,因此分配的数组长度最长为n即可
175+
char *code = (char *)malloc(n*sizeof(char));
176+
if(!code)
177+
{
178+
printf("code malloc faild!");
179+
exit(-1);
180+
}
181+
182+
int cur = 2*n-2; //当前遍历到的节点的序号,初始时为根节点序号
183+
int code_len = 0; //定义编码的长度
184+
185+
//构建好赫夫曼树后,把weight用来当做遍历树时每个节点的状态标志
186+
//weight=0表明当前节点的左右孩子都还没有被遍历
187+
//weight=1表示当前节点的左孩子已经被遍历过,右孩子尚未被遍历
188+
//weight=2表示当前节点的左右孩子均被遍历过
189+
int i;
190+
for(i=0;i<cur+1;i++)
191+
{
192+
HT[i].weight = 0;
193+
}
194+
195+
//从根节点开始遍历,最后回到根节点结束
196+
//当cur为根节点的parent时,退出循环
197+
while(cur != -1)
198+
{
199+
//左右孩子均未被遍历,先向左遍历
200+
if(HT[cur].weight == 0)
201+
{
202+
HT[cur].weight = 1; //表明其左孩子已经被遍历过了
203+
if(HT[cur].lchild != -1)
204+
{ //如果当前节点不是叶子节点,则记下编码,并继续向左遍历
205+
code[code_len++] = '0';
206+
cur = HT[cur].lchild;
207+
}
208+
else
209+
{ //如果当前节点是叶子节点,则终止编码,并将其保存起来
210+
code[code_len] = '\0';
211+
HC[cur] = (char *)malloc((code_len+1)*sizeof(char));
212+
if(!HC[cur])
213+
{
214+
printf("HC[cur] malloc faild!");
215+
exit(-1);
216+
}
217+
strcpy(HC[cur],code); //复制编码串
218+
}
219+
}
220+
221+
//左孩子已被遍历,开始向右遍历右孩子
222+
else if(HT[cur].weight == 1)
223+
{
224+
HT[cur].weight = 2; //表明其左右孩子均被遍历过了
225+
if(HT[cur].rchild != -1)
226+
{ //如果当前节点不是叶子节点,则记下编码,并继续向右遍历
227+
code[code_len++] = '1';
228+
cur = HT[cur].rchild;
229+
}
230+
}
231+
232+
//左右孩子均已被遍历,退回到父节点,同时编码长度减1
233+
else
234+
{
235+
HT[cur].weight = 0;
236+
cur = HT[cur].parent;
237+
--code_len;
238+
}
239+
240+
}
241+
free(code);
242+
}

Huffman tree/data_structure.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
赫夫曼树的存储结构,它也是一种二叉树结构,
3+
这种存储结构既适合表示树,也适合表示森林。
4+
*/
5+
typedef struct Node
6+
{
7+
int weight; //权值
8+
int parent; //父节点的序号,为-1的是根节点
9+
int lchild,rchild; //左右孩子节点的序号,为-1的是叶子节点
10+
}HTNode,*HuffmanTree; //用来存储赫夫曼树中的所有节点
11+
typedef char **HuffmanCode; //用来存储每个叶子节点的赫夫曼编码
12+
13+
14+
//根据给定数量的权值构造一棵赫夫曼树
15+
HuffmanTree create_HuffmanTree(int *,int);
16+
17+
//从所有节点中选出权值最小的根节点,并将其在数组中的序号返回
18+
//该函数主要是供select_minium函数调用
19+
int min(HuffmanTree ,int);
20+
21+
//从所有节点中选出权值最小的两个根节点,并将其序号分别保存在后两个参数中
22+
void select_minium(HuffmanTree,int,int &,int &);
23+
24+
//从叶子节点到根节点逆向求每个字符的赫夫曼编码
25+
void HuffmanCoding(HuffmanTree,HuffmanCode &,int);
26+
27+
//从根节点到叶子节点无栈非递归遍历赫夫曼树,并求叶子节点的赫夫曼编码
28+
void HuffmanCoding2(HuffmanTree,HuffmanCode &,int);

Huffman tree/main.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include<stdio.h>
2+
#include<stdlib.h>
3+
#include<string.h>
4+
#include"data_structure.h"
5+
6+
int main()
7+
{
8+
int n; //需要编码的字符的个数
9+
printf("请输入需要编码的字符的个数(>1):");
10+
scanf("%d",&n);
11+
while(n<=1)
12+
{
13+
printf("字符个数必须大于1,请重新输入:");
14+
scanf("%d",&n);
15+
}
16+
17+
int i;
18+
int *wet = (int *)malloc(n*sizeof(int)); //存放每个字符的权值
19+
printf("请依次输入这%d个字符的权值(整型):",n);
20+
for(i=0;i<n;i++)
21+
{
22+
scanf("%d",wet+i);
23+
}
24+
25+
HuffmanCode HC; //保存赫夫曼编码
26+
HuffmanTree HT = create_HuffmanTree(wet,n); //生成赫夫曼树
27+
HuffmanCoding(HT,HC,n); //第一种方法求每个字符的赫夫曼编码
28+
// HuffmanCoding2(HT,HC,n); //第二种方法求每个字符的赫夫曼编码
29+
30+
for(i=0;i<n;i++)
31+
{
32+
puts(HC[i]);
33+
}
34+
free(wet);
35+
36+
return 0;
37+
}

Trie Tree/data_structure.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#define MAX 26 //字符集的大小
2+
3+
/*
4+
字典树的存储结构
5+
*/
6+
typedef struct Node
7+
{
8+
struct Node *next[MAX]; //每个节点下面可能有MAX个字符
9+
int count; //以从根节点到当前节点的字符串为公共前缀的字符串数目
10+
}TrieNode,*TrieTree;
11+
12+
//创建一课只有根节点的字典树
13+
TrieTree create_TrieTree();
14+
15+
//向字典树中插入字符串
16+
void insert_TrieTree(TrieTree,char *);
17+
18+
//统计字典树中有给定公共前缀的字符串的数目
19+
int count_TrieTree(TrieTree ,char *);
20+
21+
//销毁字典树
22+
void destroy_TrieTree(TrieTree);

0 commit comments

Comments
 (0)