通过java来实现文本压缩需要以下几个步骤:
1.创建二叉树
2.根据给定的字符串内容(读取文本文件),统计没个字符出现的频率,创建对应的节点
3.根据节点的权值创建哈夫曼树,统计字符编码
4.把字符数据替换成对应的编码
5.把字符编码没每8个一组转成byte写入文件:最后一个字节不足要补全
6.把码表写入文件
7.添加图形化界面
这一节先来讲关于二叉树的遍历
一.创建二叉树
二叉树是数据结构中重要的一个部分,二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
二叉树的特点:
1.每个结点最多有两棵子树,即二叉树不存在度大于2的结点。
2.二叉树的子树有左右之分,其子树的次序不能颠倒。
首先我们来创建节点类
class TreeNode{
public String code = ""; //统计节点的编码
public int data; //字符出现次数
public String c; //当前的字符内容
public TreeNode left;
public TreeNode right;
public TreeNode(int data){
this.data = data;
}
public TreeNode(int data,String c){
this.data=data;
this.c=c;
}
}
创建完节点类后要增加新的节点
public void addNode(TreeNode node){
if (root==null){
root=node;
}else {
//保存当前节点
TreeNode curr=root;
while(true){
//左子树
if (curr.date>node.date){
if (curr.left==null){
curr.left=node;
}
curr=curr.left;
}
//右子树
if (curr.date<= node.date){
if (curr.right==null){
curr.right=node;
}
curr=curr.right;
}
}
}
}
如果节点为空,那就创建新的节点,如果不为空,那就保存当前节点curr,如果node节点的数据小于curr的数据,就将node设为左子树,如果node节点的数据大于curr的数据,就将node设为右子树。
然后需要对二叉树从小到大进行排序
public void sort(List<TreeNode> listNode){
System.out.println("冒泡排序");
for (int i = 0; i < listNode.size()-1; i++) {
for (int j = 0; j < listNode.size()-1; j++) {
if (listNode.get(j).data > listNode.get(j + 1).data) {
TreeNode node=listNode.get(i);
listNode.set(i,listNode.get(j));
listNode.set(j,node);
}
}
}
}
使用冒泡排序的方法将二叉树的内容按顺序排列下来(当然也可以用更加便捷的方式排列)
如果需要让它进行前序、中序、后序排列,需要在创建一个排序方法
//中序遍历
public void order(TreeNode root){
if(root != null) {
//System.out.print(root.data+" ");//前序
order(root.left);
System.out.print(root.data+" ");//中序
order(root.right);
//System.out.print(root.data+" ");//后序
}
}
这样就可以让这个二叉树按照规定的顺序进行排列。调整输出语句的不同位置,就能改变它的排序方式。
最后通过主函数调用方法即可运行
public static void main(String[] args) {
int[] arr = {7,5,9,6,3,8,10,4};
Tree tree = new Tree();
for(int i=0;i<arr.length;i++){
TreeNode node = new TreeNode(arr[i]);
tree.addNode(node);
}
tree.order(tree.root);
}
这样这个二叉树就可以按照给定的顺序打印出来了
除了二叉树的三序遍历,我们还可以进行层的遍历
//层的遍历
public List<List<Integer>> levelOrder(TreeNode root){
List<List<Integer>> list = new LinkedList<>();
if(root == null){
return null;
}
TreeNode curr = root;
//队列:先进先出
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(curr);
while(queue.size() > 0){
//创建List,保存每一层的节点
List<Integer> level = new LinkedList<>();
int size = queue.size();
for(int i=0;i<size;i++){
TreeNode node = queue.poll();
level.add(node.data);
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
//把每一层的数据添加到List中
list.add(level);
}
return list;
}
offer()方法是将curr节点添加到queue队列当中,
poll()方法是从队列中删除第一个元素,但是 poll() 方法在用空集合调用时不是抛出异常,只是返回 null
当队列中存入数据成功后,创建List,保存每一层的节点,进行遍历所有节点,每添加一次,就将保存 的节点添加到list当中
在主函数中调用levelOrder()方法实现层的遍历
public static void main(String[] args) {
int[] arr = {7,5,9,6,3,8,10,4};
Tree tree = new Tree();
for(int i=0;i<arr.length;i++){
TreeNode node = new TreeNode(arr[i]);
tree.addNode(node);
}
List<List<Integer>> list = tree.levelOrder(tree.root);
for(int i=0;i<list.size();i++){
List<Integer> li = list.get(i);
for(int j=0;j<li.size();j++){
System.out.print(li.get(j)+" ");
}
System.out.println();
}
}
}
这样二叉树层的遍历也就完成了。