1. 程式人生 > >資料結構------建立一個詞索引表

資料結構------建立一個詞索引表

最近複習資料結構與演算法,就把《資料結構(C語言版)》(清華大學,嚴蔚敏)拿出來看,在串的那一章的最後有一個程式設計題--------建立一個詞索引表,寫了一下,程式碼如下。、

檔案1:define.h

內容:各種資料型別的定義

//////////////////////////////////////////////////
//
//   資料型別的定義
//
////////////////////////////////////////////////
////////////////

#define MaxBookNum 1000   // 假設只對1000本書建立索引表
#define MaxKeyNum  2500   // 索引表的最大容量
#define MaxLineNum 500    // 書目串的最大長度
#define MaxWordNum 10     // 詞表的最大容量

// 書目型別的定義
typedef struct Book 
{
	char id[10] ;   // 書號
	char name[MaxLineNum] ; // 書名  
} Book ;

//書目表的定義
typedef struct BookList
{
	Book book[MaxBookNum] ;     // 儲存書目的表
	int  number ;               // 書目數量
}BookList ;

// 關鍵字索引對應的書目id
typedef struct IdIndex
{
	char id[10] ;
	struct IdIndex * next ;
} IdIndex ;

// 索引型別定義
typedef struct BookIndex
{
	char index[50] ;
	IdIndex * head ;
} BookIndex ;


// 索引表
typedef struct BookIndexList
{
	BookIndex bookindex[MaxKeyNum] ;  // 索引項儲存資訊
	int number ;                      // 索引項的書目
} BookIndexList ;
	

// 詞表
typedef struct WordList 
{
	char Word[MaxWordNum][20] ;
	int number ;
} WordList ;

// 關鍵字表
typedef struct KeyWordList
{
	char keyword[20][20] ;
	int number ; 
} KeyWord ;
	


檔案2:implenment.cpp

內容:各種函式的定義

/////////////////////////////////////////////////
//
//   實現主要函式
//
///////////////////////////////////////////////////
////////////

#include "define.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>


// 從檔案中讀入詞表資訊
void GetWordInfo( WordList * wordlist )
{
	int i = 0 ;
	char str[1000] ;

	// 開啟檔案
	FILE * pf = fopen("word.txt","r+") ;
	if( pf == NULL )
	{
		printf("開啟檔案word.txt失敗!\n") ;
		exit(0) ;
	}

	// 讀取檔案中的內容
	while( feof(pf) != EOF )
	{
		if( fgets( str , 1000 , pf ) )
		{
			strcpy( wordlist->Word[i] , str ) ;

			if( wordlist->Word[i][strlen(wordlist->Word[i])-1] == '\n' )
			{
				wordlist->Word[i][strlen(wordlist->Word[i])-1] = '\0' ;   // 去掉每個詞最後的換行符
			}
			i++ ;
		}
		else
		{
			break ;
		}
	}
	wordlist->number = i ;    // 詞表的長度
}

// 從檔案中讀入書目串
void GetBookInfo( BookList * booklist )
{
	int i = 0 ;
	int j = 0 ;
	int count = 0 ;
	int k = 0 ;
	char str[1000] = { '\0' } ;

	// 開啟檔案
	FILE * pf = fopen( "bookinfo.txt" , "r+" ) ;
	if( pf == NULL )
	{
		printf("開啟檔案失敗!\n") ;
		exit(0) ;
	}

	// 讀取檔案中的內容
	while( feof( pf ) != EOF )
	{
		if( fgets( str , 1000 , pf ) )
		{
			if( str[strlen(str)-1] == '\n' )
			{
				str[strlen(str)-1] = '\0' ;   // 去掉讀取的一條書目字串最後的一個換行符
			}

			while( str[j] != ' ' )
			{
				booklist->book[i].id[j] = str[j] ;
				j++ ;
			}
			booklist->book[i].id[j] = '\0' ;
			count = j + 1 ;

			while( str[count] != '\0' )
			{
				booklist->book[i].name[k++] = str[count++] ;
			}
			booklist->book[i].name[k] = '\0' ;

			i++ ;
			j = 0 ;
			k = 0 ;
			strcpy( str , "" ) ;
		}
		else
		{
			break ;
		}
	}
	booklist->number = i ;  // 書目的數量
}

// 系統初始化
void InitSystem( BookList * booklist , WordList * wordlist )
{
	// 從檔案bookinfo.txt中讀取書目資訊
    GetBookInfo( booklist ) ;

	// 從檔案word.txt中讀取詞表資訊
	GetWordInfo( wordlist ) ;

	printf("書目資訊:\n") ;

	for( int i = 0 ; i < booklist->number ; i++ )
	{
		printf("%s	%s\n", booklist->book[i].id , booklist->book[i].name ) ;
	}

	printf("詞表資訊:\n") ;

	for( i = 0 ; i < wordlist->number ; i++ )
	{
		printf("%s\n" , wordlist->Word[i]) ;
	}
}

// 將一個書目名進行分割
void CutBookName( Book * book , KeyWordList * keywordlist ) 
{
	int i = 0 ;
	int j = 0 ;
	int k = 0 ;

	while( book->name[i] != '\0' )
	{
		if( book->name[i] == ' ' )
		{
			keywordlist->keyword[j][k] = '\0' ;
			k = 0 ;
			j++ ;
			i++ ;
			continue ;
		}
		keywordlist->keyword[j][k++] = book->name[i++] ;
	}
	keywordlist->keyword[j++][k] = '\0' ;
	keywordlist->number = j ;
}

// 判斷一個單詞是否為關鍵字
bool is_Key( char * word , WordList * wordlist )
{
	int i = 0 ;
	for( i = 0 ; i < wordlist->number ; i++ )
	{
		if( strcmp( wordlist->Word[i] , word ) == 0 )
		{
			return false ;
		}
	}
	return true ;
}

// 將一個書目名按照詞表過濾得到該書目名的關鍵字表
void GetBookKey( KeyWordList * keyword , WordList * wordlist , KeyWordList * lastkeyword )
{
	int i = 0 ;
	lastkeyword->number = 0 ;   // 初始化關鍵字表的書目

	for( i = 0 ; i < keyword->number ; i++ )
	{
		if( is_Key( keyword->keyword[i] , wordlist) )  //  判斷當前字串是否為關鍵字
		{
			strcpy( lastkeyword->keyword[lastkeyword->number++] , keyword->keyword[i] ) ;
		}
	}

	// 輸出一些中間結果
	/*
	printf("某書目關鍵字表:\n") ;
	for( i = 0 ; i < lastkeyword->number ; i++ )
	{
		printf("%s ",lastkeyword->keyword[i] ) ;
	}
	printf("\n") ;
	*/
}

// 判斷索引表中是否存在某個關鍵字
// 若存在,返回該索引項的下標;否則返回-1
int key_is_found( BookIndexList * bookindexlist , char * key )
{
	for( int i = 0 ; i < bookindexlist->number ; i++ )
	{
		if( strcmp( key , bookindexlist->bookindex[i].index ) == 0 )
		{
			return i ;
		}
	}
	return -1 ;
}

// 初始化索引表
void InitBookIndexList( BookIndexList * bookindexlist )
{
	bookindexlist->number = 0 ;
}


// 將一條書目資訊插入索引表
void HandleOneBookToIndexList( Book * book , KeyWordList * lastkeyword , BookIndexList * bookindexlist , WordList * wordlist )
{
	KeyWordList keywordlist ;

	CutBookName( book , &keywordlist ) ;      // 將書目資訊進行分詞
	GetBookKey( &keywordlist , wordlist , lastkeyword ) ;   // 將分詞得到的單詞進行過濾得到該書目的關鍵字

	for( int i = 0 ; i < lastkeyword->number ; i++ )
	{
		int pos = key_is_found( bookindexlist , lastkeyword->keyword[i] ) ;
		if( pos >= 0 )   // 該關鍵字在索引表中存在
		{
			IdIndex * idindex = (IdIndex*)malloc(sizeof(IdIndex)) ;
			if( !idindex )
			{
				printf("申請記憶體失敗!\n") ;
				exit(0) ;
			}
			idindex->next = NULL ;
			strcpy( idindex->id , book->id ) ;

			IdIndex * tmp = bookindexlist->bookindex[pos].head->next ;
			bookindexlist->bookindex[pos].head->next = idindex ;
			idindex->next = tmp ;
		}
		else
		{
			// 初始化該關鍵字的索引列表
			bookindexlist->bookindex[bookindexlist->number].head = ( IdIndex *)malloc(sizeof(IdIndex)) ;
			if( !bookindexlist->bookindex[bookindexlist->number].head )
			{
				printf("申請記憶體失敗!") ;
				exit(0) ;
			}
			bookindexlist->bookindex[bookindexlist->number].head->next = NULL ;

			IdIndex * idindex2 = (IdIndex*)malloc(sizeof(IdIndex)) ;
			if( !idindex2 )
			{
				printf("申請記憶體失敗!\n") ;
				exit(0) ;
			}
			idindex2->next = NULL ;

			strcpy( idindex2->id , book->id ) ;
			strcpy( bookindexlist->bookindex[bookindexlist->number].index , lastkeyword->keyword[i] ) ;

			bookindexlist->bookindex[bookindexlist->number].head->next = idindex2 ;  // 第一次插入
			bookindexlist->number++ ;
		}
	}
}

// 將兩個索引項交換位置
void SwapIndexItem( BookIndex * bookindex1 , BookIndex * bookindex2 )
{
	BookIndex  tmp ;
	tmp = *bookindex1 ;
	*bookindex1 = *bookindex2 ;
	*bookindex2 = tmp ;
}

// 將詞索引表中的索引項的關鍵字中的首字母大寫變為小寫
void exchange( BookIndexList * bookindexlist )
{
	for( int i = 0 ; i < bookindexlist->number ; i++ )
	{
		if( bookindexlist->bookindex[i].index[0] <= 'Z' )
		{
			bookindexlist->bookindex[i].index[0] = char( int(bookindexlist->bookindex[i].index[0] ) + 32 ) ;
		}
	}
}


// 將生成的詞索引表按照字典序進行排序
void SortByKey( BookIndexList * bookindexlist )
{
	int k = 0 ;
	for( int i = 0 ; i < bookindexlist->number - 1 ; i++ )
	{
		for( int j = i + 1 ; j < bookindexlist->number ; j++ )
		{
			k = 0 ;  // 初始化
			while( 1 )
			{
				if( bookindexlist->bookindex[i].index[k] > bookindexlist->bookindex[j].index[k] )
				{
					SwapIndexItem( &bookindexlist->bookindex[i] , &bookindexlist->bookindex[j] ) ;
					break ;
				}
				else if( bookindexlist->bookindex[i].index[k] == bookindexlist->bookindex[j].index[k] )
				{
					k++ ;
				}
				else
				{
					break ;
				}
			}
		}
	}
}


// 建立詞索引表
void CreateIndexList( BookList * booklist , KeyWordList * lastkeyword , BookIndexList * bookindexlist , WordList * wordlist )
{
	// 遍歷每一個索引項
	for( int i = 0 ; i < booklist->number ; i++ )
	{
		HandleOneBookToIndexList( &booklist->book[i] , lastkeyword , bookindexlist , wordlist ) ;
	}

    // 將索引項中的關鍵字的首字母大寫變為小寫
	exchange( bookindexlist ) ;

	// 根據索引項關鍵字的首字母進行排序
	SortByKey( bookindexlist ) ;

	printf("生成的詞索引表:\n") ;
	for( i = 0 ; i < bookindexlist->number ; i++ )
	{
		printf("%s	" , bookindexlist->bookindex[i].index ) ;

		IdIndex * p  = bookindexlist->bookindex[i].head->next ;

		while( p != NULL )
		{
			printf("%s " , p->id ) ;
			p = p->next ;
		}
		printf("\n") ;
	}
}

檔案3:test.cpp

內容:測試

#include "define.h"

void InitSystem( BookList * booklist , WordList *wordlist ) ;

void InitBookIndexList( BookIndexList * bookindexlist ) ;

void CreateIndexList( BookList * bookist , KeyWordList * lastkeyword , BookIndexList * bookindexlist, WordList * wordlist ) ;

int main()
{
	BookList booklist ;
	WordList wordlist ;

	KeyWordList lastkeyword ;

	BookIndexList bookindexlist ;  // 詞索引表

	InitSystem( &booklist , &wordlist ) ;   // 初始化系統

	InitBookIndexList( &bookindexlist ) ;   // 初始化詞索引表

	CreateIndexList( &booklist , &lastkeyword , &bookindexlist , &wordlist ) ;  // 建立詞索引表

	return 0 ;
}


兩個文字檔案,讀寫資料:

bookinfo.txt

word.txt


執行結果截圖: