ハッシュ法について
Posted: 2016年1月10日(日) 22:48
ずっと悩んで行き詰まってしまったためどうかお手伝いお願いします。
与えられた値を5で割って出来たその余りをハッシュ値としてハッシュテープルを構成し、それにデータを1.追加、2.削除、3.データの検索、4.ハッシュテーブルの全表示、を行える機能を持ったプログラムを作りたいのですがデータの追加、削除を行う関数がどうしてもわかりません。
またデータの検索を行った後に再度検索したり、またはハッシュテーブルの全表示を行った後に再度全表示を行うなど2回操作をするとセグメントエラーが起きてしまします。多分 (*table)=(*table)->next;が原因で起こっているのだとは思いますが他にどのように書けばいいのかわかりません。
長文になりましたがどうかご教授お願いします。
与えられた値を5で割って出来たその余りをハッシュ値としてハッシュテープルを構成し、それにデータを1.追加、2.削除、3.データの検索、4.ハッシュテーブルの全表示、を行える機能を持ったプログラムを作りたいのですがデータの追加、削除を行う関数がどうしてもわかりません。
またデータの検索を行った後に再度検索したり、またはハッシュテーブルの全表示を行った後に再度全表示を行うなど2回操作をするとセグメントエラーが起きてしまします。多分 (*table)=(*table)->next;が原因で起こっているのだとは思いますが他にどのように書けばいいのかわかりません。
長文になりましたがどうかご教授お願いします。
/*初期のハッシュテーブル
0: 25->15
1: 31->21
2: 7->12->22
3: 18
4: 4->9
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MOD 5 /* 除数y=5 */
struct node{
int key;
struct node *next;
};
struct queue{
struct node *top,*rear;
};
typedef enum{
Quit,Insert,Delete,Print,Search
}Menu;
/* メニュー選択 */
Menu selectmenu(void)
{
int ch;
do{
printf("\n(1)ハッシュに新規データを追加\n(2)ハッシュのデータを削除\n");
printf("(3)ハッシュテーブルの表示\n(4)ハッシュテーブルから検索\n");
printf("(0)処理終了\n");
printf("メニューを指定してください。:"); scanf("%d",&ch);
}while(ch<Quit||ch>Search);
return (Menu)ch;
}
/* ハッシュテーブルから探索 */
struct node *member(struct node **table, int key){
int i=0,j=0;
j=key%MOD;
if(j<0||4<j)goto FAILURE;
for(i=0;i<j;i++)(*table)=(*table++);
while(1){
(*table)=(*table)->next; /* ここが原因 */
if(key==(*table)->key)goto SUCCESS;
if((*table)->next==NULL)goto FAILURE;
}
SUCCESS: return (*table);
FAILURE: return NULL;
}
/*リストに先頭からノードを挿入 */
void enqueue(struct node **table,struct queue *q,int key2,int *rear){
struct queue q2;
if(*rear==0){
q->top=(struct node*)malloc(sizeof(struct queue));
(*table)=(struct node*)malloc(sizeof(struct node)); //メモリの開放
(*table)->next=q->top;
q->top->key=key2;
q->top->next=NULL;
q->rear=q->top;
}else{
q2.top=(struct node*)malloc(sizeof(struct queue)); //メモリの開放
q2.top->key=key2;
q2.top->next=NULL;
(*table)->next=q2.top;
q2.top->next=q->rear; //rearの指すとこの変更
q->rear = q2.top;
}
(*rear)++;
}
/* ハッシュに新規データを追加 */
int insert(struct node **table, int key){
int surplus;
struct node *node;
node=member(table,key);
if(node!=NULL)return 0;
else{
surplus=key%MOD;
// enqueue(&table[surplus],&q[surplus],key,&rear[surplus]);
}
return key;
}
/* ハッシュのデータを削除 */
int delete(struct node **table, int key){
int surplus;
struct node *node;
node=member(table,key);
if(node==NULL)return 0;
else{
surplus=key%MOD;
// dequeue(&table[surplus],&q[surplus],key,&rear[surplus]);
}
return key;
}
/* ハッシュテーブルの表示 */
void print_hash(struct node **table){
int i=0,j=0;
printf("\nハッシュテーブルを表示します。\n");
for(i=0;i<5;i++){
printf("%d: ",i);
while(1){
(*table)=(*table)->next; /* ここが原因 */
printf("%d",(*table)->key);
if((*table)->next==NULL)break;
printf("->");
}
printf("\n");
(*table)=(*table++);
j++;
}
for(i=0;i<5;i++)(*table)=(*table--);
printf("\n\n");
}
int main(){
struct node *table[5]={NULL,NULL,NULL,NULL,NULL}; /* table->key=NULL */
int rear[5]={0,0,0,0,0};
int x[10]={18,9,22,4,21,12,15,31,7,25}; /* 変数宣言 */
int i,j,tmp,surplus,search,value;
struct queue q[5];
struct node *tmpnode;
Menu menu;
for(j=0;j!=10;j++){
surplus=x[j]%MOD;
enqueue(&table[surplus],&q[surplus],x[j],&rear[surplus]); /* 初期値からハッシュテーブルの作成 */
}
do{
switch (menu = selectmenu()){
case Insert:;
printf("ハッシュに追加する値を入力して下さい。\n");
scanf("%d",&value);
tmp=insert(table,value);
if(tmp != 0)printf("\n\n%dをハッシュに追加しました。\n\n",tmp);
else printf("\n\n既に同じデータがハッシュに含まれています。\n\n");
break;
case Delete:;
printf("ハッシュから削除する値を入力して下さい。\n");
scanf("%d",&value);
tmp=delete(table,value);
if(tmp != 0)printf("\n\n%dをハッシュから削除しました。\n\n",tmp);
else printf("\n\n指定したデータがハッシュに含まれていません。\n\n");
break;
case Print:;
print_hash(table);
break;
case Search:;
printf("探索する値を入力して下さい。\n");
scanf("%d",&value);
tmpnode=member(table,value);
if(tmpnode != NULL)printf("\n\n%dは見付かりました。\n\n",tmpnode->key);
else printf("\n\n%dは見付かりませんでした。\n\n",value);
break;
}
}while(menu != Quit);
for(i=0;i<5;i++)free(table[i]);
return 0;
}