1.树的构建

  1. package huffman;
  2.  
  3. public abstract class BinaryTreeBasis {
  4. protected TreeNode root;
  5.  
  6. public BinaryTreeBasis() {
  7. root = null;
  8. } // end default constructor
  9.  
  10. public BinaryTreeBasis(Object rootItem) {
  11. root = new TreeNode(rootItem, null, null);
  12. } // end constructor
  13.  
  14. public boolean isEmpty() {
  15. // Returns true if the tree is empty, else returns false.
  16. return root == null;
  17. } // end isEmpty
  18.  
  19. public void makeEmpty() {
  20. // Removes all nodes from the tree.
  21. root = null;
  22. } // end makeEmpty
  23.  
  24. public Object getRootItem() throws TreeException {
  25. // Returns the item in the trees root.
  26. if (root == null) {
  27. throw new TreeException("TreeException: Empty tree");
  28. }
  29. else {
  30. return root.getItem();
  31. } // end if
  32. } // end getRootItem
  33.  
  34. public TreeNode getRoot() throws TreeException {
  35. // additional method to return the root as TreeNode.
  36. return root;
  37. } // end getRoot
  38.  
  39. } // end BinaryTreeBasis
  1. package huffman;
  2.  
  3. public class BinaryTree extends BinaryTreeBasis {
  4. public BinaryTree() {
  5. } // end default constructor
  6.  
  7. public BinaryTree(Object rootItem) {
  8. super(rootItem);
  9. } // end constructor
  10.  
  11. public BinaryTree(Object rootItem,
  12. BinaryTree leftTree,
  13. BinaryTree rightTree) {
  14. root = new TreeNode(rootItem, null, null);
  15. attachLeftSubtree(leftTree);
  16. attachRightSubtree(rightTree);
  17. } // end constructor
  18.  
  19. public void setRootItem(Object newItem) {
  20. if (root != null) {
  21. root.setItem(newItem);
  22. }
  23. else {
  24. root = new TreeNode(newItem, null, null);
  25. } // end if
  26. } // end setRootItem
  27.  
  28. public void attachLeft(Object newItem) {
  29. if (!isEmpty() && root.getLeft() == null) {
  30. // assertion: nonempty tree; no left child
  31. root.setLeft(new TreeNode(newItem, null, null));
  32. } // end if
  33. } // end attachLeft
  34.  
  35. public void attachRight(Object newItem) {
  36. if (!isEmpty() && root.getRight() == null) {
  37. // assertion: nonempty tree; no right child
  38. root.setRight(new TreeNode(newItem, null, null));
  39. } // end if
  40. } // end attachRight
  41.  
  42. public void attachLeftSubtree(BinaryTree leftTree)
  43. throws TreeException {
  44. if (isEmpty()) {
  45. throw new TreeException("TreeException: Empty tree");
  46. }
  47. else if (root.getLeft() != null) {
  48. // a left subtree already exists; it should have been
  49. // deleted first
  50. throw new TreeException("TreeException: " +
  51. "Cannot overwrite left subtree");
  52. }
  53. else {
  54. // assertion: nonempty tree; no left child
  55. root.setLeft(leftTree.root);
  56. // don't want to leave multiple entry points into
  57. // our tree
  58. leftTree.makeEmpty();
  59. } // end if
  60. } // end attachLeftSubtree
  61.  
  62. public void attachRightSubtree(BinaryTree rightTree)
  63. throws TreeException {
  64. if (isEmpty()) {
  65. throw new TreeException("TreeException: Empty tree");
  66. }
  67. else if (root.getRight() != null) {
  68. // a right subtree already exists; it should have been
  69. // deleted first
  70. throw new TreeException("TreeException: " +
  71. "Cannot overwrite right subtree");
  72. }
  73. else {
  74. // assertion: nonempty tree; no right child
  75. root.setRight(rightTree.root);
  76. // don't want to leave multiple entry points into
  77. // our tree
  78. rightTree.makeEmpty();
  79. } // end if
  80. } // end attachRightSubtree
  81.  
  82. protected BinaryTree(TreeNode rootNode) {
  83. root = rootNode;
  84. } // end protected constructor
  85.  
  86. public BinaryTree detachLeftSubtree()
  87. throws TreeException {
  88. if (isEmpty()) {
  89. throw new TreeException("TreeException: Empty tree");
  90. }
  91. else {
  92. // create a new binary tree that has root's left
  93. // node as its root
  94. BinaryTree leftTree;
  95. leftTree = new BinaryTree(root.getLeft());
  96. root.setLeft(null);
  97. return leftTree;
  98. } // end if
  99. } // end detachLeftSubtree
  100.  
  101. public BinaryTree detachRightSubtree()
  102. throws TreeException {
  103. if (isEmpty()) {
  104. throw new TreeException("TreeException: Empty tree");
  105. }
  106. else {
  107. BinaryTree rightTree;
  108. rightTree = new BinaryTree(root.getRight());
  109. root.setRight(null);
  110. return rightTree;
  111. } // end if
  112. } // end detachRightSubtree
  113.  
  114. } // end BinaryTree
  1. package huffman;
  2.  
  3. public class TreeNode {
  4. private Object item;
  5. private TreeNode leftChild;
  6. private TreeNode rightChild;
  7.  
  8. public TreeNode(Object newItem) {
  9. // Initializes tree node with item and no children.
  10. item = newItem;
  11. leftChild = null;
  12. rightChild = null;
  13. } // end constructor
  14.  
  15. public TreeNode(Object newItem,
  16. TreeNode left, TreeNode right) {
  17. // Initializes tree node with item and
  18. // the left and right children references.
  19. item = newItem;
  20. leftChild = left;
  21. rightChild = right;
  22. } // end constructor
  23.  
  24. public Object getItem() {
  25. // Returns the item field.
  26. return item;
  27. } // end getItem
  28.  
  29. public void setItem(Object newItem) {
  30. // Sets the item field to the new value newItem.
  31. item = newItem;
  32. } // end setItem
  33.  
  34. public TreeNode getLeft() {
  35. // Returns the reference to the left child.
  36. return leftChild;
  37. } // end getLeft
  38.  
  39. public void setLeft(TreeNode left) {
  40. // Sets the left child reference to left.
  41. leftChild = left;
  42. } // end setLeft
  43.  
  44. public TreeNode getRight() {
  45. // Returns the reference to the right child.
  46. return rightChild;
  47. } // end getRight
  48.  
  49. public void setRight(TreeNode right) {
  50. // Sets the right child reference to right.
  51. rightChild = right;
  52. } // end setRight
  53.  
  54. public String toString() {
  55. return "" + item;
  56. }
  57.  
  58. public boolean isLeaf() {
  59. return ((getLeft() == null) && (getRight() == null));
  60. }
  61.  
  62. } // end TreeNode

2.逐比特读写的方法

  1. package huffman;
  2.  
  3. import java.io.*;
  4. /**
  5. * This class is designed to read in bits from a file that is stored in the same format
  6. * as specified by the BitWriter
  7. * It is based on the iterator model, with similar names. It has different return types though.
  8. * @author Shane Paul
  9. * 7/10/2003
  10. * @
  11. */
  12. public class BitReader {
  13.  
  14. //The inputStream
  15. FileInputStream input;
  16. //Stores the next 3 bytes in the file, to check for EOF and deal with the last byte being potentially half full
  17. int current, plus1, plus2;
  18. //The number of bits that have been read so far in the current byte
  19. int count;
  20. //Have we reached the end of the file? If so, count must be ==0 also before we are finally done
  21. boolean finished;
  22.  
  23. /**
  24. * Construct a new BitReader from a file.
  25. */
  26. public BitReader(String file) throws Exception{
  27. this(new File(file));
  28. }
  29. public BitReader(File file) throws Exception{
  30. file.createNewFile();
  31. if(!file.canRead())
  32. throw new IOException("Oh My!! This file cannot be read from.....whatever shall I do? \nfile: "+file);
  33. input = new FileInputStream(file);
  34. //Read in the first two bytes. This assumes that the list contains at least one bit and therefore two bytes...
  35. plus1 = input.read();
  36. plus2 = input.read();
  37. }
  38. /**
  39. * Returns the next available bit in the file
  40. * @return the next boolean in the file
  41. */
  42. public boolean next()throws Exception{
  43. if(!hasNext())
  44. throw new NoBitsLeftToReturn();
  45. //Get the next bit
  46. if(count==0){ //We have no more bits in this particular byte
  47. //Get the next byte from the file
  48. current=plus1;
  49. plus1=plus2;
  50. plus2 = input.read(); //-1 is returned if we reach the EOF
  51. count=8;
  52. if(plus2<0){
  53. finished = true;
  54. count = 8-plus1; //only need to read the leftover bits
  55. }
  56. }
  57. count--;
  58. //get the leftmost bit and shift to right most
  59. int bit = current&0x80;
  60. bit = bit>>7;
  61. //shift current to left for one bit
  62. current = current<<1;
  63. if(bit==0)
  64. return false;
  65. return true;
  66. }
  67. /**
  68. * returns whether or not there are any bits left to read.
  69. */
  70. public boolean hasNext(){
  71. return !(finished && count==0);
  72. }
  73. /**
  74. * Thiis an informative exception that is thrown when you forget to check hasNext()
  75. * @author Shane Paul
  76. * 7/10/2003
  77. * @
  78. */
  79. public class NoBitsLeftToReturn extends Exception{}
  80. /**
  81. * Testing
  82. * @param args
  83. */
  84. public static void main(String[] args) throws Exception{
  85. BitReader br = new BitReader("writetest.txt");
  86. while(br.hasNext()){
  87. if(br.next())
  88. System.out.println("1");
  89. else
  90. System.out.println("0");
  91. }
  92. }
  93. }
  1. package huffman;
  2.  
  3. import java.io.*;
  4. /**
  5. * A simple class that allows a user to write a stream of bits to a file.
  6. * You should make sure you .flush() the BitWriter when you have finished writing.
  7. * Otherwise there will be bits and pieces left in the writer. :)
  8. * Once you HAVE flushed this writer, you can no longer write bits to it.
  9. * This is because it would make the algorithm a little more difficult and I am lazy. (it is
  10. * also not needed)
  11. *
  12. * For those that are interested:
  13. * The bots are stored in sections of bytes. The last byte in the file stores
  14. * the number of bits in the last byte that were filled in to make up a whole byte.
  15. *
  16. *
  17. * @author Shane Paul
  18. * 7/10/2003
  19. * @
  20. */
  21. public class BitWriter {
  22. //For writing to a file
  23. FileOutputStream output;
  24. //Stores 8 bits, before writing them to the FileWriter
  25. int buffer;
  26. //Count the number of bits
  27. int count;
  28. //Whether or not this Writer has been closed yet
  29. boolean closed = false;
  30. /**
  31. * Constuct a BitWriter using a String filename. The file will be overwritten.
  32. * @param filename The name of the file.
  33. * @exception IOException is thrown if the file does not exist or is not writable
  34. */
  35. public BitWriter(String filename) throws IOException{
  36. this(new File(filename)); //uses "this" to call the file constructor
  37. }
  38. /**
  39. * Construct a BitWriter using a File.
  40. * @param file The name of the file.
  41. * @exception IOException is thrown if the file does not exist or is not writable
  42. */
  43. public BitWriter(File file) throws IOException{
  44. //Test to see file is actually a file and can have data written to it
  45. file.createNewFile();
  46. if(!file.canWrite())
  47. throw new IOException("Oh My!! This file cannot be written to.....whatever shall I do? \nfile: "+file);
  48. output = new FileOutputStream(file);
  49. }
  50. /**
  51. * Writes a single bit to a file. The bit is defined by the boolean it receives
  52. * @param bit TRUE = 1, FALSE = 0
  53. * @exception IOException Throws an IOException if there were any problems writing to this file
  54. */
  55. public void writeBit(boolean bit)throws Exception{
  56. //Add in the specified bit by using the other method
  57. if(bit)
  58. writeBit(1);
  59. else
  60. writeBit(0);
  61. }
  62. /**
  63. * Flushes the buffer and closes this writer for good. The writer will accept no further bits after this method
  64. * has been called. You cannot "flush" this buffer because you cannot write single bits to the file.
  65. * Once you have "flushed" this buffer, it is then closed for good. (see class descrip. for why)
  66. */
  67. public void close()throws Exception{
  68. if(closed)
  69. throw new BitWriterClosedAlreadyException();
  70. output.flush();
  71. if(count!=0){
  72. int leftOverBits = 8-count;
  73. buffer = buffer<<leftOverBits;
  74. output.write(buffer);
  75. output.write(leftOverBits);
  76. }
  77. else
  78. output.write(0); //no extra bits
  79. output.close();
  80. closed = true;
  81. }
  82. /**
  83. * Another method that writes a single bit to a file.
  84. * This time it takes in an integer (or you could just pass a byte and it will be upcast)
  85. * only values 0 and 1 are acceptable.
  86. * <b>You need not do anything special with these exceptions, they are simply to inform you of the type
  87. * of error you have so you can debuig easier.</b>
  88. * If you try passing it another value, it will throw an exception. (to help debugging)
  89. * @param bit
  90. * @exception IOException Throws an IOException if there were any problems writing to this file
  91. * @exception InvalidBitException An exception I made up to indicate that you are not using this method correctly..
  92. */
  93. public void writeBit(int bit)throws Exception{
  94. //can't write to a closed bitwriter
  95. if(closed)
  96. throw new BitWriterClosedAlreadyException();
  97. if(bit <0 || bit>1)
  98. throw new InvalidBitException();
  99. count++;
  100. buffer=(buffer<<1);
  101. //Add in the specified bit
  102. if(bit==1)
  103. buffer|=1;
  104. //empty the buffer and reset the count
  105. if(count==8){
  106. output.write(buffer);
  107. count = 0;buffer = 0;
  108. }
  109. }
  110. /**
  111. * This is a simple Exception class that is thrown when you attempt to incorrectly call the writeBit method.
  112. * You do not need to do anything with this exception, they are just to make debugging easier
  113. * @author Shane Paul
  114. * 7/10/2003
  115. * @
  116. */
  117. public class InvalidBitException extends Exception{
  118.  
  119. }
  120. /**
  121. * This is an exception to inform you that you are trying to write to a bitwriter that has already been closed.
  122. * @author Shane Paul
  123. * 7/10/2003
  124. * @
  125. */
  126. public class BitWriterClosedAlreadyException extends Exception{
  127.  
  128. }
  129.  
  130. /**
  131. * Testing...and an example of how to use this class.
  132. * @param args
  133. */
  134. public static void main(String[] args) throws Exception{
  135. BitWriter bw = new BitWriter("writetest.txt");
  136. for(int j=0;j<12;j++){
  137. int num=(int)(Math.random()*30);
  138. if (num % 2 == 0) {
  139. System.out.println("0");
  140. bw.writeBit(0);
  141. }
  142. else {
  143. System.out.println("1");
  144. bw.writeBit(1);
  145. }
  146. }
  147. bw.close();
  148. }
  149. }

3.CharFreq,字母以及出现频率的数据结构

  1. package huffman;
  2.  
  3. // This class represents an object which stores a single character and an integer frequency
  4.  
  5. public class CharFreq implements Comparable {
  6.  
  7. private char c;
  8. private int freq;
  9.  
  10. public CharFreq(char c, int freq) {
  11. this.c = c;
  12. this.freq = freq;
  13. }
  14.  
  15. public char getChar() {
  16. return c;
  17. }
  18.  
  19. public int getFreq() {
  20. return freq;
  21. }
  22.  
  23. public int compareTo(Object o) {
  24. return freq - ((CharFreq)o).freq;
  25. }
  26.  
  27. public String toString() {
  28. return "(" + c + ":" + freq + ")";
  29. }
  30. }

4.TreeException

  1. package huffman;
  2.  
  3. public class TreeException extends RuntimeException {
  4. public TreeException(String s) {
  5. super(s);
  6. } // end constructor
  7. } // end TreeException

5.压缩与解压缩的测试代码

  1. package huffman;
  2.  
  3. import java.io.*;
  4. import java.lang.reflect.Array;
  5. import java.util.*;
  6.  
  7. public class TextZip {
  8.  
  9. private static final String ID = "201692388";
  10.  
  11. /**
  12. * This method generates the huffman tree for the text: "abracadabra!"
  13. *
  14. * @return the root of the huffman tree
  15. */
  16.  
  17. public static TreeNode abracadbraTree() {
  18. TreeNode n0 = new TreeNode(new CharFreq('!', 1));
  19. TreeNode n1 = new TreeNode(new CharFreq('c', 1));
  20. TreeNode n2 = new TreeNode(new CharFreq('\u0000', 2), n0, n1);
  21. TreeNode n3 = new TreeNode(new CharFreq('r', 2));
  22. TreeNode n4 = new TreeNode(new CharFreq('\u0000', 4), n3, n2);
  23. TreeNode n5 = new TreeNode(new CharFreq('d', 1));
  24. TreeNode n6 = new TreeNode(new CharFreq('b', 2));
  25. TreeNode n7 = new TreeNode(new CharFreq('\u0000', 3), n5, n6);
  26. TreeNode n8 = new TreeNode(new CharFreq('\u0000', 7), n7, n4);
  27. TreeNode n9 = new TreeNode(new CharFreq('a', 5));
  28. TreeNode n10 = new TreeNode(new CharFreq('\u0000', 12), n9, n8);
  29. return n10;
  30. }
  31.  
  32. /**
  33. * This method decompresses a huffman compressed text file. The compressed
  34. * file must be read one bit at a time using the supplied BitReader, and
  35. * then by traversing the supplied huffman tree, each sequence of compressed
  36. * bits should be converted to their corresponding characters. The
  37. * decompressed characters should be written to the FileWriter
  38. *
  39. * @param br the BitReader which reads one bit at a time from the
  40. * compressed file
  41. * huffman the huffman tree that was used for compression, and
  42. * hence should be used for decompression
  43. * fw a FileWriter for storing the decompressed text file
  44. */
  45. public static void decompress(BitReader br, TreeNode huffman, FileWriter fw) throws Exception {
  46.  
  47. // IMPLEMENT THIS METHOD
  48. TreeNode scaner = huffman;
  49. while(br.hasNext()){
  50.  
  51. for(;!scaner.isLeaf() && br.hasNext();){
  52. if(br.next())
  53. scaner = scaner.getRight();
  54. else
  55. scaner = scaner.getLeft();
  56. }
  57. CharFreq item = (CharFreq)(scaner.getItem());
  58. fw.write(item.getChar());
  59. scaner = huffman;
  60. }
  61.  
  62. }
  63.  
  64. /**
  65. * This method traverses the supplied huffman tree and prints out the
  66. * codes associated with each character
  67. *
  68. * @param t the root of the huffman tree to be traversed
  69. * code a String used to build the code for each character as
  70. * the tree is traversed recursively
  71. */
  72. static Map<Character,String> table = new Hashtable<>();
  73.  
  74. public static void traverse(TreeNode t, String code) {
  75.  
  76. // IMPLEMENT THIS METHOD
  77. if(!t.isLeaf()){
  78. traverse(t.getLeft(), code + '0');
  79. traverse(t.getRight(),code + '1');
  80. }
  81. else {
  82. CharFreq item = (CharFreq) (t.getItem());
  83. table.put(item.getChar(), code);
  84. System.out.println(item.getChar() +": "+ code);
  85. }
  86. }
  87.  
  88. // public static Map<Character, String> traverse(TreeNode t) {
  89. //
  90. // Map<Character,String> table = new Hashtable<>();
  91. //
  92. // // IMPLEMENT THIS METHOD
  93. // if(!t.isLeaf()){
  94. // traverse(t.getLeft());
  95. // traverse(t.getRight());
  96. // }
  97. // else {
  98. // CharFreq item = (CharFreq) (t.getItem());
  99. // System.out.println(item.getChar()+": " + "code");
  100. // }
  101. // }
  102. /**
  103. * This method removes the TreeNode, from an ArrayList of TreeNodes, which
  104. * contains the smallest item. The items stored in each TreeNode must
  105. * implement the Comparable interface.
  106. * The ArrayList must contain at least one element.
  107. *
  108. * @param a an ArrayList containing TreeNode objects
  109. *
  110. * @return the TreeNode in the ArrayList which contains the smallest item.
  111. * This TreeNode is removed from the ArrayList.
  112. */
  113. public static TreeNode removeMin(ArrayList a) {
  114. int minIndex = 0;
  115. for (int i = 0; i < a.size(); i++) {
  116. TreeNode ti = (TreeNode)(a.get(i));
  117. TreeNode tmin = (TreeNode)(a.get(minIndex));
  118. if (((Comparable)(ti.getItem())).compareTo(tmin.getItem()) < 0)
  119. minIndex = i;
  120. }
  121. TreeNode n = (TreeNode)a.remove(minIndex);
  122. return n;
  123. }
  124.  
  125. /**
  126. * This method counts the frequencies of each character in the supplied
  127. * FileReader, and produces an output text file which lists (on each line)
  128. * each character followed by the frequency count of that character. This
  129. * method also returns an ArrayList which contains TreeNodes. The item stored
  130. * in each TreeNode in the returned ArrayList is a CharFreq object, which
  131. * stores a character and its corresponding frequency
  132. *
  133. * @param fr the FileReader for which the character frequencies are being
  134. * counted
  135. * pw the PrintWriter which is used to produce the output text file
  136. * listing the character frequencies
  137. *
  138. * @return the ArrayList containing TreeNodes. The item stored in each
  139. * TreeNode is a CharFreq object.
  140. */
  141. public static ArrayList countFrequencies(FileReader fr, PrintWriter pw) throws Exception {
  142.  
  143. // IMPLEMENT THIS METHOD
  144. int c;
  145. ArrayList<TreeNode> list = new ArrayList<>();
  146.  
  147. while ((c = fr.read()) != -1) {
  148.  
  149. if(list.isEmpty()) {
  150. list.add(new TreeNode(new CharFreq((char) c, 1)));
  151. continue;
  152. }
  153. int i;
  154. for( i=0; i<list.size(); i++){
  155. TreeNode temp = list.get(i);
  156. CharFreq item = (CharFreq) (temp.getItem());
  157. if((char)c == item.getChar())
  158. list.set(i, new TreeNode(new CharFreq((char)c, item.getFreq() + 1)));
  159. }
  160.  
  161. if(i >=list.size())
  162. list.add(new TreeNode(new CharFreq((char)c, 1)));
  163. }
  164.  
  165. for(int i = 0; i < list.size(); i++){
  166. CharFreq temp = (CharFreq)(list.get(i).getItem());
  167. pw.print(temp);
  168. }
  169.  
  170. return list;
  171. }
  172.  
  173. /**
  174. * This method builds a huffman tree from the supplied ArrayList of TreeNodes.
  175. * Initially, the items in each TreeNode in the ArrayList store a CharFreq object.
  176. * As the tree is built, the smallest two items in the ArrayList are removed,
  177. * merged to form a tree with a CharFreq object storing the sum of the frequencies
  178. * as the root, and the two original CharFreq objects as the children. The right
  179. * child must be the second of the two elements removed from the ArrayList (where
  180. * the ArrayList is scanned from left to right when the minimum element is found).
  181. * When the ArrayList contains just one element, this will be the root of the
  182. * completed huffman tree.
  183. *
  184. * @param trees the ArrayList containing the TreeNodes used in the algorithm
  185. * for generating the huffman tree
  186. *
  187. * @return the TreeNode referring to the root of the completed huffman tree
  188. */
  189. public static TreeNode buildTree(ArrayList trees) throws IOException {
  190.  
  191. // IMPLEMENT THIS METHOD
  192. while(trees.size() > 1){
  193. TreeNode rleft = removeMin(trees);
  194. TreeNode rright = removeMin(trees);
  195. CharFreq item = new CharFreq('\u0000',((CharFreq)rleft.getItem()).getFreq() +
  196. ((CharFreq)rright.getItem()).getFreq() );
  197. TreeNode root = new TreeNode( item, rleft, rright);
  198. trees.add( root );
  199. }
  200. return (TreeNode)trees.get(0);
  201. }
  202.  
  203. /**
  204. * This method compresses a text file using huffman encoding. Initially, the
  205. * supplied huffman tree is traversed to generate a lookup table of codes for
  206. * each character. The text file is then read one character at a time, and
  207. * each character is encoded by using the lookup table. The encoded bits for
  208. * each character are written one at a time to the specified BitWriter.
  209. *
  210. * @param fr the FileReader which contains the text file to be encoded
  211. * huffman the huffman tree that was used for compression, and
  212. * hence should be used for decompression
  213. * bw the BitWriter used to write the compressed bits to file
  214. */
  215. public static void compress(FileReader fr, TreeNode huffman, BitWriter bw) throws Exception {
  216.  
  217. // IMPLEMENT THIS METHOD
  218. traverse(huffman,"");
  219.  
  220. int c;
  221. while((c = fr.read()) != -1){
  222.  
  223. char c1 = (char) c;
  224. String code = table.get(c);
  225. char[] arrayCodes = code.toCharArray();
  226.  
  227. for(int i = 0; i < arrayCodes.length; i++){
  228. if(arrayCodes[i] == '0')
  229. bw.writeBit(false);
  230. if(arrayCodes[i] == '1')
  231. bw.writeBit(true);
  232. }
  233. }
  234.  
  235. }
  236.  
  237. /**
  238. * This method reads a frequency file (such as those generated by the
  239. * countFrequencies() method) and initialises an ArrayList of TreeNodes
  240. * where the item of each TreeNode is a CharFreq object storing a character
  241. * from the frequency file and its corresponding frequency. This method provides
  242. * the same functionality as the countFrequencies() method, but takes in a
  243. * frequency file as parameter rather than a text file.
  244. *
  245. * @param inputFreqFile the frequency file which stores characters and their
  246. * frequency (one character per line)
  247. *
  248. * @return the ArrayList containing TreeNodes. The item stored in each
  249. * TreeNode is a CharFreq object.
  250. */
  251. public static ArrayList readFrequencies(String inputFreqFile) throws Exception {
  252.  
  253. // IMPLEMENT THIS METHOD
  254. FileInputStream fis = new FileInputStream(inputFreqFile);
  255. InputStreamReader isr = new InputStreamReader(fis,"utf-8");
  256. BufferedReader br = new BufferedReader(isr);
  257.  
  258. ArrayList<TreeNode> list = new ArrayList<>();
  259.  
  260. String s;
  261. while((s = br.readLine()) != null){
  262. String[] ss = s.split(" ");
  263. TreeNode t = new TreeNode(new CharFreq(ss[0].charAt(0), Integer.parseInt(ss[1])));
  264. list.add(t);
  265. }
  266.  
  267. return list;
  268. }
  269.  
  270. /* This TextZip application should support the following command line flags:
  271.  
  272. QUESTION 2 PART 1
  273. =================
  274. -a : this uses a default prefix code tree and its compressed
  275. file, "a.txz", and decompresses the file, storing the output
  276. in the text file, "a.txt". It should also print out the size
  277. of the compressed file (in bytes), the size of the decompressed
  278. file (in bytes) and the compression ratio
  279.  
  280. QUESTION 2 PART 2
  281. =================
  282. -f : given a text file (args[1]) and the name of an output frequency file
  283. (args[2]) this should count the character frequencies in the text file
  284. and store these in the frequency file (with one character and its
  285. frequency per line). It should then build the huffman tree based on
  286. the character frequencies, and then print out the prefix code for each
  287. character
  288.  
  289. QUESTION 2 PART 3
  290. =================
  291. -c : given a text file (args[1]) and the name of an output frequency file
  292. (args[2]) and the name of the output compressed file (args[3]), this
  293. should compress file
  294.  
  295. QUESTION 2 PART 4
  296. =================
  297. -d : given a compressed file (args[1]) and its corresponding frequency file
  298. (args[2]) and the name of the output decompressed text file (args[3]),
  299. this should decompress the file
  300.  
  301. */
  302.  
  303. public static void main(String[] args) throws Exception {
  304.  
  305. if (args[0].equals("-a")) {
  306. BitReader br = new BitReader("a.txz");
  307. FileWriter fw = new FileWriter("a.txt");
  308.  
  309. // Get the default prefix code tree
  310. TreeNode tn = abracadbraTree();
  311.  
  312. // Decompress the default file "a.txz"
  313. decompress(br, tn, fw);
  314.  
  315. // Close the ouput file
  316. fw.close();
  317. // Output the compression ratio
  318. // Write your own implementation here.
  319.  
  320. }
  321.  
  322. else if (args[0].equals("-f")) {
  323. FileReader fr = new FileReader(args[1]);
  324. PrintWriter pw = new PrintWriter(new FileWriter(args[2]));
  325.  
  326. // Calculate the frequencies
  327. ArrayList trees = countFrequencies(fr, pw);
  328.  
  329. // Close the files
  330. fr.close();
  331. pw.close();
  332.  
  333. // Build the huffman tree
  334. TreeNode n = buildTree(trees);
  335.  
  336. // Display the codes
  337. traverse(n, "");
  338. }
  339.  
  340. else if (args[0].equals("-c")) {
  341.  
  342. FileReader fr = new FileReader(args[1]);
  343. PrintWriter pw = new PrintWriter(new FileWriter(args[2]));
  344. ArrayList trees = countFrequencies(fr, pw);
  345.  
  346. fr.close();
  347. pw.close();
  348.  
  349. TreeNode n = buildTree(trees);
  350.  
  351. // IMPLEMENT NEXT
  352. // Finish the compress function here
  353.  
  354. // then output the compression ratio
  355. // Write your own implementation here.
  356.  
  357. }
  358.  
  359. else if (args[0].equals("-d")) {
  360. ArrayList a = readFrequencies(args[2]);
  361. TreeNode tn = buildTree(a);
  362. BitReader br = new BitReader(args[1]);
  363. FileWriter fw = new FileWriter(args[3]);
  364. decompress(br, tn, fw);
  365. fw.close();
  366.  
  367. // Output the compression ratio
  368. // Write your own implementation here.
  369.  
  370. }
  371. }
  372. }

huffman树实现的压缩算法,java的更多相关文章

  1. Java蓝桥杯练习题——Huffman树

    Huffman树在编码中有着广泛的应用.在这里,我们只关心Huffman树的构造过程. 给出一列数{pi}={p0, p1, -, pn-1},用这列数构造Huffman树的过程如下: 找到{pi}中 ...

  2. [数据结构与算法]哈夫曼(Huffman)树与哈夫曼编码

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  3. Huffman树与编码的简单实现

    好久没写代码了,这个是一个朋友问的要C实现,由于不会C,就用JAVA写了个简单的.注释掉的代码属性按照原来朋友发的题里带的参数,发现没什么用就给注释掉了. package other; import ...

  4. 数据结构(二十七)Huffman树和Huffman编码

    Huffman树是一种在编码技术方面得到广泛应用的二叉树,它也是一种最优二叉树. 一.霍夫曼树的基本概念 1.结点的路径和结点的路径长度:结点间的路径是指从一个结点到另一个结点所经历的结点和分支序列. ...

  5. Huffman树与Huffman编码

    1.Huffman树 今天复习Huffman树.依稀记得自己被Huffman树虐的经历.还记得是7月份,我刚开始看数据结构与算法,根本看不懂Huffman树的操作.后来我终于悟出了Huffman树是怎 ...

  6. Huffman树、霍夫曼编码

    Huffman树指的是带权路径长度WPL最小的二叉树 WPL=路径*权值 Huffman常用于压缩编码,正常传输ABCDEF这些字母需要3位二进制树来描述,但由于一篇文章中ABCDEF这些字母出现的概 ...

  7. 构造数列Huffman树总耗费_蓝桥杯

    快排! /** 问题描述 Huffman树在编码中有着广泛的应用.在这里,我们只关心Huffman树的构造过程. 给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的 ...

  8. NOI 2015 荷马史诗【BZOJ 4198】k叉Huffman树

    抱歉因为NOIP集训,好长时间没再写题解了. NOI 2015也就只有这道题一看就能懂了-- 4198: [Noi2015]荷马史诗 Time Limit: 10 Sec  Memory Limit: ...

  9. 【数据结构】Huffman树

    参照书上写的Huffman树的代码 结构用的是线性存储的结构 不是二叉链表 里面要用到查找最小和第二小 理论上锦标赛法比较好 但是实现好麻烦啊 考虑到数据量不是很大 就直接用比较笨的先找最小 去掉最小 ...

随机推荐

  1. Spring Boot与Docker部署

    开启Docker远程访问 首先需要开启docker远程访问功能,以便可以进行远程操作. CentOS 6 修改/etc/default/docker文件,重启后生效(service docker re ...

  2. 关于d3.js 将一个element 拖拽到另一个element的响应事件

    rt 正在做机柜可视化, 一个需求是能拖拽左侧列表的设备名称, 拖到右侧42U机柜中,并将设备图片放置在对应机柜位置上. 开始的时候一切都很顺利,点击左侧设备名称,添加一个g容器,将设备名称作为tex ...

  3. 解决Oracle数据库空间不足问题

    //查询表空间的大小以及文件路径地址select tablespace_name, file_id, file_name,round(bytes/(1024*1024),0) total_space ...

  4. SQLServer “无法对数据库'XXX' 执行删除,因为它正用于复制”的解决方法

    “无法对数据库'XXX'执行删除,因为它正用于复制” 解决办法: 执行  sp_removedbreplication 'XXX'  这个语句的解释是:从数据库中删除所有复制对象,但不更新分发服务器上 ...

  5. SpringMVC的执行流程

    解析SpringMVC执行流程 SpringMVC的执行图大概如下所示 1.首先它是由客户端发起请求,到DispatcherServlet,被拦截后到HandlerMapping这里充当一个路由器,通 ...

  6. 13. Roman to Integer (JAVA)

    Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. Symbol Value I 1 ...

  7. PCIE4.0 简单介绍

    关于PCI-E的标准,可以从2003年说起,2003年推出了PCI-E 1.0标准,在三年之后就推出了PCI-E 2.0,而在4年后的2010年就推出了PCI-E 3.0,但是在2010年之后的6年里 ...

  8. OO_多线程电梯_单元总结

    概述: 面向对象的第二单元是多线程电梯.第一次实现一部傻瓜电梯,每次只送一个人:第二次实现一部可稍带电梯:第三次实现三部可稍带电梯. 一.设计策略 1.第5.6次作业设计思路 第5.6次作业的架构相似 ...

  9. UML图之时序图

    时序图(Sequence Diagram)是显示对象之间交互的图,这些对象是按时间顺序排列的.顺序图中显示的是参与交互的对象及其对象之间消息交互的顺序.时序图中包括的建模元素主要有:角色(Actor) ...

  10. IDEA开发环境中快捷键与系统 QQ等冲突的解决办法

    1.快捷键冲突1:IDEA中,Ctrl+Alt+向左/右/箭头快捷键 (回到光标的前一个位置,回到光标的后一个位置).该快捷键与系统中旋转屏幕的快捷键冲突了,需要解决.为了保留IDEA的中快捷键,我就 ...