Java data structure and algorithm

Posted by cbn_noodles on Mon, 27 Dec 2021 09:20:47 +0100

catalogue

Huffman coding

Principle analysis

Basic introduction

Best practices - data compression (create Huffman tree)

code implementation

Operation effect

Generate Huffman coding table

Partial code

Complete code

Operation effect

Huffman coding

Transmitted string

1)I like like like java do you like a java

2)d:1 y:1 u:1 j:2 v:2 o:2 l:4 k:4 e:4 i:5 a:5: 9 / / number of characters

3) A Huffman tree is constructed according to the number of occurrences of the above characters, and the number of occurrences is used as the weight

Steps to form Huffman tree:

1) Sort from small to large. Each data is a node, and each node can be regarded as the simplest binary tree.

2) Take out the two binary trees with the smallest weight of the root node.

3) Form a new binary tree. The weight of the root node of the new binary tree is the sum of the weight of the root node of the previous two binary trees

4) The new binary tree is sorted again according to the weight of the root node, and the steps of 1-2-3-4 are repeated until all the data in the sequence are processed to obtain a Huffman tree.

4. According to the Huffman tree, specify the code (prefix code) for each character. The path to the left is 0 and the path to the right is 1,

Code: o: 1000 u:10010 d:100110 y:100111 i:101

a:110 k:1110 e:1111 j:0000 v:0001

l:001   :01

5. According to the Huffman code above, the corresponding code of our 'I like like like java do you like a java' string is (note the lossless compression we use here)

Principle analysis

Note that the Huffman tree may be different according to different sorting methods, so the corresponding Huffman codes are not exactly the same, but the WPL is the same and the length of the last generated Huffman code is the same. For example, if we make the new binary tree generated every time always rank last in the binary tree with the same weight, The generated binary tree is:

Basic introduction

1) Huffman coding is also translated as Huffman coding, also known as Huffman coding. It is a coding method and belongs to a program algorithm

2) Huffman coding is one of the classical applications of Huffman tree in telecommunications

3) Huffman coding is widely used in data file compression, and its compression rate is usually between 20% ~ 90%

4) Huffman code is a kind of variable word length coding. Huffman proposed a coding method in 1952, which is called optimal coding.


Best practices - data compression (create Huffman tree)

A paragraph of text will be given, such as "I like like like java do you like a java", and the data will be compressed according to the Huffman tree mentioned earlier.

Step 1: according to the principle of Huffman encoding compressed data, you need to create a Huffman tree corresponding to "I like like like java do you like a java"

Idea:

(1)Node {data ", weight, left and right}

(2) Get the byte [] array corresponding to "I like like like java do you like a java"

(3) Write a method to put the Node to be built into the Huffman tree into the List in the form of [] Node[data=97,weight=5],

Node[]date=32,weight=9]......, Embodiment x:1 y:1 u:1 j:2 v:2 o:2 l:4 k:4 e:4 i:5 a:5

(4) You can create the corresponding Huffman tree through List

code implementation

package huffmancode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HuffmanCode {

	public static void main(String[] args) {
		String content="I like like like java do you like a java";
		byte[] contentBytes=content.getBytes();
		System.out.println(contentBytes.length);//40
		
		List<Node> nodes=getNodes(contentBytes);
		System.out.println("nodes"+nodes);
		
		//Test one and create a binary tree
		System.out.println("huffman tree ");
		Node huffmanTreeRoot=createHuffmanTree(nodes);
		System.out.println("Preorder traversal");
		huffmanTreeRoot.preOrder();
	}
	
	//Preorder traversal method
	private static void preOrder(Node root) {
		if(root!=null) {
			root.preOrder();
		}else {
			System.out.println("Huffman tree is empty");
		}
	}
	private static List<Node>getNodes(byte[] bytes){
		//Create an ArrayList
		ArrayList<Node> nodes=new ArrayList<Node>();
		
		//Traverse bytes and count the number of occurrences of each byte - > map [key, value]
		Map<Byte, Integer> counts=new HashMap<>();
		for (byte b:bytes) {
			Integer count=counts.get(b);
			if (count==null) {//The Map does not have this character data, for the first time
				counts.put(b,1);
			}else {
				counts.put(b,count+1);
			}
		}
		//Convert each key value pair into a Node object and add it to the nodes collection
		//Traversal map
		for (Map.Entry<Byte, Integer>entry:counts.entrySet()) {
			nodes.add(new Node(entry.getKey(),entry.getValue()));
		}
		return nodes;
	}
	//You can create the corresponding Huffman tree through List
	private static Node createHuffmanTree(List<Node>nodes) {
		while (nodes.size()>1) {
			//Sort, from small to large
			Collections.sort(nodes);
			//Take out the first smallest binary tree
			Node leftNode=nodes.get(0);
			//Take out the second smallest binary tree
			Node rightNode=nodes.get(1);
			//Create a new binary tree. Its root node has no data but only weights
			Node parent=new Node(null,leftNode.weight+rightNode.weight);
			parent.left=leftNode;
			parent.right=rightNode;
			
			//Delete the two binary trees that have been processed from nodes
			nodes.remove(leftNode);
			nodes.remove(rightNode);
			//Add the new binary tree to nodes
			nodes.add(parent);
		}
		//The last node of nodes is the root node of Huffman tree
		return nodes.get(0);
	}
}
//Create a Node to display the data and weights
class Node implements Comparable<Node>{
	Byte data;//Store the data (character) itself, such as' a '= > 97' '= > 32
	int weight;//Weight, indicating the number of times characters appear
	Node left;
	Node right;
	public Node(Byte data,int weight) {
		this.data=data;
		this.weight=weight;
	}
	@Override
	public int compareTo(Node o) {
		//Sort from small to large
		return this.weight-o.weight;
	}
	public String toString() {
		return "Node[data="+data+"weight="+weight+"]";
	}
	//Preorder traversal
	public void preOrder() {
		System.out.println(this);
		if(this.left!=null) {
			this.left.preOrder();
		}
		if(this.right!=null) {
			this.right.preOrder();
		}
	}
}

Operation effect

Generate Huffman coding table

Partial code

	//Generate Huffman coding corresponding to Huffman tree
	//Idea:
	//1. Store Huffman code in map < byte, string >
	//32 - > 01 97 - > 100 - > 11000, etc. [form]
	static Map<Byte,String>huffmanCodes=new HashMap<Byte, String>();
	//2. In generating Huffman coded representation, you need to splice paths and define a path where StringBuilder stores a leaf node
	static StringBuilder stringBuilder=new StringBuilder();
	
	//For calling convenience, we overload getCodes
	private static Map<Byte,String>getCodes(Node root){
		if (root==null) {
			return null;
		}
		//Handle the left subtree of root
		getCodes(root.left,"0",stringBuilder);
		//Handle the right subtree of root
		getCodes(root.right,"1",stringBuilder);
		return huffmanCodes;
	}
		//Test whether the corresponding huff code is generated
		Map<Byte, String> huffmanCodes=getCodes(huffmanTreeRoot);
		System.out.println("Generated Huffman coding table"+huffmanCodes);

Complete code

package huffmancode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HuffmanCode {

	public static void main(String[] args) {
		String content="I like like like java do you like a java";
		byte[] contentBytes=content.getBytes();
		System.out.println(contentBytes.length);//40
		
		List<Node> nodes=getNodes(contentBytes);
		System.out.println("nodes"+nodes);
		
		//Test one and create a binary tree
		System.out.println("huffman tree ");
		Node huffmanTreeRoot=createHuffmanTree(nodes);
		System.out.println("Preorder traversal");
		huffmanTreeRoot.preOrder();
		
		//Test whether the corresponding huff code is generated
		Map<Byte, String> huffmanCodes=getCodes(huffmanTreeRoot);
		System.out.println("Generated Huffman coding table"+huffmanCodes);
	}
	//Generate Huffman coding corresponding to Huffman tree
	//Idea:
	//1. Store Huffman code in map < byte, string >
	//32 - > 01 97 - > 100 - > 11000, etc. [form]
	static Map<Byte,String>huffmanCodes=new HashMap<Byte, String>();
	//2. In generating Huffman coded representation, you need to splice paths and define a path where StringBuilder stores a leaf node
	static StringBuilder stringBuilder=new StringBuilder();
	
	//For calling convenience, we overload getCodes
	private static Map<Byte,String>getCodes(Node root){
		if (root==null) {
			return null;
		}
		//Handle the left subtree of root
		getCodes(root.left,"0",stringBuilder);
		//Handle the right subtree of root
		getCodes(root.right,"1",stringBuilder);
		return huffmanCodes;
	}
	/*
	 * Function: get the Huffman codes of all nodes of the incoming node node and put them into the Huffman codes collection
	 * node Incoming node
	 * code Path: the left child node is 0 and the right child node is 1
	 * stringBuilder  For splicing paths
	 * */
	private static void getCodes(Node node,String code,StringBuilder stringBuilder) {
		StringBuilder stringBuilder2=new StringBuilder(stringBuilder);
		//Add code to stringBuilder2
		stringBuilder2.append(code);
		if (node!=null) {//Do not process if node==null
			//Judge whether the current node is a leaf node or a non leaf node
			if (node.data==null) {//Non leaf node
				//Recursive processing
				//Recursive right
				getCodes(node.left,"0", stringBuilder2);
				//Recursive right
				getCodes(node.right, "1", stringBuilder2);
				
			}else {//Description is a leaf node
				//It means finding the last node of a leaf
				huffmanCodes.put(node.data,stringBuilder2.toString());
			}
			
		}
	}
	//Preorder traversal method
	private static void preOrder(Node root) {
		if(root!=null) {
			root.preOrder();
		}else {
			System.out.println("Huffman tree is empty");
		}
	}
	private static List<Node>getNodes(byte[] bytes){
		//Create an ArrayList
		ArrayList<Node> nodes=new ArrayList<Node>();
		
		//Traverse bytes and count the number of occurrences of each byte - > map [key, value]
		Map<Byte, Integer> counts=new HashMap<>();
		for (byte b:bytes) {
			Integer count=counts.get(b);
			if (count==null) {//The Map does not have this character data, for the first time
				counts.put(b,1);
			}else {
				counts.put(b,count+1);
			}
		}
		//Convert each key value pair into a Node object and add it to the nodes collection
		//Traversal map
		for (Map.Entry<Byte, Integer>entry:counts.entrySet()) {
			nodes.add(new Node(entry.getKey(),entry.getValue()));
		}
		return nodes;
	}
	//You can create the corresponding Huffman tree through List
	private static Node createHuffmanTree(List<Node>nodes) {
		while (nodes.size()>1) {
			//Sort, from small to large
			Collections.sort(nodes);
			//Take out the first smallest binary tree
			Node leftNode=nodes.get(0);
			//Take out the second smallest binary tree
			Node rightNode=nodes.get(1);
			//Create a new binary tree. Its root node has no data but only weights
			Node parent=new Node(null,leftNode.weight+rightNode.weight);
			parent.left=leftNode;
			parent.right=rightNode;
			
			//Delete the two binary trees that have been processed from nodes
			nodes.remove(leftNode);
			nodes.remove(rightNode);
			//Add the new binary tree to nodes
			nodes.add(parent);
		}
		//The last node of nodes is the root node of Huffman tree
		return nodes.get(0);
	}
}
//Create a Node to display the data and weights
class Node implements Comparable<Node>{
	Byte data;//Store the data (character) itself, such as' a '= > 97' '= > 32
	int weight;//Weight, indicating the number of times characters appear
	Node left;
	Node right;
	public Node(Byte data,int weight) {
		this.data=data;
		this.weight=weight;
	}
	@Override
	public int compareTo(Node o) {
		//Sort from small to large
		return this.weight-o.weight;
	}
	public String toString() {
		return "Node[data="+data+"weight="+weight+"]";
	}
	//Preorder traversal
	public void preOrder() {
		System.out.println(this);
		if(this.left!=null) {
			this.left.preOrder();
		}
		if(this.right!=null) {
			this.right.preOrder();
		}
	}
}

Operation effect

 

Topics: Java Algorithm data structure