ページ 11

ダミーノードについて

Posted: 2011年1月19日(水) 15:58
by AZA
下のプログラムでは、ダミーノードというのを使ってあると思うんですが、これを使うことによってどう変わるんでしょうか?
またダミーノードを使わずに同じ結果を出すプログラムを作成しようとしたらどうなるんでしょうか?

コード:

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

struct LIST
{
	int data;           /* 具体的なデータ */
	struct LIST* next;  /* 次の要素へのポインタ */
};
struct LIST head;  /* リストの先頭要素(ダミー) */

/* プロトタイプ宣言 */
void addlist(void);
void deletelist(void);
void showlist(void);


int main(void)
{
	char command;
	
	head.next = NULL;
	
	do
	{
		puts( "コマンドを入力して下さい" );
		puts( "線形リストに要素を追加:a" );
		puts( "線形リストから要素を削除:b" );
		puts( "線形リストの内容を表示:c" );
		puts( "終了:q" );
		scanf( "%c", &command );
		
		switch( command )
		{
		case 'a':   /* 追加 */
			addlist();
			break;
		case 'b':   /* 削除 */
			deletelist();
			break;
		case 'c':   /* 表示 */
			showlist();
			break;
		case 'q':   /* 終了 */
			break;
		default:    /* 無効 */
			puts( "コマンドが正しくありません" );
			break;
		}
		
		puts( "" );
		fflush( stdin );
		
	}while( command != 'q' );
	
	return 0;
}

/* 線形リストに要素を追加する */
void addlist(void)
{
	struct LIST* p, *q, *newcell;
	int data;
	
	puts( "追加する要素の値を入力して下さい" );
	scanf( "%d", &data );

	p = head.next;   /* 先頭要素の次の要素のアドレス */
	q = &head;       /* 先頭要素のアドレス */
	while( p != NULL && data > p->data )
	{
		q = p;         /* 追加位置の直前の要素のnextを後で設定するために、
			              追加位置の直前の要素のアドレスを記憶しておく */
		p = p->next;   /* 次の要素へ進む */
	}
	
	/* 新しく追加する要素のためのメモリ領域を確保する */
	newcell = malloc( sizeof(struct LIST) );
	if( newcell == NULL )
	{
		puts( "メモリ不足" );
		return;
	}
	
	newcell->data = data;  /* 新しい要素のデータを設定 */
	newcell->next = p;     /* 新しい要素の次の要素へのアドレスを設定 */
	q->next = newcell;     /* 新しい要素の直前の要素のnextに、新しい要素のアドレスを設定 */
}

/* 線形リストから要素を削除する */
void deletelist(void)
{
	struct LIST *p, *q;
	int data;
	
	puts( "削除する要素の値を入力して下さい" );
	scanf( "%d", &data );
	
	p = head.next;   /* 先頭要素の次の要素のアドレス */
	q = &head;       /* 先頭要素のアドレス */
	while( p != NULL && p->data != data )
	{
		q = p;         /* 削除位置の直前の要素のnextを後で設定するために、
			              削除位置の直前の要素のアドレスを記憶しておく */
		p = p->next;   /* 次の要素へ進む */
	}
	
	if( p == NULL )  /* 一致する値がないままリストの末尾まで来た */
	{
		puts( "指定された要素はリスト内に存在しません" );
	}
	else
	{
		q->next = p->next;  /* 削除する要素の直前の要素のnextポインタを再設定 */
		free( p );          /* 要素はmallocで確保されているのでfreeで解放する */
	}
}

/* 線形リストの内容を表示する */
void showlist(void)
{
	struct LIST *p;
	
	for( p=head.next; p!=NULL; p=p->next )
	{
		printf( "%d\n", p->data );
	}
}

Re: ダミーノードについて

Posted: 2011年1月19日(水) 17:45
by ISLe
AZA さんが書きました:下のプログラムでは、ダミーノードというのを使ってあると思うんですが、これを使うことによってどう変わるんでしょうか?
またダミーノードを使わずに同じ結果を出すプログラムを作成しようとしたらどうなるんでしょうか?
実際にやってみるのがいちばんです。
9行目の
struct LIST head; /* リストの先頭要素(ダミー) */

struct LIST *head; /* リストの先頭要素(実体)を指すポインタ */
に変えて元と同じ動作をするように変更してみましょう。

動作を変えずにコードを変える作業をリファクタリングと言って本職のプログラマを目指すならとても大切なスキルです。

Re: ダミーノードについて

Posted: 2011年1月21日(金) 14:12
by AZA
なるほど試してみます!