哈夫曼树链式存储及简单哈夫曼编码VB实现
来源:互联网 发布:北大青鸟java课程表 编辑:程序博客网 时间:2024/05/18 01:55
一.哈夫曼树链式存储
首先做如下定义:
Typedef struct HuffNode{
Int data;/*权值*/
Struct HuffNode *LChild;
Struct HuffNode *RChild;
}HuffNode,*HuffTree;
我们在构造时,先建议叶子结点,用一组HuffNode型的指针数组(HuffNode * S
)表示:
Void createHuffTree(HuffTree *ht,int a[],int n)
S[i]=(HuffTree)malloc(sizeof(HuffNode));
S[i]->data=a[i];
S[i]->LChild=NULL;s[i]->RChild=NULL;
然后,找到s[i]->data 的两个结点,设为s[x1],s[x2];定义临时结点 HuffNode* temp;temp=(HuffTree)malloc(sizeof(HuffTree));
Temp->data=s[x1]->data+s[x2]->data;
temp->LChild=s[x1];Temp->RChild=s[x2];
s[x1]=temp;//将temp结点加入到数组s中。删除s[x1];
S[x2]=NULL;//删除s[x2];
接着再找最小的,后面过程是重复的,对于n个叶子结点的哈夫曼树,该循环体其实只用执行n-1次。
最后一步,直接赋值:*ht=temp;
其实上面过程中的指针 temp,完全可以用*ht代替,那样的话,最后一步就赘余了。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define M 20
#define INF 100
typedef struct HuffNode{
int data;
struct HuffNode *LChild;
struct HuffNode *RChild;
}HuffNode,*HuffTree;
void CreateHuffTree(HuffTree *ht){
int min1,min2,mid;
HuffNode *s
,*temp;
int i,n,m;
for(i=0;i<M;i++) s
=NULL;/*初始化。。*/
printf("请输入叶子结点的个数\n");
scanf("%d",&n);
printf("请输入权值\n");
for(i=0;i<n;i++){
s[i]=(HuffNode *)malloc(sizeof(HuffNode));
scanf("%d",&(s[i]->data));
s[i]->LChild=NULL;
s[i]->RChild=NULL;
}/*创建叶子结点*/
m=n-1;
do{
m--;
mid=INF;
for(i=0;i<n;i++)
if((s[i]!=NULL)&&(mid>s[i]->data)) {mid=s[i]->data;min1=i;}
mid=INF;
for(i=0;i<n;i++)
if((s[i]!=NULL)&&(i!=min1)&&(mid>s[i]->data)) {mid=s[i]->data;min2=i;}/*找最小的2个结点*/
temp=(HuffTree)malloc(sizeof(HuffNode));
temp->data=s[min1]->data+s[min2]->data;
temp->LChild=s[min1];
temp->RChild=s[min2];
s[min1]=temp;
s[min2]=NULL;
}while(m);
(*ht)=temp;
}
void PrintTree(HuffTree ht,int n){
int i;
if(ht==NULL) return;
PrintTree(ht->RChild,n+1);
for(i=0;i<n;i++)
printf(" ");
printf("%d\n",ht->data);
PrintTree(ht->LChild,n+1);
}
main(){
HuffTree ht;
CreateHuffTree(&ht);
PrintTree(ht,0);
}
运行结果:
二.哈夫曼编码(Visual Basic 6.0 实现)
算法核心:创建哈夫曼树、加密及解密。
1. 创建哈夫曼树:本程序在创建哈夫曼树时采用了静态表的存储方式,与以往相比,哈夫曼树的结点元素增加了两个元素:tag标记与information信息,方便编码。其中information信息可以不要,因为我之前写的哈夫曼树中没有parent信息,本次沿用以前的哈夫曼树的创建方法,为了减少改动故没删掉information信息造成内存的浪费,敬请原谅!!
关于编码程序及exe文件,已上传CSDN(及新浪爱问):http://download.csdn.net/source/3570180
欢迎下载。。。
哈夫曼树头结点定义如下:
Type HuffTree
data1 As String ‘结点数据字符串
data2 As Integer ‘结点权值,整型
parent As Integer
LChild As Integer
RChild As Integer
tag As String * 1 ‘定义长度为一的定长字符串,其值为0或1,分别代表该结点是其双亲的左、右孩子
information As Boolean ‘布尔型,标记结点是否有双亲
End Type
其算法思想与数据结构课本上的类同,此处不再赘述。
2. 加密:
加密前的处理:
创建好树后,对给定的加密前的字符串S,我们将它进行分割,之所以进行分割,是为了保证加密后的字符串不至于太长,以免解密时发生堆栈溢出错误(系统决定的没办法)!我们将以每十个字符作为一个子串,逐个加密,加密后的串存于数组sJie()中。
加密过程:
首先利用mid函数截取字符串sS中的每个字符依次赋给Os: Os$=mid$(sS,i,1) ‘i为循环变量,i=1 to len(sS)
然后先根遍历哈夫曼树找到结点Os(返回其下标index)
用串Bstring连接该结点的tag值,之后连接其parent结点的tag值,依次找parent,一直到树根,连接其tag值。不过这样得到编码串Bstring与我们需要串是反序的,所以只用将Bstring逆序即可得到加密串。如此重复下去,直到 i=原串的长度(Len(sS))退出即可。
3. 解密
解密前的准备:
解密的串的来源有两种,一种是上次编码后的串,另一种是用户输入的串。对于前一种串,在加密的时候已经进行分割sJie().而对于用户输入的串我们也要进行分割,我们以每30个字符作为一个子串;只不过这种分割不一定是一个整串,这一点有点棘手,只能定义一个全局变量p存储上一步调用解密函数访问到那个点的下标,下次接着访问。如果刚好访问到叶子结点,则下次从根节点(此时p=2*n-2,n为叶子结点的个数)开始访问。
解密操作(函数):
因为我们之前已经创建了哈夫曼树,所以就不用字符串匹配了,这里我们将直接利用上已经建好的哈夫曼树。
我们利用mid()函数依次截取解密字符串sS中每个字符,依次存于Os中:Os$=mid$(sS,i,1) ‘此处的i的意义与加密时一样
下面对Os进行判断:(假设定义了树 :ht() as HuffTree)
如果 Os=”0” ,往左孩子转(p=ht(p).LChild);否则,往右孩子转(p=ht(p).RChild).
接着进行判断:判断p是否为叶子结点(ht(p).LChild=-1 And ht(p).RChild=-1),如果是叶子结点,则记下该结的数据(Rstring=Rstring+ht(p).data1)’“+”表示连接
并且,又从树根(p=2*n-2)起,进行下一次解密。
‘ ====================================================
4. 哈夫曼编码之vb实现:
打开Visual Basic 6.0 ,一共添加3 个窗体(Form1.frm、Form2.frm、Form3.frm)、添加一个模块(Module1.bas)
各个窗体及其上的控件属性见下表:
另外,点击菜单编辑器,给form1加两个菜单
菜单1
标题:设置(&S);名称:Set;可视
菜单2
标题:帮助(&H);名称:HelpMe;可视
模块Module1.代码如下:
Type HuffTree
data1 As String
data2 As Integer
parent As Integer
LChild As Integer
RChild As Integer
tag As String * 1
information As Boolean
End Type
Global xx As Integer
Global PW As String
Global iL As Integer
Global n As Integer
Global p As Integer
Function JiaMi(h() As HuffTree, ByVal ss As String)
Dim Os As String * 1
Dim pNode As Integer
Dim x As Integer
Dim BString As String
Dim length As Integer
Dim midstring As String
length = Len(ss)
For i = 1 To length
Os = Mid(ss, i, 1)
x = xx
SearchNode h(), x, Os, pNode
Do Until h(pNode).parent = -1
midstring = midstring + h(pNode).tag
pNode = h(pNode).parent
Loop
BString = BString + rev(midstring)
Os$ = ""
midstring = ""
Next i
JiaMi = BString
BString = ""
End Function
Function JieMi(h() As HuffTree, ss As String)
Dim RString As String
Dim Os As String * 1
Dim length As Integer
length = Len(ss)
i = 1
For i = 1 To length
Os = Mid(ss, i, 1)
If Os = "0" Then
p = h(p).LChild
Else
p = h(p).RChild
End If
If h(p).LChild = -1 And h(p).RChild = -1 Then
RString = RString + h(p).data1
p = xx
End If
Next i
JieMi = RString
RString = ""
End Function
Function SearchNode(h() As HuffTree, i As Integer, Os As String, pNode As Integer)
If i = -1 Then
Exit Function
End If
If h(i).data1 = Os Then
pNode = i
Exit Function
End If
SearchNode h(), h(i).LChild, Os, pNode
SearchNode h(), h(i).RChild, Os, pNode
End Function
Function rev(s As String)
Dim sstring As String
length = Len(s)
For i = 1 To length
sstring = sstring + Mid(s, length - i + 1, 1)
rev = sstring
Next i
End Function
Form1代码如下:
Dim ht() As HuffTree
Dim index1, index2 As Integer
Dim sJia, sJie() As String
Private Sub Command1_Click(Index As Integer)
Select Case Index
Case 0
Dim ss As String
Dim length As Integer
ss = Text1.Text
length = Len(ss)
Text1.Text = ""
If length Mod 10 = 0 Then
iL = length / 10
Else
iL = length \ 10 + 1
End If
ReDim sJia(iL) As String
ReDim sJie(iL) As String
For i = 0 To iL - 1
sJia(i) = Mid$(ss, i * 10 + 1, 10)
sJie(i) = JiaMi(ht(), sJia(i))
Text1.Text = Text1.Text + sJie(i)
Next i
r = InputBox("加密完成,是否写入文本?(Y/N)")
If UCase(r) = "Y" Then
Open "JiaString.txt" For Output As #1
Print #1, Text1.Text
Close #1
MsgBox "恭喜,系统已将加密文本写为本软件所在目录下的JiaString.txt;请注意查收!",”VbOkOnly”,”操作成功”
End If
'---------------------------------------------------
Case 1
If iL = 0 Then
Dim s As String
s = Text1.Text
l = Len(s)
If l Mod 30 = 0 Then
iL = l / 30
Else
iL = l \ 30 + 1
End If
ReDim sJie(iL) As String
For i = 0 To iL - 1
sJie(i) = Mid(s, i * 30 + 1, 30)
Next i
End If
Text1.Text = ""
p = xx
For i = 0 To iL - 1
Text1.Text = Text1.Text + JieMi(ht(), sJie(i))
Next i
iL = 0
r = InputBox("加密完成,是否写入文本?(Y/N)")
If UCase(r) = "Y" Then
Open "JieString.txt" For Output As #1
Print #1, Text1.Text
Close #1
MsgBox "恭喜,系统已将加密文本写为本软件所在目录下的JieString.tex;请注意查收!",”VbOkOnly”,”操作成功”
End If
'---------------------------------------------------
Case 2
Text1.Text = ""
Case 3
End
End Select
End Sub
Private Function Min2(h() As HuffTree, in1, in2)
Min = 10000
For i = 0 To xx
If h(i).information = False And Min > h(i).data2 Then
Min = h(i).data2
in1 = i
End If
Next i
h(in1).information = True
Min = 10000
For i = 0 To xx
If h(i).information = False And Min > h(i).data2 Then
Min = h(i).data2
in2 = i
End If
Next i
h(in2).information = True
End Function
Private Function CreateHuffTree()
Dim ss As String
Dim obj2 As FileSystemObject
Set obj2 = CreateObject("scripting.filesystemobject")
r = obj2.FileExists("sString.dll")
If r Then
z = InputBox("是否沿用上次的编码树?(Y/N)")
If UCase(z) = "Y" Then
Open "sString.dll" For Input As #1
Input #1, s1
Close #1
x = InStr(1, s1, "~")
If x = 0 Then
ss = s1
Else
ss = Mid(s1, 1, x - 1) + "," + Mid(s1, x + 1, Len(s1) - x)
End If
Else
ss = Text1.Text
x = InStr(1, ss, ",")
If x Then
s1 = Mid(ss, 1, x - 1) + "~" + Mid(ss, x + 1, Len(ss) - x)
Else
s1 = ss
End If
Open "sString.dll" For Output As #1
Print #1, s1
Close #1
End If
Else
ss = Text1.Text
x = InStr(1, ss, ",")
If x = 0 Then
s1 = Mid(ss, 1, x - 1) + "~" + Mid(ss, x + 1, Len(ss) - x)
Else
s1 = ss
End If
Open "sString.dll" For Output As #1
Print #1, s1
Close #1
End If
'---------------------------------------------------
n = Len(ss)
xx = 2 * n - 2
ReDim ht(0 To xx) As HuffTree
For i = 0 To n - 1
ht(i).data1 = Mid$(ss, i + 1, 1)
ht(i).data2 = 1
ht(i).LChild = -1: ht(i).RChild = -1: ht(i).information = False: ht(i).parent = -1
Next i
For i = n To xx
ht(i).data2 = 10000
ht(i).data1 = ""
ht(i).parent = -1
Next i
For i = 0 To n - 2
Min2 ht(), index1, index2
ht(n + i).data2 = ht(index1).data2 + ht(index2).data2
ht(n + i).LChild = index1: ht(n + i).RChild = index2: ht(n + i).information = False
ht(index1).parent = n + i: ht(index2).parent = n + i
ht(index1).tag = "0": ht(index2).tag = "1"
Next i
End Function
Private Sub Command2_Click()
CreateHuffTree
Text1.Text = "请输入一个串进行加密或解密"
End Sub
Private Sub Form_Load()
Dim Obs As FileSystemObject
Set Obs = CreateObject("Scripting.FileSystemObject")
r = Obs.FileExists("PassWord.dll")
If r = False Then
PW = ""
Else
Open "PassWord.dll" For Input As #1
Input #1, PW
Close #1
End If
If PW <> "" Then
Form3.Show
Form1.Hide
End If
Text1.Text = "请输入一个串来创建编码树"
End Sub
Private Sub HelpMe_Click()
Shell "cmd /chelp\index.htm", vbHide
End Sub
Private Sub Set_Click()
Form1.Hide
Form2.Show
End Sub
Form2的代码如下:
Private Sub Text1_KeyPress(KeyAscii As Integer)
If KeyAscii = 13 Then
Text2.SetFocus
End If
End Sub
Private Sub Text2_KeyPress(KeyAscii As Integer)
If KeyAscii = 13 Then
Text3.SetFocus
End If
End Sub
Private Sub Text3_KeyPress(KeyAscii As Integer)
If KeyAscii = 13 Then
Ps1 = Text1.Text
Ps2 = Text2.Text
Ps3 = Text3.Text
If Ps1 <> PW Then
MsgBox "原密码错误,请检查", vbOKOnly, "Error"
Form2.Hide
Form1.Show
Else
If Ps2 <> Ps3 Then
MsgBox "两次输入不一致,请重新输入", vbOKOnly, "Error"
Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
Text1.SetFocus
Else
PW = Ps2
Open "PassWord.dll" For Output As #1
Print #1, PW
Close #1
Form1.Show
Form2.Hide
End If
End If
End If
End Sub
Form3的代码如下:
Dim s As String
Private Sub Text1_KeyPress(KeyAscii As Integer)
s = Text1.Text
If KeyAscii = 13 Then
Form3.Hide
Form2.Hide
Form1.Show
If s <> PW Then
MsgBox "密码错误,请检查", vbDefaultButton1, "错误提示"
End
End If
End If
End Sub
注:由于本程序的帮助文件使用网页写的,而且镶嵌图片,故此处不列出代码,如想调试运行上述代码,请删除form1代码中的
Private Sub HelpMe_Click()
Shell "cmd /chelp\index.htm", vbHide
End Sub
段。
- 哈夫曼树链式存储及简单哈夫曼编码VB实现
- 栈的链式存储结构及简单实现
- 集合的链式存储及操作实现
- 链式栈存储实现及操作
- 链式队列存储实现及操作
- 栈的链式存储结构及实现
- 栈的链式存储结构及实现
- 队列的链式存储结构及实现
- 队列的链式存储结构及实现
- 【线性表】顺序存储、链式存储的实现及操作
- 栈的顺序存储及链式存储的分别实现
- 栈---链式存储实现
- 队列链式存储实现
- 栈的链式存储结构及C实现
- JAVA实现队列 队列的链式存储结构及操作
- Java基础 - 栈的链式存储结构及实现
- Java基础 - 队列的链式存储结构及实现
- 栈的链式存储结构操作及实现
- 最基本的TCP客户端
- 单击dataGridView某一行时将dataGridView当前选择行的某列值赋值给某个文本框
- unresolved external symbol __endthreadex错误解决
- 【入门教程】Linux下静态库和共享库的制作方法
- 自定义标签的案例
- 哈夫曼树链式存储及简单哈夫曼编码VB实现
- VC知识百问
- 机器人方面的顶级会议与杂志有哪些
- Windows CE 简介
- corte-m3中的pc值的问题
- 关于“抽象类是否可继承实体类”的辨析。
- 动态调用动态库方法 | from web
- 三进制解决天平平衡问题
- 两个路由器桥接方法