您的位置:首页 > 理论基础 > 数据结构算法

数据结构-串操作应用之词索引表

2016-07-22 20:21 459 查看
[b]为书库创建查询索引表[/b]

建立词索引表基本步骤:

  1、从书目文件中读入一个书目单。

  2、从书目单中提取所有关键字插入词表。

  3、对词表中的每一个关键字在索引表中进行查找并作相应的插入操作。

详细操作:

  1、为识别从书名串中分离出来的单词是否是关键字,需要一张常用词表。顺序扫描书目单,首先分离单词,然后查找常用词表,若不和表中任一词相等,则为关键字,插入临时存放关键字的词表中。

  2、在索引表中查询关键字时可能出现两种情况:其中一种是索引表上已经有此关键词的索引项,只要在该项中插入书号索引即可;其二是需要在索引表中插入此关键词的索引项,插入应按字典有序原则插入。

  3、首先定义存储的数据结构:词表为线性表,只存放一本书的书名中若干个关键字,其数量有限,采用顺序存储结构即可,其中每个词是一个字符串。索引表为有序表,虽是动态生成,在生成过程中需频繁进行插入操作,但考虑索引表主要为查找用,为了提高查找效率,采用顺序存储结构;表中每隔索引项包含两个内容:其一是关键词,因索引表为常驻内存,则考虑节省存储,采用堆分配存储表示的串类型;其二是书号索引,由于书号索引是在索引表生成过程中逐个插入,且不同关键词的书号索引个数不等,甚至可能相差很多,则宜采用链表结构的线性表。

代码实现部分:

ConcordanceList.cpp

#include "ChainedList.h"
#include "HeapString.h"

#include <conio.h>

#define  MaxBookNum      1000    // 假设只对1000本书建索引表
#define  MaxKeyNum       2500    // 索引表的最大容量
#define  MaxLineLen       500    // 书目串的最大长度
#define  MaxWordNum        10    // 词表的最大容量
#define  MaxWordLength     30    // 单词的最大长度

typedef int Boolean;
typedef int Status;

typedef struct {
char    item[MaxWordNum][MaxWordLength];  // 字符串的数组
int     last;        // 词表的长度
} WordListType;          // 词表类型(顺序表)

typedef struct {
HString   key;       // 关键词
LinkList bnolist;   // 存放书号索引的链表
} IdxTermType;           // 索引项类型

typedef struct {
IdxTermType  item[MaxKeyNum+1];
int          last;
} IdxListType;           // 索引表类型(有序表)

//------ 基本操作 ------
void InitIdxList(IdxListType &idxlist);
// 初始化操作,置索引表idxlist为空表,即idxlist.last=0,
// 且在idxlist.item[0]设一空串
void GetLine(FILE *f);
// 从文件f读入一个书目信息到书目串缓冲区buf
Status ExtractKeyWord(char *Buffer, WordListType &w, int &bno);
// 从buf中提取书名关键词到词表wdlist,书号存入bno
Status InsertIdxList(IdxListType &idxlist, ElemType bno);
// 将书号为bno的书名关键词按词典顺序插入索引表idxlist
Status PutText(FILE *g, IdxListType idxlist);
// 将生成的索引表idxlist输出到文件g
void PrintFile(FILE *FileName);

Status InsertIdxList(IdxListType &idxlist, int bno);
// 索引表插入算法
void GetWord(int i, HString &wd);
// 用wd返回词表wdlist中第i个关键词。
int Locate(IdxListType &idxlist, HString wd, Boolean &b);
// 在索引表idxlist中查询是否存在与wd相等的关键词。
// 若存在,则返回其在索引表中的位置,
// 且b取值TRUE;否则返回插入位置,且b取值FALSE
void InsertNewKey(IdxListType &idxlist, int i, HString wd);
// 在索引表idxlist的第i项上插入新关键词wd,
// 并初始化书号索引的链表为空表
Status InsertBook(IdxListType &idxlist, int i, int bno);
// 在索引表idxlist的第i项中插入书号为bno的索引

//------ 主要变量 ------
char          buf[MaxLineLen];   // 书目串缓冲区
WordListType  wdlist;    // 词表
IdxListType   idxlist;   // 索引表

//------ 主函数 ------
int main(int argc, char* argv[]) {
FILE *f,*g;
int BookNo;
if ((f = fopen("BookInfo.txt", "r"))==NULL) {
printf("ERROR in open BookInfo.txt!\n");
exit(1);
}
if ((g = fopen ("BookIdx.txt", "w"))==NULL) {
printf("ERROR in open BookIdx.txt!\n");
exit(1);
}
printf("书目文件:\n");
PrintFile(f);
InitIdxList(idxlist);         // 初始化索引表idxlist为空表
while (!feof (f)) {
GetLine (f);                // 从文件f读入一个书目信息到buf
ExtractKeyWord(buf,wdlist,BookNo);
// 从buf提取关键词到词表,书号存入BookNo
InsertIdxList(idxlist, BookNo);  // 书号为BookNo的关键词插入索引表
}
PutText(g, idxlist);          // 将生成的索引表idxlist输出到文件g
fclose(f);
fclose(g);
printf("对书目文件进行处理后的索引文件:\n");
if ((g = fopen ("Algo0409BookIdx.txt", "r"))==NULL) {
printf("ERROR in open BookIdx.txt!\n");
exit(1);
}
PrintFile(g);
fclose(g);
printf("按任意键,结束 ......\n");
getch();
return 0;
} // main

Status InsertIdxList(IdxListType &idxlist,  int bno) {
int i,j;
HString wd;
Boolean b;
for (i=0;  i<wdlist.last;  i++) {
GetWord(i, wd);
j = Locate(idxlist, wd, b);
if (!b)
InsertNewKey(idxlist, j, wd);  //  插入新的索引项
InsertBook(idxlist, j, bno);     //  插入书号索引
}
return OK;
} // InsertIdxList

void GetWord(int i,  HString &wd) {
char *p;
p = *(wdlist.item +i);  // 取词表中第i个字符串
StrAssign(wd, p);       // 生成关键字字符串
} // GetWord

int Locate(IdxListType &idxlist, HString wd, Boolean &b) {
int i,m;
for (i = idxlist.last-1;
((m = StrCompare(idxlist.item[i].key, wd)) > 0);  --i);
if (m==0) { // 找到
b = TRUE;
return i;
} else {  // 没找到
b = FALSE;
return i+1;
}
} // Locate

void InsertNewKey(IdxListType &idxlist, int i, HString wd) {
int j;
for (j=idxlist.last-1;  j>=i;  --j)  // 后移索引项
idxlist.item[j+1] = idxlist.item[j];
// 插入新的索引项
StrCopy(idxlist.item[i].key, wd);    // 串赋值
InitList(idxlist.item[i].bnolist);   // 初始化书号索引表为空表
++idxlist.last;
} // InsertNewKey

Status InsertBook(IdxListType &idxlist, int i, int bno) {
Link p;
if (!MakeNode (p, bno))
return OVERFLOW;                   // 分配失败
Append(idxlist.item[i].bnolist, p);  // 插入新的书号索引
return OK;
} // InsertBook

//------ 基本操作 -------
void InitIdxList(IdxListType &idxlist) {
int i;
idxlist.last= 0;
for(i=0; i<MaxKeyNum+1; i++)
InitList(idxlist.item[i].bnolist);
}

Status ExtractKeyWord(char* Buffer,WordListType &w,int &Num) {
int i=0, j=0, k=0;
bool Ignore;
char TempChar[30];
char IgnoreChar[7][10] = { "to","of","the","and","not","or","if" };
w.last=0;
while(*(Buffer+i)!= ' ') { TempChar[i]=*(Buffer+i);  i++; }
i++;
TempChar[i]= '\0';
Num=atoi(TempChar);
while(*(Buffer+i)!='\n' && *(Buffer+i)!='\0') {
// 每个字符串末尾都有作为结束符'\n'
if(*(Buffer+i)!=' ') { // 若非空字符,则把当前字符加入新的字符串中
if(*(Buffer+i)>='A' && *(Buffer+i)<='Z')  // 大写字母转换为小写
*(Buffer+i)-='A'-'a';
w.item[j][k]=*(Buffer+i);
k++;  i++;
} else {               // 如果是空字符,这是则开始另一个字符串
Ignore=false;
w.item[j][k++]='\0';
for (int m=0; m<7; m++)
if(strcmp(w.item[j],IgnoreChar[m])==0)
{ Ignore=true;  break; }
if (!Ignore) { j++;  k=0;  i++;  w.last++; }
else { k=0;  i++; }
}
}
w.item[j][k++]='\0';     // 把最后一个字符串收尾
Ignore=false;
for (int m=0; m<7; m++)
if (strcmp(w.item[j],IgnoreChar[m])==0)
{ Ignore=true;  break; }
if (!Ignore) w.last++;   // 并把最大数加1
return OK;
}

void GetLine(FILE *f) {
fgets(buf, MaxLineLen, f);  // buf是全局数组变量
}

Status PutText(FILE *IdxFile, IdxListType MyIdx) {
int i,j,k;
Link p;
for(i=0; i<MyIdx.last; i++) {
for(j=0; j<MyIdx.item[i].key.length; j++)
putc(*(MyIdx.item[i].key.ch+j ),IdxFile);
putc('\t',IdxFile);
if (MyIdx.item[i].key.length < 8) putc('\t',IdxFile);
p = MyIdx.item[i].bnolist.head;
for (k=0; k<MyIdx.item[i].bnolist.len; k++) {
p = p->next;
fprintf(IdxFile,"%03d",p->data);
putc(' ', IdxFile);
}
putc('\n',IdxFile);
}
return OK;
}

void PrintFile(FILE *FileName) {  // 辅助函数
char ch;
rewind(FileName);
ch=getc(FileName);
while (ch!=EOF) {
putchar(ch);
ch=getc(FileName);
}
printf("\n");
rewind(FileName);
}


HeapString.h

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

typedef int Status;
#define OK 1
#define ERROR 0
#define OVERFLOW -2

typedef struct{
char *ch;    //若是非空串,则按串长度分配存储区域,否则ch为NULL
int length;    //串的长度
}HString;

/*生成一个其值等于等于串常量chars的串T*/
Status StrAssign(HString &T, char *chars){
if(T.ch)
free(T.ch);    //若串存储空间不为NULl 释放原有空间
int i = strlen(chars);    //获取chars长度
if(!i){
T.ch = NULL;    //串常量chars长度为0时串为空串长度0存储区间指向NULL
T.length = 0;
}
else{
T.ch = (char *)malloc(i * sizeof(char));    //申请空间
if(!T.ch)
exit(OVERFLOW);
for(int j = 0; j < i; j++)
T.ch[j] = chars[j];        //写入chars串
T.length = i;
}
return OK;
}

/*由串S复制得到T*/
Status StrCopy(HString &T, HString S){
if(T.ch)
free(T.ch);
T.ch = (char*)malloc(S.length * sizeof(char));
if(!T.ch)
exit(OVERFLOW);
for(int j = 0; j < S.length; j++)
T.ch[j] = S.ch[j];
T.length = S.length;
return OK;
}
/*若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0*/
int StrCompare(HString T, HString S){
for(int i = 0; i < S.length && i < T.length; i++)
if(S.ch[i] != T.ch[i])
return S.ch[i] - T.ch[i];
return S.length - T.length;
}


ChainedList.h

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

#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define TRUE 1
#define FALSE 0

typedef int Status;
typedef int ElemType;

typedef struct LNode{
ElemType data;
struct LNode *next;
}*Link, *Position;
typedef struct{
Link head, tail;
int len;
}LinkList;

Status InitList(LinkList &L){
L.head = (Link)malloc(sizeof(LNode));
if(!L.head)
exit(OVERFLOW);
L.tail = L.head;
L.len = 0;
L.head->next = NULL;
return 0;
}

Status MakeNode(Link &p,ElemType e){
p = (Link)malloc(sizeof(LNode));
if(!p)
exit(OVERFLOW);
p->data = e;
p->next = NULL;
return OK;
}

Status Append(LinkList &L, Link S){
Link p;
L.tail->next = S;
p = S;
++L.len;
while(p->next){
p = p->next;
++L.len;
}
L.tail = p;
return OK;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: