開放番地法でのハッシュ表生成

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
カイト

開放番地法でのハッシュ表生成

#1

投稿記事 by カイト » 14年前

C言語 Linux gcc

整数が1,000,000入っているファイルを読み込み開放番地法でハッシュ表を生成するプログラムを作っています。
・1レコード読み込みハッシュ表に格納する際に探査回数を計測し、加算していく。
・また、100,000レコード読み込み格納する毎の時刻を計測する。
イメージとしては以下のような感じです。

要素数  占有率 総探査回数 格納時間(秒)
100,000  0.1   *******    *******
200,000  0.2   *******    *******
300,000  0.3   ******     ******
      ・・・
        ・・・
1,000,000 1.0   *******    ******


やりたいことは伝わりましたでしょうか。
(もし「わけわからねー」ということがありましたら質問していただければ迅速に回答いたします)

自分でもできる限りのことはしてみたのですが、占有率と格納時間がうまくいきません。
総探査回数もあっているかどうか・・・
ファイルは以下のサイトにアップしてあります。

http://www.dotup.org/uploda/www.dotup.o ... 4.zip.html

ヘッダーファイルだけうまくアップロードできなかったので以下にに示しておきます。

コード:

/*hash_open.h*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>

typedef struct cell{     //バケットの構造体
  int key;               //キー(整数値)
}CELL;
CELL*Htable;             //ハッシュ表(開放番地法、連鎖法)

#define INTV -1          //初期化定数
#define FLS  -1          //関数戻り値(エラー値)

#include"Hash_funcs.c"      //ハッシュ関数
#include"Hash.c"            //ハッシュ表関連の関数
#include"Hash_open.c"          //開放番地法操作関数

#define STORE rc = store(Htable, HSIZE, DVS, inv)     //キーの格納
#define CHECK  rc = check_Htable(Htable, HSIZE)        //ハッシュ表が初期化されているか
#define DELHASH deallocate_Htable(Htable)              //ハッシュ表の削除

何日か前にも似たような質問をさせていただきましたが、ファイルがうまくアップできていなかったようで、申し訳ありませんでした。以前の問題は解決しました。
似たような質問なので、同じトピック内で質問すべきことかもしれませんが、ファイルがゴチャゴチャになるとわかりずらいと思いまして、新たにトピックを立てました。
よろしくお願いします。
http://dixq.net/forum/viewtopic.php?f=3&t=9413

box
記事: 2002
登録日時: 15年前

Re: 開放番地法でのハッシュ表生成

#2

投稿記事 by box » 14年前

カイト さんが書きました: http://www.dotup.org/uploda/www.dotup.o ... 4.zip.html
中身を見たところ、まだ化けているようです。
カイト さんが書きました: ヘッダーファイルだけうまくアップロードできなかったので以下にに示しておきます。

コード:

#include"Hash_funcs.c"      //ハッシュ関数
#include"Hash.c"            //ハッシュ表関連の関数
#include"Hash_open.c"          //開放番地法操作関数
ヘッダーの中で*.cファイルをインクルードする、という設計ポリシーは本当に適切なのでしょうか。
私にはそのポリシーがどうも理解できません。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

カイト

Re: 開放番地法でのハッシュ表生成

#3

投稿記事 by カイト » 14年前

box さんが書きました:
カイト さんが書きました: http://www.dotup.org/uploda/www.dotup.o ... 4.zip.html
中身を見たところ、まだ化けているようです。
カイト さんが書きました: ヘッダーファイルだけうまくアップロードできなかったので以下にに示しておきます。

コード:

#include"Hash_funcs.c"      //ハッシュ関数
#include"Hash.c"            //ハッシュ表関連の関数
#include"Hash_open.c"          //開放番地法操作関数
ヘッダーの中で*.cファイルをインクルードする、という設計ポリシーは本当に適切なのでしょうか。
私にはそのポリシーがどうも理解できません。

カイト

Re: 開放番地法でのハッシュ表生成

#4

投稿記事 by カイト » 14年前

box さんが書きました:
カイト さんが書きました: http://www.dotup.org/uploda/www.dotup.o ... 4.zip.html
中身を見たところ、まだ化けているようです。
カイト さんが書きました: ヘッダーファイルだけうまくアップロードできなかったので以下にに示しておきます。

コード:

#include"Hash_funcs.c"      //ハッシュ関数
#include"Hash.c"            //ハッシュ表関連の関数
#include"Hash_open.c"          //開放番地法操作関数
ヘッダーの中で*.cファイルをインクルードする、という設計ポリシーは本当に適切なのでしょうか。
私にはそのポリシーがどうも理解できません。

カイト

Re: 開放番地法でのハッシュ表生成

#5

投稿記事 by カイト » 14年前

↑間違えて送信してしまいました<(_ _)>
box さんが書きました: 中身を見たところ、まだ化けているようです。
再度ダウンロードしましたが、文字化けはみられませんでした。
具体的にどのファイルのどの部分が文字化けしているか教えてください。
box さんが書きました: ヘッダーの中で*.cファイルをインクルードする、という設計ポリシーは本当に適切なのでしょうか。
私にはそのポリシーがどうも理解できません。
ポリシーなんてありませんよ。学校で教えられた通りにやっているだけです。

カイト

Re: 開放番地法でのハッシュ表生成

#6

投稿記事 by カイト » 14年前

すみません、最初からここに張っておけばよかったですねw
よろしくお願いします。

コード:

/* Hash.c */

//入力値:hsize    ハッシュ表の大きさ(番地空間)
//戻り値:Htable   ハッシュ表の先頭番地

CELL *allocate_Htable(int hsize){
  CELL *Htable;
  Htable = (CELL*)malloc(sizeof(CELL)*hsize);   //ハッシュ表を割り付け
  if(Htable == NULL){
    printf("空き記憶域がありません。\n");
    exit(1);
  }
  return Htable;
}


//入力値: hsize    ハッシュ表の大きさ(番地空間)
//     **Htable ハッシュ表の先頭番地
//戻り値:      無し
void deallocate_Htable(CELL *Htable){
  free(Htable);
  return;
}

コード:

/*Hash_funcs.c */

// 入力引数             key :  キー
//                  m od :  除数
// 戻り値              hv :   ハッシュ値
int hash(int key, int mod){   // 剰余法
  int hv;                   // 剰余
  hv = key % mod;               // 剰余をhash値とする
  return hv;
}



//  入力値 :       adrs     (当該)バケット番号
//               size    hash表の大きさ
//               cons     定数(増分)
//  戻り値 :       adrs     バケット番号
int prob_lin(int size, int cons, int adrs){ // 線形探査関数
  cons = 2999;
  adrs += cons;
  if (size <= adrs)               // アドレスが番地空間を越えた
    adrs -= size;
  return adrs;
};

コード:

/* Hash_main.c */

#define HSIZE 1000000 // ハッシュ表の大きさ(100万)
#define DVS 999983 // 除数(HSIZEを超えない最大の素数)
#define CONSL 19 // 線形探査法の定数

#define CONSR1 99989 // HSIZE / 2 < 二重分散法1の定数
#define CONSR2 199999 // 二重分散法2の定数 < 2 * HSIZE

#include "hash_open.h" // 開放番地法

#include "utilities.c" // ユーティリティ関数
#include "Hash_message.c" // メッセージ出力関数
#define NARG 2 // コマンドライン引数
#define FMTF "%d\n" // ファイル入力
#define NFL3

int COUNT;

int main(void) {
  FILE *fin ;
  int cmdnum , // コマンド番号
      rc , // 関数の戻り値
      i = 0 ,
      inv , // 入力値(集合の要素)
      oun = HSIZE / 10 ; // 処理レコード数出力単位
      double microsec;
      clock_t start, end;
      float o = 0.0;

  fin =open_file("integer1MR.dat", "r" ) ; // 入力ファイル(整数の集合)

  Htable = allocate_Htable(HSIZE) ; // ハッシュ表の動的割付け
  init_tbl(Htable, HSIZE) ; // ハッシュ表初期化


    printf("要素数   占有率    総探査回数  格納時間(秒)\n");
    while (fscanf(fin, FMTF, &inv) != EOF) { // キーの読込み
    start = clock();
    STORE ; // キーの格納
    end = clock();
    microsec = (double)(end - start) / CLOCKS_PER_SEC;
    if (rc == FLS) printf( "%d は格納できません\n" , inv);
    if (++i % oun == 0) {   
    o = i / 1000000;
       printf(" %d   %f      %d         %f      \n", i, o, COUNT, microsec);
     }
  }


  return 0;
}

コード:

/*Hash_open.c*/

extern int COUNT;

//   *table : hash表
//    size :  hash表の大きさ
void init_tbl(CELL *Htable, int hsize){  //ハッシュ表を初期化
  int i;
  for(i = 0; i < hsize; i++) {
    Htable[i].key = INTV ;
  }
  return ;
}

コード:

//   入力値 :        *table      hash表
//                  size      hash表の大きさ
//                  cons       除数
//                  inv        入 力値
//   戻り値 :                    バケット番号、-1(無い場合)
int store(CELL *table, int size, int cons, int inv) {
  int adr ,                               // hash表の番地
    i=1;                               // 探査回数
  COUNT++;                               // 総探査回数
  adr = hash(inv, cons) ;                  // hash値を計算
  while(i <= size){
    if (table[adr].key == INTV){          // adrsi番地は空いている
      COUNT++;
      table[adr].key = inv;        // adrs番地に格納
      return adr;
    }
    else if (table[adr].key != INTV){// adrs番地は空いていない
      COUNT++;
      if (table[adr].key == inv)        // 入力値は既格納
	return FLS;
      adr = prob_lin(size, CONSL, adr);      // 線形探査法による次の番地
      ++i;
    }
  }
  return FLS;
}

コード:

/*utilities.c*/

 // 入力引数 fname : ファイル名
// mode : ファイルモード
FILE *open_file(char *fname, char *mode) {
FILE *fp ;
if ((fp = fopen(fname, mode)) == 0) { //ファイルのオープン
printf("%s がオープンできません\n", fname) ;
exit(0) ;
}
return fp ;
}

box
記事: 2002
登録日時: 15年前

Re: 開放番地法でのハッシュ表生成

#7

投稿記事 by box » 14年前

カイト さんが書きました: ポリシーなんてありませんよ。学校で教えられた通りにやっているだけです。
*.c から *.h をインクルードすることはごくふつうの方法です。
ところが、逆は見かけたことがないです。

*.h から *.c をインクルードする方法を教えてくださったかたに、
「それってふつうのやり方ですか?」と確認した方がよいのではないかと思います。

それからもう一つ、インデントをきちんとすることを強くおすすめします。
インデントがきちんとしていないと、
例えばif文やwhile文の中にどの文が属しているかがパッと見てわかりづらい、ということが起きます。
そうすると、どうなるでしょうか。バグの原因になりかねません。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

閉鎖

“C言語何でも質問掲示板” へ戻る