數據結構-串操作應用之詞索引表


為書庫創建查詢索引表

建立詞索引表基本步驟:

  1、從書目文件中讀入一個書目單。

  2、從書目單中提取所有關鍵字插入詞表。

  3、對詞表中的每一個關鍵字在索引表中進行查找並作相應的插入操作。

詳細操作:

  1、為識別從書名串中分離出來的單詞是否是關鍵字,需要一張常用詞表。順序掃描書目單,首先分離單詞,然后查找常用詞表,若不和表中任一詞相等,則為關鍵字,插入臨時存放關鍵字的詞表中。

  2、在索引表中查詢關鍵字時可能出現兩種情況:其中一種是索引表上已經有此關鍵詞的索引項,只要在該項中插入書號索引即可;其二是需要在索引表中插入此關鍵詞的索引項,插入應按字典有序原則插入。

  3、首先定義存儲的數據結構:詞表為線性表,只存放一本書的書名中若干個關鍵字,其數量有限,采用順序存儲結構即可,其中每個詞是一個字符串。索引表為有序表,雖是動態生成,在生成過程中需頻繁進行插入操作,但考慮索引表主要為查找用,為了提高查找效率,采用順序存儲結構;表中每隔索引項包含兩個內容:其一是關鍵詞,因索引表為常駐內存,則考慮節省存儲,采用堆分配存儲表示的串類型;其二是書號索引,由於書號索引是在索引表生成過程中逐個插入,且不同關鍵詞的書號索引個數不等,甚至可能相差很多,則宜采用鏈表結構的線性表。

代碼實現部分:

ConcordanceList.cpp

  1 #include "ChainedList.h"
  2 #include "HeapString.h"
  3 
  4 #include <conio.h>
  5 
  6 #define  MaxBookNum      1000    // 假設只對1000本書建索引表
  7 #define  MaxKeyNum       2500    // 索引表的最大容量
  8 #define  MaxLineLen       500    // 書目串的最大長度
  9 #define  MaxWordNum        10    // 詞表的最大容量
 10 #define  MaxWordLength     30    // 單詞的最大長度
 11 
 12 typedef int Boolean;
 13 typedef int Status;
 14 
 15 typedef struct {
 16     char    item[MaxWordNum][MaxWordLength];  // 字符串的數組
 17     int     last;        // 詞表的長度
 18 } WordListType;          // 詞表類型(順序表)
 19 
 20 typedef struct {
 21     HString   key;       // 關鍵詞
 22     LinkList bnolist;   // 存放書號索引的鏈表
 23 } IdxTermType;           // 索引項類型
 24 
 25 typedef struct {
 26     IdxTermType  item[MaxKeyNum+1];
 27     int          last;
 28 } IdxListType;           // 索引表類型(有序表)
 29 
 30 //------ 基本操作 ------
 31 void InitIdxList(IdxListType &idxlist);
 32    // 初始化操作,置索引表idxlist為空表,即idxlist.last=0,
 33    // 且在idxlist.item[0]設一空串
 34 void GetLine(FILE *f);
 35    // 從文件f讀入一個書目信息到書目串緩沖區buf
 36 Status ExtractKeyWord(char *Buffer, WordListType &w, int &bno);
 37    // 從buf中提取書名關鍵詞到詞表wdlist,書號存入bno
 38 Status InsertIdxList(IdxListType &idxlist, ElemType bno);  
 39    // 將書號為bno的書名關鍵詞按詞典順序插入索引表idxlist
 40 Status PutText(FILE *g, IdxListType idxlist);           
 41    // 將生成的索引表idxlist輸出到文件g
 42 void PrintFile(FILE *FileName);
 43 
 44 Status InsertIdxList(IdxListType &idxlist, int bno);
 45    // 索引表插入算法
 46 void GetWord(int i, HString &wd);                
 47    // 用wd返回詞表wdlist中第i個關鍵詞。
 48 int Locate(IdxListType &idxlist, HString wd, Boolean &b);
 49    // 在索引表idxlist中查詢是否存在與wd相等的關鍵詞。
 50    // 若存在,則返回其在索引表中的位置,
 51    // 且b取值TRUE;否則返回插入位置,且b取值FALSE
 52 void InsertNewKey(IdxListType &idxlist, int i, HString wd);
 53    // 在索引表idxlist的第i項上插入新關鍵詞wd,
 54    // 並初始化書號索引的鏈表為空表
 55 Status InsertBook(IdxListType &idxlist, int i, int bno);
 56    // 在索引表idxlist的第i項中插入書號為bno的索引
 57 
 58 //------ 主要變量 ------
 59 char          buf[MaxLineLen];   // 書目串緩沖區
 60 WordListType  wdlist;    // 詞表
 61 IdxListType   idxlist;   // 索引表
 62 
 63 //------ 主函數 ------
 64 int main(int argc, char* argv[]) { 
 65   FILE *f,*g;
 66   int BookNo;
 67   if ((f = fopen("BookInfo.txt", "r"))==NULL) {
 68     printf("ERROR in open BookInfo.txt!\n");
 69     exit(1);
 70   }
 71   if ((g = fopen ("BookIdx.txt", "w"))==NULL) {
 72     printf("ERROR in open BookIdx.txt!\n");
 73     exit(1);
 74   }
 75   printf("書目文件:\n");
 76   PrintFile(f);
 77   InitIdxList(idxlist);         // 初始化索引表idxlist為空表
 78   while (!feof (f)) {
 79     GetLine (f);                // 從文件f讀入一個書目信息到buf
 80     ExtractKeyWord(buf,wdlist,BookNo);  
 81         // 從buf提取關鍵詞到詞表,書號存入BookNo
 82     InsertIdxList(idxlist, BookNo);  // 書號為BookNo的關鍵詞插入索引表
 83   }
 84   PutText(g, idxlist);          // 將生成的索引表idxlist輸出到文件g
 85   fclose(f);
 86   fclose(g);
 87   printf("對書目文件進行處理后的索引文件:\n");
 88   if ((g = fopen ("Algo0409BookIdx.txt", "r"))==NULL) {
 89     printf("ERROR in open BookIdx.txt!\n");
 90     exit(1);
 91   }
 92   PrintFile(g);
 93   fclose(g);
 94   printf("按任意鍵,結束 ......\n");
 95   getch();
 96   return 0;
 97 } // main
 98 
 99 Status InsertIdxList(IdxListType &idxlist,  int bno) { 
100   int i,j;
101   HString wd;
102   Boolean b;
103   for (i=0;  i<wdlist.last;  i++) {
104     GetWord(i, wd);   
105     j = Locate(idxlist, wd, b);
106     if (!b)
107       InsertNewKey(idxlist, j, wd);  //  插入新的索引項
108     InsertBook(idxlist, j, bno);     //  插入書號索引
109   }
110   return OK;
111 } // InsertIdxList
112 
113 void GetWord(int i,  HString &wd) {
114   char *p;
115   p = *(wdlist.item +i);  // 取詞表中第i個字符串
116   StrAssign(wd, p);       // 生成關鍵字字符串
117 } // GetWord
118 
119 int Locate(IdxListType &idxlist, HString wd, Boolean &b) {
120   int i,m;
121   for (i = idxlist.last-1; 
122        ((m = StrCompare(idxlist.item[i].key, wd)) > 0);  --i);
123   if (m==0) { // 找到
124     b = TRUE;
125     return i;  
126   } else {  // 沒找到
127     b = FALSE;
128     return i+1;
129   }         
130 } // Locate
131 
132 void InsertNewKey(IdxListType &idxlist, int i, HString wd) {
133   int j;
134   for (j=idxlist.last-1;  j>=i;  --j)  // 后移索引項
135     idxlist.item[j+1] = idxlist.item[j];
136   // 插入新的索引項
137   StrCopy(idxlist.item[i].key, wd);    // 串賦值
138   InitList(idxlist.item[i].bnolist);   // 初始化書號索引表為空表
139   ++idxlist.last;
140 } // InsertNewKey
141 
142 Status InsertBook(IdxListType &idxlist, int i, int bno) {
143   Link p;
144   if (!MakeNode (p, bno)) 
145     return OVERFLOW;                   // 分配失敗
146   Append(idxlist.item[i].bnolist, p);  // 插入新的書號索引
147   return OK;
148 } // InsertBook
149 
150 //------ 基本操作 -------
151 void InitIdxList(IdxListType &idxlist) {
152   int i;
153   idxlist.last= 0;
154   for(i=0; i<MaxKeyNum+1; i++)
155     InitList(idxlist.item[i].bnolist);
156 }
157 
158 Status ExtractKeyWord(char* Buffer,WordListType &w,int &Num) {
159   int i=0, j=0, k=0;
160   bool Ignore;
161   char TempChar[30];
162   char IgnoreChar[7][10] = { "to","of","the","and","not","or","if" };
163   w.last=0;
164   while(*(Buffer+i)!= ' ') { TempChar[i]=*(Buffer+i);  i++; }
165   i++;
166   TempChar[i]= '\0';
167   Num=atoi(TempChar);
168   while(*(Buffer+i)!='\n' && *(Buffer+i)!='\0') { 
169     // 每個字符串末尾都有作為結束符'\n'
170     if(*(Buffer+i)!=' ') { // 若非空字符,則把當前字符加入新的字符串中
171       if(*(Buffer+i)>='A' && *(Buffer+i)<='Z')  // 大寫字母轉換為小寫
172         *(Buffer+i)-='A'-'a';
173       w.item[j][k]=*(Buffer+i);
174       k++;  i++;
175     } else {               // 如果是空字符,這是則開始另一個字符串
176       Ignore=false;
177       w.item[j][k++]='\0';
178       for (int m=0; m<7; m++)
179         if(strcmp(w.item[j],IgnoreChar[m])==0) 
180           { Ignore=true;  break; }
181       if (!Ignore) { j++;  k=0;  i++;  w.last++; }
182       else { k=0;  i++; }
183     }
184   }
185   w.item[j][k++]='\0';     // 把最后一個字符串收尾
186   Ignore=false;
187   for (int m=0; m<7; m++)
188     if (strcmp(w.item[j],IgnoreChar[m])==0) 
189       { Ignore=true;  break; }
190   if (!Ignore) w.last++;   // 並把最大數加1
191   return OK;
192 }
193 
194 void GetLine(FILE *f) {
195   fgets(buf, MaxLineLen, f);  // buf是全局數組變量
196 }
197 
198 Status PutText(FILE *IdxFile, IdxListType MyIdx) { 
199   int i,j,k;
200   Link p;
201   for(i=0; i<MyIdx.last; i++) {
202     for(j=0; j<MyIdx.item[i].key.length; j++)
203       putc(*(MyIdx.item[i].key.ch+j ),IdxFile);
204     putc('\t',IdxFile);
205     if (MyIdx.item[i].key.length < 8) putc('\t',IdxFile);
206     p = MyIdx.item[i].bnolist.head;
207     for (k=0; k<MyIdx.item[i].bnolist.len; k++) {
208       p = p->next;
209       fprintf(IdxFile,"%03d",p->data);
210       putc(' ', IdxFile);
211     }
212     putc('\n',IdxFile);
213   }
214   return OK;
215 }
216     
217 void PrintFile(FILE *FileName) {  // 輔助函數
218   char ch;
219   rewind(FileName);
220   ch=getc(FileName);
221   while (ch!=EOF) {
222     putchar(ch);
223     ch=getc(FileName);
224   }
225   printf("\n");
226   rewind(FileName);
227 }

HeapString.h

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 
 5 typedef int Status;
 6 #define OK 1
 7 #define ERROR 0
 8 #define OVERFLOW -2
 9 
10 typedef struct{
11     char *ch;    //若是非空串,則按串長度分配存儲區域,否則ch為NULL
12     int length;    //串的長度
13 }HString;
14 
15 /*生成一個其值等於等於串常量chars的串T*/
16 Status StrAssign(HString &T, char *chars){
17     if(T.ch)
18         free(T.ch);    //若串存儲空間不為NULl 釋放原有空間
19     int i = strlen(chars);    //獲取chars長度
20     if(!i){
21         T.ch = NULL;    //串常量chars長度為0時串為空串長度0存儲區間指向NULL
22         T.length = 0;
23     }
24     else{
25         T.ch = (char *)malloc(i * sizeof(char));    //申請空間
26         if(!T.ch)
27             exit(OVERFLOW);
28         for(int j = 0; j < i; j++)
29             T.ch[j] = chars[j];        //寫入chars串
30         T.length = i;
31     }
32     return OK;
33 }
34 
35 /*由串S復制得到T*/
36 Status StrCopy(HString &T, HString S){
37     if(T.ch)
38         free(T.ch);
39     T.ch = (char*)malloc(S.length * sizeof(char));
40     if(!T.ch)
41         exit(OVERFLOW);
42     for(int j = 0; j < S.length; j++)
43         T.ch[j] = S.ch[j];    
44     T.length = S.length;
45     return OK;
46 }
47 /*若S>T,則返回值>0;若S=T,則返回值=0;若S<T,則返回值<0*/
48 int StrCompare(HString T, HString S){
49     for(int i = 0; i < S.length && i < T.length; i++)
50         if(S.ch[i] != T.ch[i])
51             return S.ch[i] - T.ch[i];
52     return S.length - T.length;
53 }

ChainedList.h

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 #define OK 1
 5 #define ERROR 0
 6 #define OVERFLOW -2
 7 #define TRUE 1
 8 #define FALSE 0
 9 
10 typedef int Status;
11 typedef int ElemType;
12 
13 typedef struct LNode{
14     ElemType data;
15     struct LNode *next;
16 }*Link, *Position;
17 typedef struct{
18     Link head, tail;
19     int len;
20 }LinkList;
21 
22 Status InitList(LinkList &L){
23     L.head = (Link)malloc(sizeof(LNode));
24     if(!L.head)
25         exit(OVERFLOW);
26     L.tail = L.head;
27     L.len = 0;
28     L.head->next = NULL;
29     return 0;
30 }
31 
32 Status MakeNode(Link &p,ElemType e){
33     p = (Link)malloc(sizeof(LNode));
34     if(!p)
35         exit(OVERFLOW);
36     p->data = e;
37     p->next = NULL;
38     return OK;
39 }
40 
41 Status Append(LinkList &L, Link S){
42     Link p;
43     L.tail->next = S;
44     p = S;
45     ++L.len;
46     while(p->next){
47         p = p->next;
48         ++L.len;
49     }
50     L.tail = p;
51     return OK;
52 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM