数据结构-串操作应用之词索引表
2016-07-22 20:21
459 查看
[b]为书库创建查询索引表[/b]
建立词索引表基本步骤:
1、从书目文件中读入一个书目单。
2、从书目单中提取所有关键字插入词表。
3、对词表中的每一个关键字在索引表中进行查找并作相应的插入操作。
详细操作:
1、为识别从书名串中分离出来的单词是否是关键字,需要一张常用词表。顺序扫描书目单,首先分离单词,然后查找常用词表,若不和表中任一词相等,则为关键字,插入临时存放关键字的词表中。
2、在索引表中查询关键字时可能出现两种情况:其中一种是索引表上已经有此关键词的索引项,只要在该项中插入书号索引即可;其二是需要在索引表中插入此关键词的索引项,插入应按字典有序原则插入。
3、首先定义存储的数据结构:词表为线性表,只存放一本书的书名中若干个关键字,其数量有限,采用顺序存储结构即可,其中每个词是一个字符串。索引表为有序表,虽是动态生成,在生成过程中需频繁进行插入操作,但考虑索引表主要为查找用,为了提高查找效率,采用顺序存储结构;表中每隔索引项包含两个内容:其一是关键词,因索引表为常驻内存,则考虑节省存储,采用堆分配存储表示的串类型;其二是书号索引,由于书号索引是在索引表生成过程中逐个插入,且不同关键词的书号索引个数不等,甚至可能相差很多,则宜采用链表结构的线性表。
代码实现部分:
ConcordanceList.cpp
HeapString.h
ChainedList.h
建立词索引表基本步骤:
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; }
相关文章推荐
- 每次弹出一个栈的最小元素
- 计算几何中的精确度
- 数据结构实验之二叉树二:遍历二叉树
- 数据结构和算法系列17 图
- PQ树小结
- 数据结构与算法JavaScript - 列表
- 数据结构和算法关系
- 1.17 k阶斐波那契序列的第m项值的函数算法
- SDUT 3343 数据结构实验之二叉树四:还原二叉树
- C++学习之路(3) 常用数据结构与STL
- SDUT 2137 数据结构实验之求二叉树后序遍历和层次遍历
- 【算法和数据结构】平衡查找树之B树
- 归并排序
- 中缀表达式变成后缀表达式
- redis 源码阅读 内部数据结构--字符串
- splay入门题---中位数
- hdu1016_Prime_Ring_Problem(经典dfs)
- 数据结构与算法简记:按层次顺序遍历和存储二叉树
- LibreOffice源码开发_重要数据结构
- 数据结构实验之数组三:快速转置