一、实验目的
1、掌握二叉树的特点和性质;
2、掌握哈夫曼树的构造算法;
3、掌握哈夫曼树编码的构造算法。
二、实验内容
编写一个实验程序,随机给定一个字符串,统计其中ASCLL码为0-255的字符出现的次数,构造出对应的赫夫曼编码,用其替换产生加密码(其他字符保持不变),再由加密码解密产生原字符串,并且利用相关数据进行测试。
三、实验要求
1、实验报告要求用Java语言实现,2或3人一组。
2、完成“数据结构项目情境实验报告”。
3、完成项目程序代码的编写,并能正确运行
四、开发环境及人员分工
集成开发环境(IDE) | Eclipse JAVA |
项目成员 | 分工 |
五、实现过程详细说明
1.随机给定一个字符串
2.统计其中ASCLL码为0-255的字符出现的次数,
3.构造出对应的赫夫曼编码,
4.用其替换产生加密码(其他字符保持不变),再由加密码解密产生原字符串,并且利用相关数据进行测试。
六、实验总结
这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于游逆而解。上机实习一方面能使书本上的知识变活,起到深化理解和灵活掌握教学内容的目的;另一方面,上机实习是对学生软件设计的综合能力的训练,包括问题分析,总体结构设计,程序设计基本技能和技巧的训练。
七、代码实现(程序粘贴,运行结果截图)
package news;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import org.junit.Test;
public class wgyz {
private class TreeNode {
public TreeNode(Character ch, int val, int freq, TreeNode left, TreeNode right) {
this.ch = ch;
this.val = val;
this.freq = freq;
this.left = left;
this.right = right;
}
Character ch;
int val;
int freq;
TreeNode left;
TreeNode right;
} @Test public void testEncode(){
String s = "wgyz-3143-zhzhx-3060";
System.out.println("编码前:"+s);
Object[] encodeRes = encode(s);
String encodeStr = (String)encodeRes[0];
Map<Character,String> encodeMap = (Map<Character, String>)encodeRes[1];
System.out.println("编码表:");
for(Map.Entry<Character,String> e:encodeMap.entrySet()){
System.out.println(e.getKey()+":"+e.getValue()); }
System.out.println("编码后:"+encodeStr);
String decodeStr = decode(encodeStr,encodeMap);
System.out.println("解码后:"+decodeStr); }
public Object[] encode(String s){
Object[]res= new Object[2];
Map<Character,String> encodeMap = new HashMap<Character, String>();
TreeNode tree = constructTree(s);
findPath(tree, encodeMap, new StringBuilder());
findPath(tree, encodeMap, new StringBuilder());
StringBuilder sb = new StringBuilder();
for(int i=0;i<s.length();i++){
String tmp = encodeMap.get(s.charAt(i));
sb.append(tmp); }
res[0]=sb.toString();
res[1] = encodeMap;
return res; }
private TreeNode constructTree(String s) {
if (s == null || s.equals("")) {return null; }
//计算每个字母的词频,放到Map中
Map<Character, Integer> dataMap = new HashMap<Character, Integer>();
for (int i = 0; i < s.length(); i++) {
Character c = s.charAt(i);
if (dataMap.containsKey(c)) {
int count = dataMap.get(c);
dataMap.put(c, count + 1);
} else { dataMap.put(c, 1); } }
LinkedList<TreeNode> nodeList = new LinkedList<TreeNode>();
for (Map.Entry<Character, Integer> entry : dataMap.entrySet()) {
Character ch = entry.getKey();
int freq = entry.getValue();
int val = 0;
TreeNode tmp = new TreeNode(ch,val,freq,null,null);
nodeList.add(tmp); }
Collections.sort(nodeList, new Comparator<TreeNode>() {
public int compare(TreeNode t1, TreeNode t2) {
return t1.freq-t2.freq; } });
//size==1,代表字符串只包含一种类型的字母
if(nodeList.size()==1){
TreeNode t = nodeList.get(0);
return new TreeNode(null,0,nodeList.get(0).freq,t,null); }
TreeNode root = null;
while(nodeList.size()>0){
TreeNode t1 = nodeList.removeFirst();
TreeNode t2 = nodeList.removeFirst();
//左子树的val赋值为0,右子树的val赋值为1
t1.val = 0;
t2.val = 1;
if(nodeList.size()==0){
root = new TreeNode(null,0,t1.freq+t2.freq,t1,t2); }else {
//此时代表还有可以合并的节点
TreeNode tmp = new TreeNode(null,0,t1.freq+t2.freq,t1,t2);
//t1、t2合并后,需要将得到的新节点加入到原链表中,继续与其他节点合并,
//此时需要保证原链表的有序性,需要进行排序
if(tmp.freq>nodeList.getLast().freq){
nodeList.addLast(tmp); }else { for(int i=0;i<nodeList.size();i++){int tmpFreq = tmp.freq;if(tmpFreq<= nodeList.get(i).freq){ nodeList.add(i,tmp); break; } } } } } return root; }//对已经建立好的二叉树进行遍历,得到每个字符的编码
private void findPath(TreeNode root, Map<Character,String> res, StringBuilder path) {
if (root.left == null && root.right == null) {
path.append(root.val);
res.put(root.ch,path.substring(1));
path.deleteCharAt(path.length() - 1);
return;} path.append(root.val);
if (root.left != null) findPath(root.left, res, path);
if (root.right != null) findPath(root.right, res, path);
path.deleteCharAt(path.length() - 1); }
public String decode(String encodeStr,Map<Character,String> encodeMap){
StringBuilder decodeStr = new StringBuilder();
while(encodeStr.length()>0){
for(Map.Entry<Character,String> e: encodeMap.entrySet()){
String charEncodeStr = e.getValue(); if(encodeStr.startsWith(charEncodeStr)){
decodeStr.append(e.getKey());
encodeStr = encodeStr.substring(charEncodeStr.length());
break; } } }return decodeStr.toString();}}