• ベストアンサー

ハフマン符号化の問題を解くプログラム

ハフマンの符号化の問題を解くプログラムをC言語(コンソールアプリケーション)で作りたいのですが ファイルの圧縮とかをするプログラムはいろいろなサイトにあったのですが、 簡単な情報源を与えられたものを符号化するプログラムで参考にできるようなサイトは見つかりませんでした。 誰かプログラムの例を教えていただけないでしょうか? 入力する例はつぎのようなものです S=(a1, a2, a3, a4, a5, a6/0.35, 0.15, 0.15, 0.20, 0.10, 0.05)

  • upnn
  • お礼率90% (10/11)

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

木の作り方によって得られる符号は微妙に違いますのでこれは参考です。 シンボルと頻度テーブルから木を作って符号一覧を表示します。 符号化だけならleftとrightは不要です(復号化のとき使う) #include <stdio.h> #define N 6 /* N>=2 */ char *s[N]={"a1","a2","a3","a4","a5","a6"}; float f[2*N-1]={0.35,0.15,0.15,0.20,0.10,0.05}; int size=N, parent[2*N-1], left[2*N-1], right[2*N-1]; /* ハフマン木の作成 */ void huff(void) {  int i,j,dat1,dat2;  float min;  /* 初期化 */  for (i=0;i<2+N;i++) left[i]=right[i]=parent[i]=0;  /* 最小頻度2個をまとめ続ける */  while(1) {   /* 一番小さい数を探す */   for (i=0;i <size;i++) if (f[i]>=0) break;   if (i==size) break; /* 頻度リストが空? */   dat1=i; min=f[dat1];   for (;i<size;i++) if (f[i]<min && f[i]>=0) {min=f[i]; dat1=i;}   /* 二番目に小さい数を探す */   for (i=0; i<size; i++) if ((f[i]>=0)&&(i!=dat1)) break;   if (i==size) break; /* 頻度リストが1個しかない */   dat2=i; min=f[dat2];   for (;i<size;i++) if (f[i]<min && f[i]>=0 && i!=dat1) { min=f[i]; dat2=i; }   /* 木に登録 */   left[size]=dat1; right[size]=dat2;   parent[dat1]=size; parent[dat2]= -size;   f[size]=f[dat1]+f[dat2]; f[dat1]= -1; f[dat2]= -1;   size ++;  } } /* ハフマン符号の出力 */ void outenc(int huf) {  if (huf== size-1) return;  if (parent[huf]<0) {   outenc(-parent[huf]); printf("1");  } else {   outenc(parent[huf]); printf("0");  } } /* メインルーチン */ int main(void) {  int i;  huff();  for (i=0; i<N; i++) { printf("%s ",s[i]); outenc(i); printf("\n"); }  return 0; }

upnn
質問者

お礼

詳しい説明ありがとうございます。 コメントが多いのでとてもわかりやすかったです。 これを参考にいろいろ変えて試してみます。 本当にありがとうございました。

関連するQ&A

  • ハフマン符号のプログラム

     以下の問題に回答できる方,いらっしゃいましたらソースファイルと実行結果を送ってください。  ファァイル(記号列)を読み込んで,ハフマン符号によりファイルを圧縮するプログラム(C言語)を作成する(プログラムは,圧縮を行うものと,解凍を行うものの2つ作る)。また,いくつか適当なファイルに対して,圧縮を行い圧縮率を測定する。 (1)圧縮プログラムについて  圧縮のステップ  (a)入力ファイルを読み込み各記号の出現頻度をカウントする。  (b)得られた出現頻度を使って各符号のハフマン符号を生成する。  (c)各符号の出現頻度を出力ファイルに書き出す。  (d)もう一度入力ファイルを読み込みながら各符号をハフマン符号で置き換え    て出力ファイルに出力する。圧縮ファイルの形式は次のようになる。   0x00の  0x01の … 0xffの 先頭文字の 2文字目の … 終端文字の   出現頻度 出現頻度 出現頻度 符号語   符号語    符号語    (c)で書きこむ部分      (d)で書きこむ部分 (2)解凍プログラムについて  解凍のステップ  (a)各符号の出現頻度を圧縮ファイルから読み込む。  (b)得られた出現頻度を使って各符号のハフマン符号を生成する。  (c)圧縮ファイルの符号語を読み込みながら各符号のハフマン符号と比較しも    し一致したらその記号を解凍ファイルに出力する。  (d)(c)をファイルの終わりもしくは出現頻度をすべて足し合わせた記号数分処   理するまで繰り返す。  関数について  関数get_bit  ファイルから1bit読み込んで戻り値として返す。  (ファイルポインタはグローバル変数で用意する)  関数put_bit  引数として0,または1を渡すと1bitずつファイルに書き込む。  (ファイルポインタはグローバル変数で用意する)

  • ハフマン符号化について

    ハフマン符号化についてですが、圧縮のためであるので、 ハフマン符号化を行いなさいといわれた場合において、 木構造の1と0の取り方はどんなものでも良いのでしょうか? 生起確率が A:0.12 B:0.12 C:0.28 D:0.48 であった場合、 添付画像の青い文字のように符号化を行い、 A:000 B:001 C:01 D:1 としても、赤い文字のように符号化を行い、 A:111 B:110 C:10 D:0 としても、どちらでもハフマン符号化としては正解なのでしょうか? また、0と1を階層ごとにランダムにとっても問題ないのでしょうか?

  • 2元ハフマン符号化プログラムが作れなくて困っています。

    以下のC言語のプログラムを作成出来る方、いらっしゃいましたらソースファイルを載せて下さい。 2元ハフマン符号化プログラム:具体的な無記憶情報源が入力されたときに、そのハフマン記号を出力される ご教授よろしくおねがいします

  • ブロックハフマン符号化プログラムの作成

    現在学校の研究で「ブロック(n次拡大情報源)ハフマン符号化」プログラムをC言語で作成しています。 これは、通常のハフマン符号化でデータ1個ごとに出現頻度を調べてそれぞれにハフマン符号を割り当てるところを、ファイル中で隣り合うデータ2個(あるいは3個、4個、・・・n個)を一かたまりと見なし、それぞれの出現頻度を調べてハフマン符号を割り当てる、というものです。 通常のハフマン符号化は以前作成したことがあるのですが、これをどのようにして上記のようなプログラムに改変すればいいのかわかりません。 ちなみに、データのバッファリングは以下のようにし、 #define BUFFER_SIZE 102400 unsigned char buffer[BUFFER_SIZE]; (中略) int i,c; i = 0; while(i < BUFFER_SIZE && (c = fgetc(fp_i)) != EOF) { buffer[i] = c; i++; } 各データの出現頻度は以下のようにして調べています。 #define N 256 (中略) int hist[N * 2]; for(i = 0;i < (N * 2);i++) hist[i] = 0; for(i = 0;i < size;i++) hist[data[i]]++; ※data[i]は前述のbuffer[i]、sizeは前述のi(圧縮対象データのファイルサイズ)です。 やはり、バッファリングに使う配列をもう少しサイズの大きい型で宣言するとこから始めるべきでしょうか? ご教授お願いします。

  • VB2008  ハフマン符号のプログラム

    ハフマン符号のプログラムソースを探しています! http://www.ccad.sist.chukyo-u.ac.jp/~mito/syllabi/daisu/huffman/index.htm#TOP に、Visual C++で作成されたプログラムがあります。 これを、VB2008に書きかえることのできる方いらっしゃいませんか? 符号化と複合化を別に(コントロールのボタンを用いて「符号化」、「複合化」とできるなど)していただければありがたいです。 ぜひ、よろしくお願いします!!

  • ハフマン符号化による圧縮

    1と0でできたN×Nの行列 例えば 0 1 1 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 1 0 0 1 1 0 1 1 0 0 1 0 0 0 1 1 0 0 というような行列を ___ |01|1 1 1 0 |01|1 0 0 0  ̄ ̄ ̄  1 1  0 0 1 1  1 0  0 1 1 0  1 1  0 0 1 0  0 0  1 1 0 0 このように4ビットごとに分けてハフマン符号化による圧縮を行うプログラムを作りたいと考えていますが、よくわかりません。どなたか教えてください。 また四角で囲んだところは0101と考えていいそうです。

  • JPEG画像にさらにハフマン符号化をかけると・・・?

    現在卒業研究の一環で「なぜJPEG画像にハフマン符号化をかけてもほとんど圧縮できないのか?」というテーマについて考えています。 研究の過程でハフマン符号化プログラムを組み、様々な種類のJPEG画像を圧縮し、圧縮率を検証しました。その結果、フルカラー画像もグレースケール画像もほとんど圧縮できませんでしたが、単純な線画(白地に黒い線を数本引いただけのもの)の画像のみ元の2割程度まで圧縮できました。 最初はやはりJPEG画像には元からハフマン符号化がかかっているから圧縮率が悪いのかな、とも思ったのですが、『単純な線画の画像のみ元の2割程度まで圧縮できている』ので、単に「元からハフマン符号化がかかっているから」では説明がつかないように思えます。 おおまかで構いませんので、これの原因について皆様のご意見をお聞かせください。よろしくお願いします。

  • ハフマン符号によるエントロピー符号化?

    現在、JPEG画像圧縮について調べていまして、 1 非可逆圧縮では、まず離散コサイン変換をして、画像の空間領域を周波数領域に変換 2 次に1によって変換した周波数領域をアナログデータと見たて、デジタル化する量子化を行い情報量を削る。 3 最後にハフマン符号によるエントロピー符号化で圧縮  とwikipediaで調べて2までは理解できたのですが、3のハフマン符号によるエントロピー符号化というのがよくわかりません。 どなたか詳しい方、わかりやすく教えていただけないでしょうか?  回答よろしくおねがいいたします。

  • ハフマン符号 情報源記号と符号語の対応表

    S=(a1 0.15 , a2 0.3 , a3 0.05 , a4 0.2 a5 0.25 , a6 0.05) この情報源Sに対するハフマン符号をハフマン符号の木を構成することにより、情報源記号と符号語の対応表を示せ。 という問題があるのですが、これについて質問です。 符号の木は、これらのa1~a6が二進数でどうなるのかがわからないと書けないと思うのですが、この問題にはその二進数の割り当てがしてありません。 これは最初からa1ならば0やa2ならば01という風に決まっていたり、また、勝手に割り当ててもいいのでしょうか? どなたかご教授お願いします。

  • Huffmannのプログラム

    Huffman法のプログラムをC言語で作成する上で、Huffman木の作成と符号化のところがなかなか出来なくて困っています。 英文を読み込んで、各文字の出現回数を数えて、というところまではいけるのですが… 教えていただけませんか?(特にHuffman木を作るところ) Huffman法の仕組みは分かるのですが…

専門家に質問してみよう