Whether in our development projects, or in our daily life, will be more involved in file compression. When it comes to file compression, someone may want to ask how the file compression is implemented, what the principle of implementation is, and for developers, how to implement such a compressed function.
Next, let's look at the knowledge of file compression. How is file compression implemented? This we have to understand the data structure, because the file in the process of compression will be converted into data flow, then how to compress the data stream, the problem depends on the algorithm to achieve. So what is the algorithm for file compression? That's huffmantree.
When it comes to huffmantree, we need to talk about data structures and algorithms. In computers, data structures and algorithms can be said to be the soul of a program.
Data structure: is a collection of elements that have one or more specific relationships to each other. According to different viewpoints, we divide the data structure into logical structure and physical structure.
(1). Logical structure: Refers to the interrelationship between data elements in a data object. The logical structure consists of the collection structure (the data elements in the collection structure have no other relationship with each other except for the same set); linear structure (a one-to-one relationship between data elements in a linear structure); tree structure (there is a single-to-many hierarchical relationship between data elements in a tree structure) ; graphical structure (the data elements of a graphical structure are many-to-many relationships).
(2). Physical structure: Refers to the logical structure of data in the computer storage form. The physical structure contains: sequential storage structure (is the data elements stored in the address contiguous storage unit, the data between the logical relationship and the physical relationship is consistent); Chain storage structure (refers to the data elements stored in arbitrary storage units, the set of storage units can be continuous, or can be discontinuous)
The above describes the classification of data structure, of course, when speaking of Huffmantree, it is necessary to mention the "tree structure."
Tree: is a finite set of n (n greater than or equal to 0) nodes. Now introduce the three representations of the tree:
(1). Parental representation (in each node, an indicator is attached to indicate the position of the parent node to the linked list);
(2). Child notation (each node has multiple pointer fields, each of which points to the root node of a tree, which we call the linked list notation);
(3). Child Brother Representation (any tree, its first child if existence is the only one, its friends if the existence is also unique, so we set two pointers, pointing to the node's first child and the sibling of this node, respectively).
The tree mentioned above, now introduce the binary tree.
Binary tree: is a finite set of n (n greater than or equal to 0) nodes, which is either empty or has a root node and two disjoint tree of the right subtree of the Saozi, called the root node, consisting of two forks.
Here are some special two-fork trees:
(1). Oblique tree: All nodes are only in the left subtree of the two fork tree called the Left oblique tree. All nodes are only right subtree called right oblique tree.
(2). Full two fork tree: In a binary tree, if all branch nodes have Saozi right subtree, and all the leaves are on the same layer, such a two-fork tree becomes full two fork tree.
(3). Complete binary tree: A two-fork tree with n nodes is numbered sequentially, if the node numbered I (1 greater than or equal to I less than or equal to n) and the node numbered I in the same depth of the full two fork tree are exactly the same in the binary tree, then this binary tree becomes a complete binary tree.
I first introduced the definition and classification of data structure, followed by the introduction of tree, Binary tree. Finally, let us come to the specific understanding of huffmantree.
A branch from one node in the tree to another node makes up a path between two nodes, and the number of branches on the path is called the path length. The path length of a tree is the sum of the length of the path from the root to each node. The weighted path length of a node is the product of the length of the path from the node to the heel and the right on the node. The weighted path length of the tree is the sum of the weighted path lengths of all the leaf nodes in the tree.
Huffmantree: With the weighted path length WPL the smallest two-tree called the Huffman Tree. (also known as: Optimal binary tree)
Huffman encoding: Specifies that the left branch of the Huffman tree represents 0, and the branch represents 1, then the sequence of 0 and 1 of the path branching from the root node to the leaf node is encoded for that node's corresponding character.
The above introduces the related concept of huffmantree knowledge, now need to use this data structure in code implementation, followed by a section of the implementation of C # code Huffmantree.
1. base class for bit streams:
/// <summary> ///the base class for the bit stream. /// </summary> /// <remarks> ///a byte stream is converted between the rule implementations of a bit flow. /// </remarks> Public Abstract classBitstream {/// <summary> ///get the maximum number of digits quickly on the data stream/// </summary> Public Abstract intMaxreadahead {Get;Set; } /// <summary> ///reads a bit from the stream. /// </summary> /// <param name= "Count" >the number of bits read. </param> /// <returns>bit is UInt32. </returns> Public Abstract UINTRead (intcount); /// <summary> ///querying data on a stream/// </summary> /// <param name= "Count" >the number of bits of the query. </param> /// <returns>bit is UInt32. </returns> /// <remarks>This method does not consume bits (that is, move the file pointer). </remarks> Public Abstract UINTPeek (intcount); /// <summary> ///consumes bits from the stream without returning them. /// </summary> /// <param name= "Count" >the number of bits consumed. </param> Public Abstract voidConsume (intcount); }
2. Huffman Tree Implementation:
/// <summary> ///The realization of Huffman tree. /// </summary> /// <remarks> ///creates a lookup table that takes any bit sequence (the length of the maximum tree depth) to indicate the output symbol. In the WIM file, in practice, there is not a piece more than 32768 bytes///length, so we often produce a larger lookup table than its data encoding. This makes the exception fast symbol find O (1), but less efficient overall. /// </remarks> Public Sealed classHuffmantree {//the maximum bits per symbol Private ReadOnly int_numbits; //Maximum Symbol Private ReadOnly int_numsymbols; Private ReadOnly UINT[] _buffer; PublicHuffmantree (UINT[] lengths) {Lengths=lengths; _numsymbols=lengths. Length; UINTMaxLength =0; for(vari =0; i < lengths.length; ++i) {if(Lengths[i] >maxLength) {MaxLength=Lengths[i]; }} _numbits= (int) MaxLength; _buffer=New UINT[1<<_numbits]; Build (); } Public UINT[] Lengths {Get;Set; } Public UINTNextsymbol (bitstream bitstream) {varSymbol =_buffer[bitstream.peek (_numbits)]; //We may be reading, resetting the position of the bitstreamBitstream.consume ((int) Lengths[symbol]); returnsymbol; } Private voidBuild () {varPosition =0; //for each bit length ... for(vari =1; I <= _numbits; ++i) {//Check each symbol for(UINTSymbol =0; Symbol < _numsymbols; ++symbol) { if(Lengths[symbol]! = i)Continue; varNumtofill =1<< (_numbits-i); for(varn =0; n < Numtofill; ++N) {_buffer[position+ N] =symbol; } position+=Numtofill; } } for(vari = position; I < _buffer. Length; ++i) {_buffer[i]=UINT. MaxValue; } } }
The Heffman code has some knowledge about the two-fork tree with weighted path, which is used to understand the principle of compression. The understanding of the data structure requires us to spend a lot of time, and we need to do a careful classification of these data structures.
Analysis of Huffmantree and algorithm implementation in C #