`
zhuozhuobeauty
  • 浏览: 18158 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

我是爱种树的好菇凉之哈夫曼树

    博客分类:
  • java
 
阅读更多

1、哈夫曼树及其构建

哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+ Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。

他的构建方式为:

首先先将离散节点从小到大升序排序

第二从离散节点中在挑选排序前两个节点当做一个新的父节点的两个子节点

第三从离散的节点中去除刚刚使用的两个节点

第四重复第二和第三步骤,直到所有离散节点剔除完毕。哈夫曼树就构建完成

 2、哈夫曼树的编码方式

遵循左子树编号为0,右子树编号为1的方式

3、实现哈弗曼树的构建,遍历,编码

 

package Huffman;



public class Node<T> {

	// 数据
	T data;
	// 权重
	int power;
	//编码,初始化为空
	String coding = "";
	Node<T> leftNode;

	Node<T> rightNode;
	

	public Node(T data,int power) {
		this.power = power;
		this.data = data;
	}
	public String toString() {
		// TODO Auto-generated method stub
		return "[data:" + data + "   power:" + power + "]";
	}

	@SuppressWarnings("unchecked")
	public boolean compareTo(Node node) {

		if (this.power < node.power) {
			return true;
		}

		return false;
	}
	public Node<T> getLeftNode() {
		return leftNode;
	}
	public void setLeftNode(Node<T> leftNode) {
		this.leftNode = leftNode;
	}
	public Node<T> getRightNode() {
		return rightNode;
	}
	public void setRightNode(Node<T> rightNode) {
		this.rightNode = rightNode;
	}
	public String getCoding() {
		return coding;
	}
	public void setCoding(String coding) {
		this.coding = coding;
	}
}

 创建哈夫曼树

/**
	 * 创建哈夫曼树
	 * 
	 * @param list
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static  Node createHuffmanTree(List<Node> list) {

		while (list.size() > 1) {
			sort(list);
			//实例化左节点,此时list中存储的已经是排好序的数据
			Node left = list.get(list.size() - 1);
            //实例化右节点
			Node right = list.get(list.size() - 2);
            //构造父节点,节点中存储的字符为空,权值为两子树权值之和
			Node parent = new Node(null,left.power + right.power);
            //将两子节点与parent连接
			parent.leftNode = left;
			parent.rightNode = right;
            //把最小的两个删除
			list.remove(list.size() - 1);
			list.remove(list.size() - 1);
            //将parent添加到队列中
			list.add(parent);
		}
		//返回第一个节点
		return list.get(0);
	}

 **关于list.remove(int i);

是 java.util.List<E>中的一种方法,其中List<E>接口是有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

它允许重复的元素存在。

它中间一些常用的方法
 

 boolean add(E e)
          向列表的尾部添加指定的元素(可选操作)。

 

 void clear()
          从列表中移除所有元素(可选操作)。
 boolean isEmpty()
          如果列表不包含元素,则返回 true

 

 E remove(int index)
          移除列表中指定位置的元素(可选操作)。

 

这些在API文档中均可以查找到

接下来是遍历输出

//中序遍历输出,两个字母合成的父节点的data为0
	public static void inOrder(Node root){  
        if(root==null){return;}  
        inOrder(root.getLeftNode());  
        System.out.println("data is:  "+root.data+"    power is:  "+root.power);  
        inOrder(root.getRightNode());  
    }  

 编码

//对list中的元素进行编码
	public  static< T> void generateHuffmanCode(Node< T> root){
		if (root==null) return;
		
	       if(root.getLeftNode()!=null) 
	           root.getLeftNode().setCoding(root.getCoding()+"0");
	       if(root.getRightNode()!=null) 
	          root.getRightNode().setCoding(root.getCoding()+"1");
	       if(root.data != null)       
	       System.out.println(root.data+"的编码是"+root.coding);
	       generateHuffmanCode(root.getLeftNode());
		generateHuffmanCode(root.getRightNode());
	    }

//冒泡排序,将哈夫曼树中的节点按权值大小排序
	public static  void sort(List<Node> list) {  
  
        for (int i = 0; i < list.size() - 1; i++) {  
  
            for (int j = i + 1; j < list.size(); j++) {  
  
                if (list.get(i).compareTo(list.get(j))) {
                    // 交换数组中的元素位置
                    Node node = list.get(i);  
  
                    list.set(i, list.get(j));
                    list.set(j, node);
                }
            }  
        }  
  
	}

 梅梅发现我没有把sort()方法贴过来。。。现在来补上~~~

主函数,注意要定义一个全局的变量private static int[] array = new int[256];

还要注意,非静态的变量不能用于静态的方法,或者主函数中!!会报错

public  static void main(String[] args) {
		List<Node> list = new ArrayList<Node>();
		String st = new String();
		// 实例化一个接受命令行输入信息的对象
		java.util.Scanner sc = new java.util.Scanner(System.in);
		System.out.println("请输入要统计的字符串:");
		// 获取输入的一行字符串
		String temp = sc.nextLine();

		// 循环遍历字符串
		for (int i = 0; i < temp.length(); i++) {
			// 获取指定索引位置的字符
			char c = temp.charAt(i);
			// 将字符转换为对应的ascii
			int ascii = c;
			// 将对应的ascii位置的数组元素加1
			array[ascii]++;
		}

		// 输出
		for (int i = 0; i < array.length; i++) {
			// 如果统计个数部位0则输出
			if (array[i] != 0) {
				char c = (char) i;
				Node nod = new Node(c,array[i]);
				list.add(nod);
				System.out.println("字符" + c + "出现的次数是" + array[i]);
			}
		}
		
        //根据list创建哈夫曼树,并且将createHuffmanTree
		//返回的第一个值作为根节点
		Node root = createHuffmanTree(list);
		generateHuffmanCode(root);
		inOrder(root);
	}

 下面是运行结果~~

 

 

 编码的实现


 

遍历输出

 



 
 种树收官~~~

  • 大小: 7.7 KB
  • 大小: 3.2 KB
  • 大小: 7.1 KB
分享到:
评论

相关推荐

    哈夫曼树 课程设计 实验报告

    哈夫曼树,也称为最优二叉树,是一种特殊的二叉树,它的特点是所有叶子节点到根节点的路径上,权值之和(路径长度)最小。这里的权值通常代表字符出现的频率或概率。在数据压缩中,哈夫曼编码是基于哈夫曼树的一种...

    数据结构 哈夫曼树

    数据结构中的哈夫曼树(Huffman Tree),也称为最优二叉树,是一种特殊的二叉树,主要用于数据的编码压缩。哈夫曼树是通过哈夫曼编码(Huffman Coding)来实现的,这是一种用于无损数据压缩的算法。在这个算法中,...

    哈夫曼树压缩算法实现

    通常通过哈夫曼构建算法实现,该算法将频率最低的两个节点合并为一个新的节点,新节点的频率是其子节点频率之和,重复此过程直到只剩下一个节点,即为哈夫曼树的根节点。 3. **生成哈夫曼编码**:从哈夫曼树中生成...

    哈夫曼树与哈夫曼编码

    哈夫曼树与哈夫曼编码是数据结构和算法领域中的一个重要概念,广泛应用于数据压缩、文本编码以及优先队列等场景。哈夫曼编码是一种特殊的前缀编码方法,能够为字符提供一种高效的二进制表示,使得频繁出现的字符具有...

    数据结构哈夫曼树PPT学习教案.pptx

    "数据结构哈夫曼树PPT学习教案.pptx" 哈夫曼树是一种特殊的二叉树,它的带权路径长度最小。哈夫曼树的构造是数据结构中的一种重要算法,广泛应用于数据压缩、编码和决策树等领域。 一、基本术语 在哈夫曼树中,...

    数据结构课程设计_哈夫曼树

    数据结构课程设计的目标是让学生能够灵活运用所学的数据结构知识,特别是哈夫曼树这一重要概念,来解决实际问题。哈夫曼树是一种特殊的二叉树,常用于数据压缩和编码,通过构建最小带权路径长度的二叉树,使得频率高...

    哈夫曼树及哈夫曼编码数据结构实验报告

    2. 编码:利用构建好的哈夫曼树,从叶子节点到根节点的路径表示该字符的哈夫曼编码。路径上的左分支代表0,右分支代表1。 3. 打印编码规则:输出每个字符及其对应的哈夫曼编码,形成字符与编码的映射表。 4. 编码...

    哈夫曼树的编译码器.docx

    通过实现哈夫曼树的编译码器,我们可以更好地理解哈夫曼树的建立、哈夫曼编码和哈夫曼解码的原理和实现方法。此外,我们还可以通过实验来分析哈夫曼树的优缺点和应用场景。 五、所采用的存储结构的优缺点及采用理由...

    建哈夫曼树 实现哈夫曼编码

    哈夫曼树(Huffman Tree)和哈夫曼编码(Huffman Coding)是数据压缩领域中的基础算法,它们主要用于无损数据压缩。哈夫曼编码是一种可变长度的前缀编码,通过为每个字符分配一个唯一的二进制码,使得出现频率高的...

    哈夫曼树的实现

    根据给定的信息,本文将详细解析哈夫曼树的实现及其相关知识点,包括类的定义、构造过程以及编码方法。 ### 哈夫曼树的基本概念 ...通过对这些核心函数的理解,我们可以更好地掌握哈夫曼树的基本原理及其应用。

    哈夫曼树c语言编写

    哈夫曼树构造 输出

    java 哈夫曼树及哈夫曼树的应用

    哈夫曼树,又称最优二叉树或最小带权路径长度树,是数据结构中一种特殊的二叉树,主要用于数据的编码压缩。它的构建基于贪心算法,通过将具有最少权值的节点合并来逐步构造出一棵使得带权路径长度最短的树。在Java中...

    哈夫曼树程序设计问题

    哈夫曼树是一种特殊的二叉树,它的每个节点的权重都是其左右子树的权重之和。哈夫曼树的主要应用是用于数据压缩,特别是文本压缩。哈夫曼树的构建过程是从叶子节点开始,逐渐构建树形结构,直到根节点。 哈夫曼树的...

    哈夫曼树的基本操作

    在构造哈夫曼树的过程中,每次迭代都会找到权重最小的两个节点进行合并,形成一个新的节点,并将新节点的权重设置为这两个节点权重之和。 #### 函数 `Initialization()` 初始化哈夫曼树的过程包括读取输入的字符和...

    c语言 哈夫曼树

    哈夫曼树,又称最优二叉树或最小带权路径长度树,是数据结构领域中一种特殊的二叉树。在C语言中实现哈夫曼树主要用于数据的编码和解码,特别是压缩数据时,能够有效地提高编码效率。下面将详细介绍哈夫曼树的概念、...

    数据结构实验二哈夫曼树及哈夫曼编码译码的实现

    哈夫曼树是一种特殊的二叉树,它的每个节点的权重是其所有子节点的权重之和。哈夫曼树的应用非常广泛,如数据压缩、编码、译码等。 哈夫曼树的存储结构 哈夫曼树的存储结构可以使用静态三叉链表来实现。每个节点...

    哈夫曼树及其应用

    2. 接着,每次从 F 集合中选择权值最小的两棵树,将它们合并为一棵新树,新树的权值为两棵树权值之和,新树的根节点作为这两个节点的父节点,原树的根节点成为新树的左右子节点。新树放入集合 F 中。 3. 重复步骤2,...

    C语言实现哈夫曼树的构建

    哈夫曼编码是一种广泛应用于数据压缩领域的技术,由David A....通过学习和掌握哈夫曼树的构建与C语言实现,我们可以更好地理解数据压缩的原理,并应用于实际的编程实践中,以解决各类数据处理问题。

Global site tag (gtag.js) - Google Analytics