ページ 11

ヒープのデータの挿入

Posted: 2011年9月05日(月) 22:23
by drow
大学で勉強した課題を復習して、わからない問題があったのでおしえてください
windows7を使っています。

ヒープに新たなデータを挿入する関数insertを作成する課題で、
空の配列に複数回insertを行うことで構成したヒープがヒープ条件を満たしていることを
確認する問題です。
わからない所は、
insert(100,s,&MAX); にすると  lvalue required as unary '&' operand というエラーが出て、どう直せばいいのかわからないこと
a[MAX] = val; で、array subscript is not an integer というエラーが出ることです。a[MAX]に値が入ってないからってエラーが出る意味がわかりません。
回答よろしくおねがいします

コード:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define MAX 11
int check_heap(int a[],int N);
void insert(int val,int a[],int *);
int main(){
  FILE *fp;
  int i,j,temp,num;
  int s[MAX];
  
//ファイル読み込み
  if( (fp=fopen("numbers.dat","r")) == NULL){
    printf("file open errpr!\n");
    exit(0);
  }

  for(i=0;i<10; i++){
  fscanf(fp,"%d",&s[i]);
  }
  
  if(1 == check_heap(s,MAX))
    printf("correct!\n");
  else
    printf("difference!\n");

  printf("--------------\n");
  //sort
  for(i=0; i<MAX; i++){
    j=i;
    for(j=i; j< MAX;j++){
      if(s[i] > s[j+1]){
        temp = s[i];
        s[i] = s[j+1];
        s[j+1] = temp;
      }
    }
  }
  //check
  if(1 == check_heap(s,MAX))
    printf("correct!\n");
  else
    printf("difference!\n");
  //表示
  for(i=0;i<MAX; i++){
    printf("%d  ",s[i]);
  }
  //---------------------------
  //100を追加
   insert(100,s,&MAX); //*********************************************

  //check
  if(1 == check_heap(s,MAX))
    printf("correct!\n");
  else
    printf("difference!\n");
  //表示
  for(i=0;i<10; i++){
    printf("%d  ",s[i]);
  }
  return 0;
}

int check_heap(int a[],int N){
  int i;
  for(i=0;i<N; i++){
    if(a[i] > a[2*(i+1)] && a[i] > a[2*(i+2)] )
      return 0;
  }
  return 1;
}

void insert(int val,int a[],int *N){
  int i,temp;
  N++;
  a[MAX] = val; //***********************************
  i = 0;
  while((i-1)/2 <=0){
    if(a[i] < a[(i-1)/2]){
      temp = a[i];
      a[i] = a[(i-1)/2];
      a[(i-1)/2] = temp;
      i = (i-1)/2;//shift up
  }
    else
      break;
 }

}

<エラーコード>
# gcc 3-10.c
3-10.c: In function 'main':
3-10.c:51:4: error: lvalue required as unary '&' operand
3-10.c: In function 'insert':
3-10.c:77:4: error: array subscript is not an integer

Re: ヒープのデータの挿入

Posted: 2011年9月05日(月) 22:56
by box
とりあえず最初のエラーだけ。
drow さんが書きました: insert(100,s,&MAX);
これは、
insert(100,s,&11);
と書いているのと同じことです。
11は変数名でありませんので、&を適用することはできません。

Re: ヒープのデータの挿入

Posted: 2011年9月05日(月) 23:20
by non
2つめのエラーは
int s[MAX];の宣言は
int s[11];のことなので、確保されるのは s[0]からs[10]までです。
それなのに77行で
a[MAX] = val;
つまり、s[11]に代入しているので、配列の範囲外です。
>3-10.c:77:4: error: array subscript is not an integer
なぜ、このエラーなのかというと、a[11]はないのですが、その場所(アドレス)が何か別の変数に
割り当てられていて、それがintegerではないということなのではないでしょうか。

Re: ヒープのデータの挿入

Posted: 2011年9月05日(月) 23:25
by box
drow さんが書きました:

コード:

#define MAX 11
  int s[MAX];
このように定義した配列で、アクセスできる領域は
s[0]~s[MAX-1]
です。
drow さんが書きました:

コード:

  a[MAX] = val; //***********************************
ここで何をしたいのかよくわかりませんが、いずれにしても、
この文では配列の定義範囲外の領域にアクセスしようとしています。
後の方のエラーと直接関係があるかどうかはよくわかりませんが…。

Re: ヒープのデータの挿入

Posted: 2011年9月05日(月) 23:36
by box
drow さんが書きました:

コード:

void insert(int val,int a[],int *N){
  N++;
ポインターである N を1つ進める、というのは、どういった意味を持つのでしょうか。
当該の2個のエラーと関係があるかどうかはよくわかりませんが…。

Re: ヒープのデータの挿入

Posted: 2011年9月06日(火) 12:33
by drow
かなり書き換えて見ました。
insert_heapだけでなくcheck_heapもできてないことがわかりました。代入する数字をいろいろ変えてみるとわかるとおもいます。
ヒープ条件を満たしているかの確認をするinsert_heapとヒープ条件を満たすように追加するcheck_heapが問題なく機能するようにしたいので
教えてください。

コード:

#include<stdio.h>
#include<stdlib.h>
#define mMAX 11

//ぷろとたいぷ宣言
void check_insert(int val,int a[],int* N);
int check_heap(int* a,int N);
void swap(int* a,int* b);
//グローバル関数
int s[mMAX];

int main(void){

int MAX= 1;

 s[0]='\0';
 int a,i,k;

 printf("数字を入力してください\n");
 for(i=1;i<6;i++){
   scanf("%d",&a);
   check_insert(a,s,&MAX);
 }

//ヒープ条件が成立しているか確認
printf("確認(0なら満たしていない、1なら満たしている)する\n");
printf("HEAP_CHECK = %d\n", check_heap(s,MAX) );
//ヒープ領域の内容表示

printf("HEAP = [");
for(i = 1;i <= MAX-1; i++)
  printf("%d  ",s[i]);
printf("]\n");  
return 0;
}

void check_insert(int val,int a[],int* N){
  int parents=0,temp;
  int x;
  parents = *N/2;
  a[*N] = val;
  if(*N != 1){
 while(a[parents] > a[* N]){   
   temp = a[parents];
   a[parents] = a[*N];
   a[*N] = a[parents];
   // swap(a[parents], a[*N]);

 }
 
  }
  *N =*N+1;
}

int check_heap(int *a,int N){
  int i;
  for(i=1; i<N; i++){
    if(i*2<=N){
      if(a[i*2]< a[i] || a[i*2+1]<a[i])
	return 0;
    }
  }
  return 1;
}
//配列の交換
void swap(int* a,int *b){
  int temp;
  temp = *a;
  *a = *b;
  *s = temp;
}
『実行例1」
1
2
3
4
5
確認(0なら満たしていない、1なら満たしている)する
HEAP_CHECK = 0
HEAP = [1 2 3 4 5 ]

『実行例2」
13
5
4
7
88
確認(0なら満たしていない、1なら満たしている)する
HEAP_CHECK = 0
HEAP = [4 5 4 7 88 ]

Re: ヒープのデータの挿入

Posted: 2011年9月06日(火) 14:52
by non
check_insertとは、何をしたいのでしょうか?仕様を示してください。
1つデータを追加し、追加した親と比べて親の方が小さくなればよいのでしょうか?
ざっと、見た感じでは、そこだけ入れ替えようとしているようにも見えます。
それとも、ヒープソートしますか?

Re: ヒープのデータの挿入

Posted: 2011年9月06日(火) 18:51
by drow
>>>check_insertとは、何をしたいのでしょうか?仕様を示してください。
配列の最後にデータを追加して、
追加したデータ<親のデータ  「親の方が大きいので交換する」  
追加したデータ>親のデータ  「親の方が小さいので交換しない」 そして終了する

>>>1つデータを追加し、追加した親と比べて親の方が小さくなればよいのでしょうか?
小さい数字が親になるようにしています。追加したデータが親と比べて、親の方が大きかったら交換(シフトアップ)していきたいです。

>>>ヒープソートしますか?
ここではヒープソートはしません。
check_heap関数で配列がヒープ条件を満たしているかの真偽を確認できるようにすること、
chdek_insert関数でデータを追加して、必要に応じてシフトアップするなど、ヒープ条件が満たした配列にすること目的にプログラムしてます。

説明不足ですいません。よろしくおねがいします。

Re: ヒープのデータの挿入

Posted: 2011年9月06日(火) 22:00
by box
ところで、インデント(字下げ)の方法について勉強したことはありますか?
何だか読みづらいんですよね、そのコードって。

Re: ヒープのデータの挿入

Posted: 2011年9月06日(火) 22:39
by non
check_insert ですが、46行目が間違ってます。