学校的数据结构试验题目二--哈夫曼树编码

学校的数据结构试验题目二--哈夫曼树编码

终于写完了~~我觉得那个解码编码部分还能优化~~ 
如果有更好的方法欢迎赐教~~呵呵

题目:
009.bmp





解法:
  1  #include  < iostream >
  2  #include  < windows.h >
  3  #include  < tchar.h >
  4 
  5  #define  MAXVALUE 0xffff
  6  using   namespace  std ;
  7 
  8  typedef  struct {
  9       char  data ;
 10       int  value ;
 11       int  parent ;
 12       int  lchild ;
 13       int  rchild ;
 14  } HfmTree;   // 哈夫曼树结构 
 15 
 16  typedef  struct  {
 17       int  count ;
 18       char  code[ 10 ] ;
 19  } HfmCode , * pHfmCode;    // 哈夫曼树编码时储存编码序列结构
 20 
 21  void  CreateHfm(HfmTree hfmt[] ,  int  bufcount)   // 建立哈夫曼树
 22  {
 23       for int  i  =   0  ; i  <   2 * bufcount - 1  ; i ++  )
 24      {
 25          hfmt[i].parent  =   - 1  ;
 26          hfmt[i].lchild  =   - 1  ;
 27          hfmt[i].rchild  =   - 1  ;
 28      }
 29 
 30       for int  i  =   0  ; i  <  bufcount - 1  ; i  ++  )
 31      {
 32           int  min1  =  MAXVALUE, min2  =  MAXVALUE ,tem1  =   0  , tem2  =   0  ;
 33 
 34           for ( int  j  =   0  ; j  <  bufcount + i ; j ++  )     // 找出权值最小的2个树
 35          {
 36               if ( hfmt[j].parent  ==   - 1   &&  hfmt[j].value  <  min1 )
 37              {
 38                  min2  =  min1 ;
 39                  tem2  =  tem1 ;
 40                  min1  =  hfmt[j].value ;
 41                  tem1  =  j ;
 42              } else   if ( hfmt[j].parent  ==   - 1   &&  hfmt[j].value  <  min2)
 43              {
 44                  min2  =  hfmt[j].value ;
 45                  tem2  =  j ;
 46              }
 47          }
 48           // 合并树
 49              hfmt[tem1].parent  =  bufcount  +  i ;
 50              hfmt[tem2].parent  =  bufcount  +  i ;
 51              hfmt[bufcount + i].lchild    =  tem1 ;
 52              hfmt[bufcount + i].rchild    =  tem2 ;
 53              hfmt[bufcount + i].value  =  hfmt[tem1].value  +  hfmt[tem2].value  ;
 54      }
 55  }
 56      
 57  pHfmCode GetHfmCode(HfmTree hfmt[] ,  char  target ,  int  bufcount)   // 根据哈夫曼树编码函数
 58  {
 59       int  pos , temp , count  =   0  ;
 60      pHfmCode code  =   new  HfmCode ;
 61      code -> count  =   0  ;
 62 
 63       for int  i  =   0  ; i  <  bufcount ; i ++  )
 64      {
 65           if ( hfmt[i].data  ==  target )   // 找到目标字符在树中位置
 66          {        
 67              pos  =  i ;
 68               break  ;
 69          }
 70      }
 71      
 72       while ( 1 )   // 从叶子逆推到根节点,所得的序列倒序就是字符对应的哈夫曼编码
 73      {
 74          temp  =  hfmt[pos].parent ;
 75          
 76           if (temp  ==   - 1 )
 77               break  ;
 78 
 79           if ( hfmt[temp].lchild  ==  pos )
 80              code -> code[count ++ =   0 + ' 0 '  ;   // 转换成字符串存放
 81           else
 82              code -> code[count ++ =   1 + ' 0 '  ;
 83 
 84          pos  =  temp ;
 85          code -> count ++  ;
 86      }
 87 
 88       return  code ;    
 89  }
 90 
 91  void  CodingBuf( char  ipbuf[] , HfmTree  * hfmt ,  int  bufcount)    // 讲得到的字符串进行编码,然后写入文件
 92  {
 93      FILE  * codef ;
 94 
 95       codef  =  _tfopen( " codefile.txt "  ,  " w+ "  ) ;
 96      
 97       while ( 1 )
 98      {
 99           if ( * ipbuf  ==   ' \0 ' )   // 如果字符串遍历结束就跳出循环
100               break  ;
101 
102          pHfmCode code  =  GetHfmCode(hfmt ,  * ipbuf , bufcount) ;  // 获得哈夫曼编码
103          
104           for int  i  =  code -> count ; i  >   0  ; i --  )   // 要倒着打印,应为之前是逆推到树根的,得到的序列也是倒序的
105              fwrite( & code -> code[i - 1 ] ,  sizeof ( char ) ,  1  , codef ) ;
106          
107          ipbuf ++  ;
108      }
109 
110      fclose(codef) ;
111  }
112 
113  void  DecodingBuf(HfmTree hfmt[] ,  char  codefile[] ,  int  bufcount)   // 哈夫曼解码函数
114  {
115          FILE  * textf ;
116          textf  =  _tfopen( " textfile.txt "  ,  " w+ " ) ;
117           char  decodebuf[ 100 =  {  0  }  ,  * temp  =  codefile ;
118           int  count  =  bufcount * 2 - 2   , i  =   0 ;
119  /*
120  根据输入的编码信息,从树根开始向下遍历,
121  只要到叶子的地方就储存叶子数据,然后回到树根继续遍历
122  知道将输入的编码信息遍历完为止
123  */
124           do  
125          {
126               if ( hfmt[count].data  !=   0  )
127              {
128                  decodebuf[i ++ =  hfmt[count].data ;
129                  count  =  bufcount * 2 - 2  ;
130              }
131               if * temp  ==   ' 0 '  )
132                  count  =  hfmt[count].lchild ;
133               else
134                  count  =  hfmt[count].rchild ;
135          } while *  (temp ++ !=   ' \0 ' ) ;
136 
137          fwrite(decodebuf ,  sizeof ( char ) ,  100  , textf ) ;   // 解码信息写入文件
138 
139          fclose(textf) ;
140  }
141 
142 
143    
144  int  main( void )
145  {
146      FILE  * hfmf ,  * codef , * textf ;
147       char  ipbuf[ 100 ] ;
148       int  bufcount  =   4  ;
149      HfmTree hfmt[ 19 =  { 0 } ;
150 
151  // ----------------------------------------------信息收集部分
152      cout << " 输入终端字符集大小(1-10) " << endl ;
153      cin >> bufcount ;
154 
155       for ( int  i  =   0  ; i  <  bufcount ; i ++  )
156      {
157      cout << " 请输入终端字符内容: " << endl ;
158      cin >> hfmt[i].data ;
159      cout << " 请输入终端字符权值:(0-9) " << endl ;
160      cin >> hfmt[i].value ;
161      }
162 
163 
164  // -----------------------------------------------建哈夫曼树部分
165      CreateHfm(hfmt ,bufcount ) ;
166 
167       // 打印哈夫曼树
168       for ( int  i  =   0  ; i  <  bufcount * 2 - 1  ; i ++ )
169      {
170          cout << " id " << ' \t ' << " data " << ' \t ' << " parent " << ' \t ' << " lchild " << ' \t ' << " rchild " << ' \t ' << " value " << endl ;
171          cout << i << ' \t ' << hfmt[i].data << ' \t ' << hfmt[i].parent << ' \t ' << hfmt[i].lchild << ' \t ' << hfmt[i].rchild << ' \t ' << hfmt[i].value << endl ;
172      }
173 
174      hfmf  =  _tfopen( " hfmtree.txt "  ,  " w+ "  ) ;
175      
176 
177 
178       char  tittle[] = " id    data    parent    lchild    rchild    values "  ;
179      tittle[strlen(tittle)]  =   ' \n '  ;
180      fwrite(tittle ,  sizeof ( char ) ,  sizeof (tittle) , hfmf ) ;
181       char  data[ 1000 = { 0 }, * buf  =  data  , intbuf[ 10 = 0  };
182       for ( int  i  =   0  ; i  <  bufcount * 2 - 1  ; i ++ )
183      {
184          _itoa(i ,  intbuf ,  10  ) ;
185          memcpy(buf ,  intbuf , strlen(intbuf) * sizeof ( char ) ) ;
186          buf  +=  strlen(intbuf) ; 
187           * buf  =   ' \t ' ; buf ++  ;
188           * buf  =  hfmt[i].data ; buf ++  ;
189           * buf  =   ' \t ' ; buf ++  ;
190          
191          _itoa(hfmt[i].parent ,  intbuf ,  10  ) ;
192          memcpy(buf ,  intbuf , strlen(intbuf) * sizeof ( char ) ) ;
193          buf  +=  strlen(intbuf) ;
194           * buf  =   ' \t ' ; buf ++  ;
195 
196          _itoa(hfmt[i].lchild ,  intbuf ,  10  ) ;
197          memcpy(buf ,  intbuf , strlen(intbuf) * sizeof ( char ) ) ;
198          buf  +=  strlen(intbuf) ;
199           * buf  =   ' \t ' ; buf ++  ;
200          
201          _itoa(hfmt[i].rchild ,  intbuf ,  10  ) ;
202          memcpy(buf ,  intbuf , strlen(intbuf) * sizeof ( char ) ) ;
203          buf  +=  strlen(intbuf) ;
204           * buf  =   ' \t ' ; buf ++  ;
205 
206          _itoa(hfmt[i].value ,  intbuf ,  10  ) ;
207          memcpy(buf ,  intbuf , strlen(intbuf) * sizeof ( char ) ) ;
208          buf  +=  strlen(intbuf) ;
209           * buf  =   ' \n ' ; buf ++  ;
210 
211      }
212      fwrite(data ,  sizeof ( char ) ,  1000  , hfmf );
213      
214      cout << buf << endl ;
215  // -----------------------------------------------编码部分
216      cout << " 输入要编码的字符串 " << endl ;
217      cin >> ipbuf ;
218 
219      CodingBuf(ipbuf , hfmt , bufcount ) ;
220      
221      codef  =  _tfopen( " codefile.txt "  ,  " r+ " ) ;
222       char  codefile[ 100 =  { 0 };
223 
224      fread(codefile ,  sizeof ( char ) ,  100  , codef) ;
225      
226      cout << " 编码结果 " << endl ;
227      cout << codefile << endl ;
228 
229      system( " pause " ) ;
230  // -----------------------------------------------解码部分
231      cout << " 解码ING " << endl ;
232      DecodingBuf(hfmt , codefile , bufcount ) ;
233 
234      cout << " 解码结果: " << endl  ;
235      textf  =  _tfopen( " textfile.txt "  ,  " r+ "  ) ;
236      memset(codefile ,  0  ,  100 ) ;
237 
238      fread(codefile ,  sizeof ( char ) ,  100  , textf ) ;
239 
240      cout << codefile << endl ;
241      
242      system( " pause " ) ;
243 
244 
245 
246      fclose( textf ) ;
247      fclose( hfmf ) ;
248      fclose(codef) ;
249       return   1 ;
250 
251  }
252 
253 
254 


你可能感兴趣的:(学校的数据结构试验题目二--哈夫曼树编码)