💡 KMP算法、关键词索引

This commit is contained in:
康建伟
2019-10-29 22:03:30 +08:00
parent e526cd8f5b
commit 2fd00636f7
54 changed files with 3760 additions and 26 deletions
+7
View File
@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(KMP SString.h SString.c KMP.h KMP.c KMP-main.c)
# 链接公共库
target_link_libraries(KMP Scanf_lib)
+64
View File
@@ -0,0 +1,64 @@
#include "KMP.h" //**▲04 串**//
// 测试函数,打印字符串
void PrintElem(SString S);
int main(int argc, char** argv) {
char* s = "abaaabcaabaabcacabaabcaabaabcac";
char* t = "abaabcac";
SString S, T;
int* next; // 模式串的next函数值
int* nextval; // 模式串的nextval函数值
int pos; // 匹配起点
int i, j;
StrAssign(S, s); // 初始化主串
printf("S = ");
PrintElem(S);
StrAssign(T, t); // 初始化模式串
printf("T = ");
PrintElem(T);
// 注:next数组和nextval数组的0号单元是弃用的,从1号单元开始存储有效数据
next = (int*) malloc((T[0] + 1) * sizeof(int));
nextval = (int*) malloc((T[0] + 1) * sizeof(int));
get_next(T, next); // 算法4.7
get_nextval(T, nextval); // 算法4.8,即算法4.7的改进版
printf("next : ");
for(i = 1; i <= T[0]; i++) {
printf("%d", next[i]);
}
printf("\n");
printf("nextval : ");
for(i = 1; i <= T[0]; i++) {
printf("%d", nextval[i]);
}
printf("\n");
pos = 1;
i = Index_KMP(S, T, pos, next);
j = Index_KMP(S, T, pos, nextval);
printf("从%d个字符起,T 在 S 中第一次匹配成功的位置为 %d\n", pos, i);
printf("从%d个字符起,T 在 S 中第一次匹配成功的位置为 %d\n", pos, j);
return 0;
}
// 测试函数,打印字符串
void PrintElem(SString S) {
int i;
for(i = 1; i <= S[0]; i++) {
printf("%c", S[i]);
}
printf("\n");
}
+106
View File
@@ -0,0 +1,106 @@
/*=======================
* KMP算法
*
* 包含算法: 4.6、4.7、4.8
========================*/
#include "KMP.h" //**▲04 串**//
/*
* ████████ 算法4.6 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.该实现用到了KMP算法,是一种比较高效的字符串匹配方式
* 2.教材中没有next参数
*/
int Index_KMP(SString S, SString T, int pos, int next[]) {
int i = pos;
int j = 1;
if(pos < 1) {
return 0;
}
// 比较字符串
while(i <= S[0] && j <= T[0]) {
/*
* 两种情形:
* 1.在模式串的第一个字符处就失配
* 2.主串和模式串处的字符相等
*/
if(j == 0 || S[i] == T[j]) {
i++;
j++;
} else {
// 失配时回到前一个适当的位置
j = next[j];
}
}
if(j > T[0]) {
// 匹配成功,返回匹配位置
return i - T[0];
} else {
// 匹配失败
return 0;
}
}
/*
* ████████ 算法4.7 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
*/
void get_next(SString T, int next[]) {
int i = 1;
int j = 0;
// 模式串第一个字符处失配时,模式串需要从头比较,主串需要前进到下一个位置比较
next[1] = 0;
// 遍历模式串上的字符
while(i < T[0]) {
if(j == 0 || T[i] == T[j]) {
i++;
j++;
next[i] = j;
} else {
j = next[j];
}
}
}
/*
* ████████ 算法4.8 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
* 这是一个优化后的版本,效率较算法4.7有所提高。
*/
void get_nextval(SString T, int nextval[]) {
int i = 1;
int j = 0;
// 模式串第一个字符处失配时,模式串需要从头比较,主串需要前进到下一个位置比较
nextval[1] = 0;
// 遍历模式串上的字符
while(i < T[0]) {
if(j==0 || T[i] == T[j]) {
i++;
j++;
if(T[i] != T[j]) {
nextval[i] = j;
} else {
nextval[i] = nextval[j];
}
} else {
j = nextval[j];
}
}
}
+43
View File
@@ -0,0 +1,43 @@
/*=======================
* KMP算法
*
* 包含算法: 4.6、4.7、4.8
========================*/
#ifndef KMP_H
#define KMP_H
#include <stdio.h>
#include <stdlib.h>
#include "SString.h" //**▲04 串**//
/*
* ████████ 算法4.6 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.该实现用到了KMP算法,是一种比较高效的字符串匹配方式
* 2.教材中没有next参数
*/
int Index_KMP(SString S, SString T, int pos, int next[]);
/*
* ████████ 算法4.7 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
*/
void get_next(SString T, int next[]);
/*
* ████████ 算法4.8 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
* 这是一个优化后的版本,效率较算法4.7有所提高。
*/
void get_nextval(SString T, int nextval[]);
#endif
+33
View File
@@ -0,0 +1,33 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#include "SString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars) {
int i, len;
len = (int) strlen(chars);
// chars过长
if(len > MAXSTRLEN) {
return ERROR;
}
T[0] = len;
for(i = 1; i <= len; i++) {
T[i] = chars[i - 1];
}
return OK;
}
+36
View File
@@ -0,0 +1,36 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#ifndef SSTRING_H
#define SSTRING_H
#include <stdio.h>
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAXSTRLEN 255 // 顺序串的最大串长
/*
* 串的顺序存储类型定义
*
* 注:有效元素从SString的1号单元开始存储
* SString的0号单元用来存储其长度
*/
typedef unsigned char SString[MAXSTRLEN + 1]; // 0号单元存放串的长度
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars);
#endif
@@ -0,0 +1,12 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(WordList ELinkList.h ELinkList.c HString.h HString.c WordList.h WordList.c WordList-main.c)
# 链接公共库
target_link_libraries(WordList Scanf_lib)
# 记录要拷贝到*.exe目录下的资源文件
file(GLOB TestData TestData*.txt)
# 将资源文件拷贝到*.exe目录下,不然无法加载
file(COPY ${TestData} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
@@ -0,0 +1,95 @@
/*=======================
* 扩展的单链表(线性链表)
*
* 包含算法: 2.20
========================*/
#include "ELinkList.h" //**▲02 线性表**//
/*━━━━━━━━━━━━━━━━━━━━━━ 内存操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 内存分配
*
* 为线性链表申请一个结点,并存入指定的数据e。
*
*【备注】
* static修饰的含义是该函数仅限当前文件内使用
*/
Status MakeNode(Link* p, ElemType e) {
if(p == NULL) {
return ERROR;
}
// 申请空间
*p = (Link) malloc(sizeof(LNode));
if(*p == NULL) {
// 这里没有退出程序,而是返回错误提示
return ERROR;
}
(*p)->data = e;
(*p)->next = NULL;
return OK;
}
/*━━━━━━━━━━━━━━━━━━━━━━ 链表常规操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 初始化
*
* 初始化成功则返回OK,否则返回ERROR。
*/
Status InitList(ELinkList* L) {
Link p;
if(L == NULL) {
return ERROR;
}
// 创建头结点
p = (Link) malloc(sizeof(LNode));
if(p == NULL) {
exit(OVERFLOW);
}
p->next = NULL;
// 只有头结点时,首位游标指向自身
(*L).head = (*L).tail = p;
(*L).len = 0;
return OK;
}
/*━━━━━━━━━━━━━━━━━━━━━━ 链表扩展操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 向尾部添加
*
* 将s所指的一串结点链接在链表L后面
*/
Status Append(ELinkList* L, Link s) {
int count;
if(L == NULL || (*L).head == NULL || s == NULL) {
return ERROR;
}
count = 0;
(*L).tail->next = s;
// 确定新的尾结点位置
while(s != NULL) {
(*L).tail = s;
s = s->next;
count++;
}
(*L).len += count;
return OK;
}
@@ -0,0 +1,75 @@
/*=======================
* 扩展的单链表(线性链表)
*
* 包含算法: 2.20
========================*/
#ifndef ELINKLIST_H
#define ELINKLIST_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <limits.h> // 提供一些极限常量
#include "Status.h" //**▲01 绪论**//
/*
* ████ 注意 ████
*
* 教材中的线性链表命名为LinkList,
* 这里为了与单链表区分,故将其命名为ELinkList。
* 线性链表可以理解成对普通链表的一种扩展。
*/
/* 线性链表元素类型定义 */
typedef int ElemType;
/*
* 线性链表结构
*
* 注:这里的线性链表存在头结点
*/
typedef struct LNode {
ElemType data;
struct LNode* next;
} LNode, * Link, * Position;
/* 维护线性链表头尾指针及长度信息 */
typedef struct {
Link head, tail; // 分别指向线性链表中的头结点和尾结点
int len; // 指示线性链表中数据元素的个数
} ELinkList;
/*━━━━━━━━━━━━━━━━━━━━━━ 内存操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 内存分配
*
* 为线性链表申请一个结点,并存入指定的数据e。
*
*【备注】
* static修饰的含义是该函数仅限当前文件内使用
*/
Status MakeNode(Link* p, ElemType e);
/*━━━━━━━━━━━━━━━━━━━━━━ 链表常规操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 初始化
*
* 初始化成功则返回OK,否则返回ERROR。
*/
Status InitList(ELinkList* L);
/*━━━━━━━━━━━━━━━━━━━━━━ 链表扩展操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 向尾部添加
*
* 将s所指的一串结点链接在链表L后面
*/
Status Append(ELinkList* L, Link s);
#endif
+95
View File
@@ -0,0 +1,95 @@
/*=========================
* 串的堆分配存储表示(堆串)
*
* 包含算法: 4.4
==========================*/
#include "HString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(HString* T, const char* chars) {
int i, j;
// 求chars的长度
i = (int) strlen(chars);
// 没有有效元素
if(i == 0) {
(*T).ch = NULL;
(*T).length = 0;
return OK;
}
// 存在有效元素时,需要分配存储空间
(*T).ch = (char*) malloc(i * sizeof(char));
if(!((*T).ch)) {
exit(OVERFLOW);
}
for(j = 0; j < i; j++) {
(*T).ch[j] = chars[j];
}
(*T).length = i;
return OK;
}
/*
* 比较
*
* 比较串S和串T,返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrCompare(HString S, HString T) {
int i;
for(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;
}
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(HString* T, HString S) {
int i;
if(S.length == 0) {
(*T).ch = NULL;
(*T).length = 0;
} else {
// 分配空间
(*T).ch = (char*) malloc(S.length * sizeof(char));
if(!(*T).ch) {
exit(OVERFLOW);
}
// 复制元素
for(i = 0; i < S.length; i++) {
(*T).ch[i] = S.ch[i];
}
// 复制长度信息
(*T).length = S.length;
}
return OK;
}
+53
View File
@@ -0,0 +1,53 @@
/*=========================
* 串的堆分配存储表示(堆串)
*
* 包含算法: 4.4
==========================*/
#ifndef HSTRING
#define HSTRING
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/*
* 串的堆存储表示
*
* 注:有效元素从ch的0号单元开始存储
*/
typedef struct {
char* ch; // 若是非空串,则按串长分配存储区,否则ch为NULL
int length;
} HString;
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(HString* T, const char* chars);
/*
* 比较
*
* 比较串S和串T,返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrCompare(HString S, HString T);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(HString* T, HString S);
#endif
@@ -0,0 +1,7 @@
书 号 书 名
005 Computer Data Structures
010 Introduction to Data Structures
023 Fundamentals of Data Structures
034 The Design and Analysis of Computer Algorithms
050 Introduction to Numerical Analysis
067 Numerical Analysis
@@ -0,0 +1,27 @@
#include <stdio.h> // 提供system原型
#include "WordList.h" //**▲04 串**//
int main(int argc, char** argv) {
FILE* fp;
char line[MaxLineLen];
char* bookinfo = "TestData.txt"; // 书目文件名
char* bookidx = "BookIdx.txt"; // 关键词索引文件名
// 创建索引表
Main(bookinfo, bookidx);
// 显示索引表到屏幕
if((fp = fopen(bookidx, "r"))!=NULL) {
printf("---------索引表生成功!---------\n\n");
while(feof(fp)==FALSE) {
fgets(line, MaxLineLen, fp);
printf("%s", line);
}
} else {
printf("---------未发现索引表!---------\n");
}
return 0;
}
File diff suppressed because it is too large Load Diff
+130
View File
@@ -0,0 +1,130 @@
/*===========================================
* 索引表
*
* 包含算法: 4.9、4.10、4.11、4.12、4.13、4.14
============================================*/
#ifndef WORDLIST_H
#define WORDLIST_H
#include <stdio.h> // 提供fopen、fclose、feof、fgets原型
#include <stdlib.h> // 提供exit、strtol原型
#include <string.h> // 提供strlen、strcmpi、strlwr原型
#include "Status.h" //**▲01 绪论**//
#include "ELinkList.h" //**▲02 线性表**//
#include "HString.h" //**▲04 串**//
/* 宏定义 */
#define MaxBookNum 1000 // 允许的最大书目数(假设最多只对1000本书建索引表)
#define MaxKeyNum 2500 // 索引表最大容量(索引项数量的最大值)
#define MaxLineLen 500 // 书目串(行)的最大长度
#define MaxWordNum 100 // 词表的最大容量
/* 类型定义 */
// 布尔类型
typedef Status Boolean;
// 词表类型(顺序表)
typedef struct {
char* item[MaxWordNum]; // 词表集合
int last; // 词表的长度
} WordListType;
// 索引项类型(索引表的行)
typedef struct {
HString key; // 关键词
ELinkList bnolist; // 存放书号索引的链表
} IdxTermType;
/*
* 索引表类型
*
*【注】
* 0号单元存储表头信息,这一点与教材有所不同
*/
typedef struct {
IdxTermType item[MaxKeyNum + 1]; // 索引项的集合
int last; // 索引表中包含的索引项数目
} IdxListType;
/* 全局变量(变量名称前面都加了g标记) */
// 书目缓存区
char gBuf[MaxLineLen];
// 关键词词表(普通词表),已经排除了常用词
WordListType gWdList;
/*
* ████████ 算法4.9 ████████
*
* 从文件bookinfo中读取书目信息,并依此创建相应的关键词索引表,然后将索引表写入文件bookidx。
*/
void Main(char* bookinfo, char* bookidx);
/*
* 初始化索引表
*
*【注】
* 教材中将索引表表头置为空串,但这里设定了一个有意义的表头
*/
void InitIdxList(IdxListType* idxlist);
/*
* 从文件f中读取一条书目信息存入书目缓冲区gBuf。
*/
void GetLine(FILE* f);
/*
* 从缓冲区gBuf中提取书名关键词到词表gWdList,书号存入bno。
*/
void ExtractKeyWord(ElemType* bno);
/*
* ████████ 算法4.10 ████████
*
* 将书号bno对应的书名关键词按词典顺序插入到索引表idxlist。
*/
Status InsIdxList(IdxListType* idxlist, int bno);
/*
* ████████ 算法4.11 ████████
*
* 用wd返回词表gWdList中第i个关键词。
*/
void GetWord(int i, HString* wd);
/*
* ████████ 算法4.12 ████████
*
* 查询在索引表idxlist中是否存在与wd相等的关键词。
* 若存在,则返回wd在词表中的位置,并置b为TRUE。
* 若不存在,则返回wd应插入的位置,并置b为FALSE。
*/
int Locate(IdxListType idxlist, HString wd, Boolean* b);
/*
* ████████ 算法4.13 ████████
*
* 在索引表的索引i(>=0)处插入关键词wd,并初始化书号索引的链表为空表。
*/
void InsertNewKey(IdxListType* idxlist, int i, HString wd);
/*
* ████████ 算法4.14 ████████
*
* 为索引表在索引i(>0)处的关键词插入书号。
*/
Status InsertBook(IdxListType* idxlist, int i, int bno);
/*
* 将生成的索引表idxlist输出到文件g。
*/
void PutText(FILE* g, IdxListType idxlist);
// 判断str是否为常用词
static Status isCommonWords(char* str);
#endif
+2
View File
@@ -23,3 +23,5 @@ add_subdirectory(0309_BankQueuing)
add_subdirectory(0401_SString)
add_subdirectory(0402_HString)
add_subdirectory(0403_LString)
add_subdirectory(0404_KMP)
add_subdirectory(0405_WordList)
+64
View File
@@ -0,0 +1,64 @@
#include "KMP.h" //**▲04 串**//
// 测试函数,打印字符串
void PrintElem(SString S);
int main(int argc, char** argv) {
char* s = "abaaabcaabaabcacabaabcaabaabcac";
char* t = "abaabcac";
SString S, T;
int* next; // 模式串的next函数值
int* nextval; // 模式串的nextval函数值
int pos; // 匹配起点
int i, j;
StrAssign(S, s); // 初始化主串
printf("S = ");
PrintElem(S);
StrAssign(T, t); // 初始化模式串
printf("T = ");
PrintElem(T);
// 注:next数组和nextval数组的0号单元是弃用的,从1号单元开始存储有效数据
next = (int*) malloc((T[0] + 1) * sizeof(int));
nextval = (int*) malloc((T[0] + 1) * sizeof(int));
get_next(T, next); // 算法4.7
get_nextval(T, nextval); // 算法4.8,即算法4.7的改进版
printf("next : ");
for(i = 1; i <= T[0]; i++) {
printf("%d", next[i]);
}
printf("\n");
printf("nextval : ");
for(i = 1; i <= T[0]; i++) {
printf("%d", nextval[i]);
}
printf("\n");
pos = 1;
i = Index_KMP(S, T, pos, next);
j = Index_KMP(S, T, pos, nextval);
printf("从%d个字符起,T 在 S 中第一次匹配成功的位置为 %d\n", pos, i);
printf("从%d个字符起,T 在 S 中第一次匹配成功的位置为 %d\n", pos, j);
return 0;
}
// 测试函数,打印字符串
void PrintElem(SString S) {
int i;
for(i = 1; i <= S[0]; i++) {
printf("%c", S[i]);
}
printf("\n");
}
+106
View File
@@ -0,0 +1,106 @@
/*=======================
* KMP算法
*
* 包含算法: 4.6、4.7、4.8
========================*/
#include "KMP.h" //**▲04 串**//
/*
* ████████ 算法4.6 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.该实现用到了KMP算法,是一种比较高效的字符串匹配方式
* 2.教材中没有next参数
*/
int Index_KMP(SString S, SString T, int pos, int next[]) {
int i = pos;
int j = 1;
if(pos < 1) {
return 0;
}
// 比较字符串
while(i <= S[0] && j <= T[0]) {
/*
* 两种情形:
* 1.在模式串的第一个字符处就失配
* 2.主串和模式串处的字符相等
*/
if(j == 0 || S[i] == T[j]) {
i++;
j++;
} else {
// 失配时回到前一个适当的位置
j = next[j];
}
}
if(j > T[0]) {
// 匹配成功,返回匹配位置
return i - T[0];
} else {
// 匹配失败
return 0;
}
}
/*
* ████████ 算法4.7 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
*/
void get_next(SString T, int next[]) {
int i = 1;
int j = 0;
// 模式串第一个字符处失配时,模式串需要从头比较,主串需要前进到下一个位置比较
next[1] = 0;
// 遍历模式串上的字符
while(i < T[0]) {
if(j == 0 || T[i] == T[j]) {
i++;
j++;
next[i] = j;
} else {
j = next[j];
}
}
}
/*
* ████████ 算法4.8 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
* 这是一个优化后的版本,效率较算法4.7有所提高。
*/
void get_nextval(SString T, int nextval[]) {
int i = 1;
int j = 0;
// 模式串第一个字符处失配时,模式串需要从头比较,主串需要前进到下一个位置比较
nextval[1] = 0;
// 遍历模式串上的字符
while(i < T[0]) {
if(j==0 || T[i] == T[j]) {
i++;
j++;
if(T[i] != T[j]) {
nextval[i] = j;
} else {
nextval[i] = nextval[j];
}
} else {
j = nextval[j];
}
}
}
+102
View File
@@ -0,0 +1,102 @@
[Project]
FileName=KMP.dev
Name=KMP
Type=1
Ver=2
ObjFiles=
Includes=
Libs=
PrivateResource=
ResourceIncludes=
MakeIncludes=
Compiler=
CppCompiler=
Linker=
IsCpp=0
Icon=
ExeOutput=
ObjectOutput=
LogOutput=
LogOutputEnabled=0
OverrideOutput=0
OverrideOutputName=
HostApplication=
UseCustomMakefile=0
CustomMakefile=
CommandLine=
Folders=
IncludeVersionInfo=0
SupportXPThemes=0
CompilerSet=1
CompilerSettings=0000000000000000001000000
UnitCount=5
[VersionInfo]
Major=1
Minor=0
Release=0
Build=0
LanguageID=1033
CharsetID=1252
CompanyName=
FileVersion=
FileDescription=Developed using the Dev-C++ IDE
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=
ProductName=
ProductVersion=
AutoIncBuildNr=0
SyncProduct=1
[Unit3]
FileName=KMP-main.cpp
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit1]
FileName=KMP.cpp
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit4]
FileName=SString.cpp
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit2]
FileName=KMP.h
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit5]
FileName=SString.h
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
+43
View File
@@ -0,0 +1,43 @@
/*=======================
* KMP算法
*
* 包含算法: 4.6、4.7、4.8
========================*/
#ifndef KMP_H
#define KMP_H
#include <stdio.h>
#include <stdlib.h>
#include "SString.h" //**▲04 串**//
/*
* ████████ 算法4.6 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.该实现用到了KMP算法,是一种比较高效的字符串匹配方式
* 2.教材中没有next参数
*/
int Index_KMP(SString S, SString T, int pos, int next[]);
/*
* ████████ 算法4.7 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
*/
void get_next(SString T, int next[]);
/*
* ████████ 算法4.8 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
* 这是一个优化后的版本,效率较算法4.7有所提高。
*/
void get_nextval(SString T, int nextval[]);
#endif
+33
View File
@@ -0,0 +1,33 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#include "SString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars) {
int i, len;
len = (int) strlen(chars);
// chars过长
if(len > MAXSTRLEN) {
return ERROR;
}
T[0] = len;
for(i = 1; i <= len; i++) {
T[i] = chars[i - 1];
}
return OK;
}
+36
View File
@@ -0,0 +1,36 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#ifndef SSTRING_H
#define SSTRING_H
#include <stdio.h>
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAXSTRLEN 255 // 顺序串的最大串长
/*
* 串的顺序存储类型定义
*
* 注:有效元素从SString的1号单元开始存储
* SString的0号单元用来存储其长度
*/
typedef unsigned char SString[MAXSTRLEN + 1]; // 0号单元存放串的长度
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars);
#endif
@@ -0,0 +1,95 @@
/*=======================
* 扩展的单链表(线性链表)
*
* 包含算法: 2.20
========================*/
#include "ELinkList.h" //**▲02 线性表**//
/*━━━━━━━━━━━━━━━━━━━━━━ 内存操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 内存分配
*
* 为线性链表申请一个结点,并存入指定的数据e。
*
*【备注】
* static修饰的含义是该函数仅限当前文件内使用
*/
Status MakeNode(Link* p, ElemType e) {
if(p == NULL) {
return ERROR;
}
// 申请空间
*p = (Link) malloc(sizeof(LNode));
if(*p == NULL) {
// 这里没有退出程序,而是返回错误提示
return ERROR;
}
(*p)->data = e;
(*p)->next = NULL;
return OK;
}
/*━━━━━━━━━━━━━━━━━━━━━━ 链表常规操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 初始化
*
* 初始化成功则返回OK,否则返回ERROR。
*/
Status InitList(ELinkList* L) {
Link p;
if(L == NULL) {
return ERROR;
}
// 创建头结点
p = (Link) malloc(sizeof(LNode));
if(p == NULL) {
exit(OVERFLOW);
}
p->next = NULL;
// 只有头结点时,首位游标指向自身
(*L).head = (*L).tail = p;
(*L).len = 0;
return OK;
}
/*━━━━━━━━━━━━━━━━━━━━━━ 链表扩展操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 向尾部添加
*
* 将s所指的一串结点链接在链表L后面
*/
Status Append(ELinkList* L, Link s) {
int count;
if(L == NULL || (*L).head == NULL || s == NULL) {
return ERROR;
}
count = 0;
(*L).tail->next = s;
// 确定新的尾结点位置
while(s != NULL) {
(*L).tail = s;
s = s->next;
count++;
}
(*L).len += count;
return OK;
}
@@ -0,0 +1,75 @@
/*=======================
* 扩展的单链表(线性链表)
*
* 包含算法: 2.20
========================*/
#ifndef ELINKLIST_H
#define ELINKLIST_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <limits.h> // 提供一些极限常量
#include "Status.h" //**▲01 绪论**//
/*
* ████ 注意 ████
*
* 教材中的线性链表命名为LinkList,
* 这里为了与单链表区分,故将其命名为ELinkList。
* 线性链表可以理解成对普通链表的一种扩展。
*/
/* 线性链表元素类型定义 */
typedef int ElemType;
/*
* 线性链表结构
*
* 注:这里的线性链表存在头结点
*/
typedef struct LNode {
ElemType data;
struct LNode* next;
} LNode, * Link, * Position;
/* 维护线性链表头尾指针及长度信息 */
typedef struct {
Link head, tail; // 分别指向线性链表中的头结点和尾结点
int len; // 指示线性链表中数据元素的个数
} ELinkList;
/*━━━━━━━━━━━━━━━━━━━━━━ 内存操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 内存分配
*
* 为线性链表申请一个结点,并存入指定的数据e。
*
*【备注】
* static修饰的含义是该函数仅限当前文件内使用
*/
Status MakeNode(Link* p, ElemType e);
/*━━━━━━━━━━━━━━━━━━━━━━ 链表常规操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 初始化
*
* 初始化成功则返回OK,否则返回ERROR。
*/
Status InitList(ELinkList* L);
/*━━━━━━━━━━━━━━━━━━━━━━ 链表扩展操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 向尾部添加
*
* 将s所指的一串结点链接在链表L后面
*/
Status Append(ELinkList* L, Link s);
#endif
@@ -0,0 +1,95 @@
/*=========================
* 串的堆分配存储表示(堆串)
*
* 包含算法: 4.4
==========================*/
#include "HString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(HString* T, const char* chars) {
int i, j;
// 求chars的长度
i = (int) strlen(chars);
// 没有有效元素
if(i == 0) {
(*T).ch = NULL;
(*T).length = 0;
return OK;
}
// 存在有效元素时,需要分配存储空间
(*T).ch = (char*) malloc(i * sizeof(char));
if(!((*T).ch)) {
exit(OVERFLOW);
}
for(j = 0; j < i; j++) {
(*T).ch[j] = chars[j];
}
(*T).length = i;
return OK;
}
/*
* 比较
*
* 比较串S和串T,返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrCompare(HString S, HString T) {
int i;
for(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;
}
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(HString* T, HString S) {
int i;
if(S.length == 0) {
(*T).ch = NULL;
(*T).length = 0;
} else {
// 分配空间
(*T).ch = (char*) malloc(S.length * sizeof(char));
if(!(*T).ch) {
exit(OVERFLOW);
}
// 复制元素
for(i = 0; i < S.length; i++) {
(*T).ch[i] = S.ch[i];
}
// 复制长度信息
(*T).length = S.length;
}
return OK;
}
@@ -0,0 +1,53 @@
/*=========================
* 串的堆分配存储表示(堆串)
*
* 包含算法: 4.4
==========================*/
#ifndef HSTRING
#define HSTRING
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/*
* 串的堆存储表示
*
* 注:有效元素从ch的0号单元开始存储
*/
typedef struct {
char* ch; // 若是非空串,则按串长分配存储区,否则ch为NULL
int length;
} HString;
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(HString* T, const char* chars);
/*
* 比较
*
* 比较串S和串T,返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrCompare(HString S, HString T);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(HString* T, HString S);
#endif
@@ -0,0 +1,7 @@
Êé ºÅ Êé Ãû
005 Computer Data Structures
010 Introduction to Data Structures
023 Fundamentals of Data Structures
034 The Design and Analysis of Computer Algorithms
050 Introduction to Numerical Analysis
067 Numerical Analysis
@@ -0,0 +1,27 @@
#include <stdio.h> // 提供system原型
#include "WordList.h" //**▲04 串**//
int main(int argc, char** argv) {
FILE* fp;
char line[MaxLineLen];
char* bookinfo = "TestData.txt"; // 书目文件名
char* bookidx = "BookIdx.txt"; // 关键词索引文件名
// 创建索引表
Main(bookinfo, bookidx);
// 显示索引表到屏幕
if((fp = fopen(bookidx, "r"))!=NULL) {
printf("---------索引表生成功!---------\n\n");
while(feof(fp)==FALSE) {
fgets(line, MaxLineLen, fp);
printf("%s", line);
}
} else {
printf("---------未发现索引表!---------\n");
}
return 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,131 @@
[Project]
FileName=WordList.dev
Name=WordList
Type=1
Ver=2
ObjFiles=
Includes=
Libs=
PrivateResource=
ResourceIncludes=
MakeIncludes=
Compiler=
CppCompiler=
Linker=
IsCpp=0
Icon=
ExeOutput=
ObjectOutput=
LogOutput=
LogOutputEnabled=0
OverrideOutput=0
OverrideOutputName=
HostApplication=
UseCustomMakefile=0
CustomMakefile=
CommandLine=
Folders=
IncludeVersionInfo=0
SupportXPThemes=0
CompilerSet=1
CompilerSettings=0000000000000000001000000
UnitCount=8
[VersionInfo]
Major=1
Minor=0
Release=0
Build=0
LanguageID=1033
CharsetID=1252
CompanyName=
FileVersion=
FileDescription=Developed using the Dev-C++ IDE
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=
ProductName=
ProductVersion=
AutoIncBuildNr=0
SyncProduct=1
[Unit7]
FileName=WordList-main.cpp
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit1]
FileName=ELinkList.cpp
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit3]
FileName=HString.cpp
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit5]
FileName=WordList.cpp
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit2]
FileName=ELinkList.h
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit4]
FileName=HString.h
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit6]
FileName=WordList.h
CompileCpp=0
Folder=
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit8]
FileName=TestData.txt
Folder=
Compile=0
Link=0
Priority=1000
OverrideBuildCmd=0
BuildCmd=
+130
View File
@@ -0,0 +1,130 @@
/*===========================================
* 索引表
*
* 包含算法: 4.9、4.10、4.11、4.12、4.13、4.14
============================================*/
#ifndef WORDLIST_H
#define WORDLIST_H
#include <stdio.h> // 提供fopen、fclose、feof、fgets原型
#include <stdlib.h> // 提供exit、strtol原型
#include <string.h> // 提供strlen、strcmpi、strlwr原型
#include "Status.h" //**▲01 绪论**//
#include "ELinkList.h" //**▲02 线性表**//
#include "HString.h" //**▲04 串**//
/* 宏定义 */
#define MaxBookNum 1000 // 允许的最大书目数(假设最多只对1000本书建索引表)
#define MaxKeyNum 2500 // 索引表最大容量(索引项数量的最大值)
#define MaxLineLen 500 // 书目串(行)的最大长度
#define MaxWordNum 100 // 词表的最大容量
/* 类型定义 */
// 布尔类型
typedef Status Boolean;
// 词表类型(顺序表)
typedef struct {
char* item[MaxWordNum]; // 词表集合
int last; // 词表的长度
} WordListType;
// 索引项类型(索引表的行)
typedef struct {
HString key; // 关键词
ELinkList bnolist; // 存放书号索引的链表
} IdxTermType;
/*
* 索引表类型
*
*【注】
* 0号单元存储表头信息,这一点与教材有所不同
*/
typedef struct {
IdxTermType item[MaxKeyNum + 1]; // 索引项的集合
int last; // 索引表中包含的索引项数目
} IdxListType;
/* 全局变量(变量名称前面都加了g标记) */
// 书目缓存区
static char gBuf[MaxLineLen];
// 关键词词表(普通词表),已经排除了常用词
static WordListType gWdList;
/*
* ████████ 算法4.9 ████████
*
* 从文件bookinfo中读取书目信息,并依此创建相应的关键词索引表,然后将索引表写入文件bookidx。
*/
void Main(char* bookinfo, char* bookidx);
/*
* 初始化索引表
*
*【注】
* 教材中将索引表表头置为空串,但这里设定了一个有意义的表头
*/
void InitIdxList(IdxListType* idxlist);
/*
* 从文件f中读取一条书目信息存入书目缓冲区gBuf。
*/
void GetLine(FILE* f);
/*
* 从缓冲区gBuf中提取书名关键词到词表gWdList,书号存入bno。
*/
void ExtractKeyWord(ElemType* bno);
/*
* ████████ 算法4.10 ████████
*
* 将书号bno对应的书名关键词按词典顺序插入到索引表idxlist。
*/
Status InsIdxList(IdxListType* idxlist, int bno);
/*
* ████████ 算法4.11 ████████
*
* 用wd返回词表gWdList中第i个关键词。
*/
void GetWord(int i, HString* wd);
/*
* ████████ 算法4.12 ████████
*
* 查询在索引表idxlist中是否存在与wd相等的关键词。
* 若存在,则返回wd在词表中的位置,并置b为TRUE。
* 若不存在,则返回wd应插入的位置,并置b为FALSE。
*/
int Locate(IdxListType idxlist, HString wd, Boolean* b);
/*
* ████████ 算法4.13 ████████
*
* 在索引表的索引i(>=0)处插入关键词wd,并初始化书号索引的链表为空表。
*/
void InsertNewKey(IdxListType* idxlist, int i, HString wd);
/*
* ████████ 算法4.14 ████████
*
* 为索引表在索引i(>0)处的关键词插入书号。
*/
Status InsertBook(IdxListType* idxlist, int i, int bno);
/*
* 将生成的索引表idxlist输出到文件g。
*/
void PutText(FILE* g, IdxListType idxlist);
// 判断str是否为常用词
static Status isCommonWords(char* str);
#endif
+28 -26
View File
@@ -91,29 +91,31 @@ Commit信息中的`emoji`参考来源:
## 附:教材源码目录
| 章 | 节 | 内容 | 包含算法 | 备注 |
| :--------- | :---------- | :----------- | :-------------------- | :------------------- |
| 01 绪论 | Status | | | 定义一些共享常量和函数 |
| 02 线性表 | SqList | 顺序表 | 2.3、2.4、2.5、2.6 | 线性表的顺序存储结构 |
| | Union | A=A∪B | 2.1 | |
| | MergeSqList | C=A+B | 2.2、2.7 | 归并顺序表 |
| | LinkList | 链表 | 2.8、2.9、2.10、2.11 | 线性表的链式存储结构 |
| | MergeList | C=A+B | 2.12 | 归并链表 |
| | SLinkList | 静态链表 | 2.13、2.14、2.15、2.16 | |
| | Difference | (A-B)∪(B-A) | 2.17 | |
| | DuLinkList | 双向循环链表 | 2.18、2.19 | |
| | ELinkList | 扩展的线性链表 | 2.20 | |
| | MergeEList | C=A+B | 2.21 | 归并扩展的线性链表 |
| | Polynomial | 一元多项式 | 2.22、2.23 | |
| 03 栈和队列 | SqStack | 栈 | | 顺序存储结构 |
| | Conversion | 进制转换 | 3.1 | 栈的应用 |
| | LineEdit | 行编辑程序 | 3.2 | 栈的应用 |
| | Maze | 迷宫寻路 | 3.3 | 栈的应用 |
| | Expression | 表达式求值 | 3.4 | 栈的应用 |
| | Hanoi | 汉诺塔 | 3.5 | 递归 |
| | LinkQueue | 链列 | | 链式存储结构 |
| | SqQueue | 顺序队列 | | 循环队列,顺序存储结构 |
| | BankQueuing | 模拟银行排队 | 3.6、3.7 | 队列的应用 |
| 04 串 | SString | 顺序串 | 4.1、4.2、4.3、4.5 | 顺序存储 |
| | HString | 堆串 | 4.4 | 顺序存储,动态分配内存 |
| | LString | 块链串 | | 顺序存储+链式存储 |
| 章 | 节 | 内容 | 包含算法 | 备注 |
| :--------- | :---------- | :----------- | :------------------------------- | :------------------- |
| 01 绪论 | Status | | | 定义一些共享常量和函数 |
| 02 线性表 | SqList | 顺序表 | 2.3、2.4、2.5、2.6 | 线性表的顺序存储结构 |
| | Union | A=A∪B | 2.1 | |
| | MergeSqList | C=A+B | 2.2、2.7 | 归并顺序表 |
| | LinkList | 链表 | 2.8、2.9、2.10、2.11 | 线性表的链式存储结构 |
| | MergeList | C=A+B | 2.12 | 归并链表 |
| | SLinkList | 静态链表 | 2.13、2.14、2.15、2.16 | |
| | Difference | (A-B)∪(B-A) | 2.17 | |
| | DuLinkList | 双向循环链表 | 2.18、2.19 | |
| | ELinkList | 扩展的线性链表 | 2.20 | |
| | MergeEList | C=A+B | 2.21 | 归并扩展的线性链表 |
| | Polynomial | 一元多项式 | 2.22、2.23 | |
| 03 栈和队列 | SqStack | 栈 | | 顺序存储结构 |
| | Conversion | 进制转换 | 3.1 | 栈的应用 |
| | LineEdit | 行编辑程序 | 3.2 | 栈的应用 |
| | Maze | 迷宫寻路 | 3.3 | 栈的应用 |
| | Expression | 表达式求值 | 3.4 | 栈的应用 |
| | Hanoi | 汉诺塔 | 3.5 | 递归 |
| | LinkQueue | 链列 | | 链式存储结构 |
| | SqQueue | 顺序队列 | | 循环队列,顺序存储结构 |
| | BankQueuing | 模拟银行排队 | 3.6、3.7 | 队列的应用 |
| 04 串 | SString | 顺序串 | 4.1、4.2、4.3、4.5 | 顺序存储 |
| | HString | 堆串 | 4.4 | 顺序存储,动态分配内存 |
| | LString | 块链串 | | 顺序存储+链式存储 |
| | KMP | KMP算法 | 4.6、4.7、4.8 | 字符串匹配算法 |
| | WordList | 关键词索引 | 4.9、4.10、4.11、4.12、4.13、4.14 | 堆串和线性表的应用 |
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5D2A1F0B-F177-43A9-873A-56C7E08E6987}</ProjectGuid>
<RootNamespace>My0404_KMP</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(SolutionDir)\..\Status;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>$(SolutionDir)\..\Status\Status.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="KMP.h" />
<ClInclude Include="SString.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="KMP-main.c" />
<ClCompile Include="KMP.c" />
<ClCompile Include="SString.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="KMP.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="SString.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="KMP.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="KMP-main.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="SString.c">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>
+64
View File
@@ -0,0 +1,64 @@
#include "KMP.h" //**▲04 串**//
// 测试函数,打印字符串
void PrintElem(SString S);
int main(int argc, char** argv) {
char* s = "abaaabcaabaabcacabaabcaabaabcac";
char* t = "abaabcac";
SString S, T;
int* next; // 模式串的next函数值
int* nextval; // 模式串的nextval函数值
int pos; // 匹配起点
int i, j;
StrAssign(S, s); // 初始化主串
printf("S = ");
PrintElem(S);
StrAssign(T, t); // 初始化模式串
printf("T = ");
PrintElem(T);
// 注:next数组和nextval数组的0号单元是弃用的,从1号单元开始存储有效数据
next = (int*) malloc((T[0] + 1) * sizeof(int));
nextval = (int*) malloc((T[0] + 1) * sizeof(int));
get_next(T, next); // 算法4.7
get_nextval(T, nextval); // 算法4.8,即算法4.7的改进版
printf("next : ");
for(i = 1; i <= T[0]; i++) {
printf("%d", next[i]);
}
printf("\n");
printf("nextval : ");
for(i = 1; i <= T[0]; i++) {
printf("%d", nextval[i]);
}
printf("\n");
pos = 1;
i = Index_KMP(S, T, pos, next);
j = Index_KMP(S, T, pos, nextval);
printf("从%d个字符起,T 在 S 中第一次匹配成功的位置为 %d\n", pos, i);
printf("从%d个字符起,T 在 S 中第一次匹配成功的位置为 %d\n", pos, j);
return 0;
}
// 测试函数,打印字符串
void PrintElem(SString S) {
int i;
for(i = 1; i <= S[0]; i++) {
printf("%c", S[i]);
}
printf("\n");
}
+106
View File
@@ -0,0 +1,106 @@
/*=======================
* KMP算法
*
* 包含算法: 4.6、4.7、4.8
========================*/
#include "KMP.h" //**▲04 串**//
/*
* ████████ 算法4.6 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.该实现用到了KMP算法,是一种比较高效的字符串匹配方式
* 2.教材中没有next参数
*/
int Index_KMP(SString S, SString T, int pos, int next[]) {
int i = pos;
int j = 1;
if(pos < 1) {
return 0;
}
// 比较字符串
while(i <= S[0] && j <= T[0]) {
/*
* 两种情形:
* 1.在模式串的第一个字符处就失配
* 2.主串和模式串处的字符相等
*/
if(j == 0 || S[i] == T[j]) {
i++;
j++;
} else {
// 失配时回到前一个适当的位置
j = next[j];
}
}
if(j > T[0]) {
// 匹配成功,返回匹配位置
return i - T[0];
} else {
// 匹配失败
return 0;
}
}
/*
* ████████ 算法4.7 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
*/
void get_next(SString T, int next[]) {
int i = 1;
int j = 0;
// 模式串第一个字符处失配时,模式串需要从头比较,主串需要前进到下一个位置比较
next[1] = 0;
// 遍历模式串上的字符
while(i < T[0]) {
if(j == 0 || T[i] == T[j]) {
i++;
j++;
next[i] = j;
} else {
j = next[j];
}
}
}
/*
* ████████ 算法4.8 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
* 这是一个优化后的版本,效率较算法4.7有所提高。
*/
void get_nextval(SString T, int nextval[]) {
int i = 1;
int j = 0;
// 模式串第一个字符处失配时,模式串需要从头比较,主串需要前进到下一个位置比较
nextval[1] = 0;
// 遍历模式串上的字符
while(i < T[0]) {
if(j==0 || T[i] == T[j]) {
i++;
j++;
if(T[i] != T[j]) {
nextval[i] = j;
} else {
nextval[i] = nextval[j];
}
} else {
j = nextval[j];
}
}
}
+43
View File
@@ -0,0 +1,43 @@
/*=======================
* KMP算法
*
* 包含算法: 4.6、4.7、4.8
========================*/
#ifndef KMP_H
#define KMP_H
#include <stdio.h>
#include <stdlib.h>
#include "SString.h" //**▲04 串**//
/*
* ████████ 算法4.6 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.该实现用到了KMP算法,是一种比较高效的字符串匹配方式
* 2.教材中没有next参数
*/
int Index_KMP(SString S, SString T, int pos, int next[]);
/*
* ████████ 算法4.7 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
*/
void get_next(SString T, int next[]);
/*
* ████████ 算法4.8 ████████
*
* 计算模式串的“失配数组”,用于KMP算法。
* 这是一个优化后的版本,效率较算法4.7有所提高。
*/
void get_nextval(SString T, int nextval[]);
#endif
+33
View File
@@ -0,0 +1,33 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#include "SString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars) {
int i, len;
len = (int) strlen(chars);
// chars过长
if(len > MAXSTRLEN) {
return ERROR;
}
T[0] = len;
for(i = 1; i <= len; i++) {
T[i] = chars[i - 1];
}
return OK;
}
+36
View File
@@ -0,0 +1,36 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#ifndef SSTRING_H
#define SSTRING_H
#include <stdio.h>
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAXSTRLEN 255 // 顺序串的最大串长
/*
* 串的顺序存储类型定义
*
* 注:有效元素从SString的1号单元开始存储
* SString的0号单元用来存储其长度
*/
typedef unsigned char SString[MAXSTRLEN + 1]; // 0号单元存放串的长度
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars);
#endif
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{FA2740D7-2D96-4F57-AE79-FCDA5C13CA86}</ProjectGuid>
<RootNamespace>My0405_WordList</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(SolutionDir)\..\Status;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>$(SolutionDir)\..\Status\Status.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ELinkList.c" />
<ClCompile Include="HString.c" />
<ClCompile Include="WordList-main.c" />
<ClCompile Include="WordList.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ELinkList.h" />
<ClInclude Include="HString.h" />
<ClInclude Include="WordList.h" />
</ItemGroup>
<ItemGroup>
<None Include="TestData.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ELinkList.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="HString.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="WordList.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="WordList-main.c">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ELinkList.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="HString.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="WordList.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="TestData.txt">
<Filter>资源文件</Filter>
</None>
</ItemGroup>
</Project>
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>
@@ -0,0 +1,95 @@
/*=======================
* 扩展的单链表(线性链表)
*
* 包含算法: 2.20
========================*/
#include "ELinkList.h" //**▲02 线性表**//
/*━━━━━━━━━━━━━━━━━━━━━━ 内存操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 内存分配
*
* 为线性链表申请一个结点,并存入指定的数据e。
*
*【备注】
* static修饰的含义是该函数仅限当前文件内使用
*/
Status MakeNode(Link* p, ElemType e) {
if(p == NULL) {
return ERROR;
}
// 申请空间
*p = (Link) malloc(sizeof(LNode));
if(*p == NULL) {
// 这里没有退出程序,而是返回错误提示
return ERROR;
}
(*p)->data = e;
(*p)->next = NULL;
return OK;
}
/*━━━━━━━━━━━━━━━━━━━━━━ 链表常规操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 初始化
*
* 初始化成功则返回OK,否则返回ERROR。
*/
Status InitList(ELinkList* L) {
Link p;
if(L == NULL) {
return ERROR;
}
// 创建头结点
p = (Link) malloc(sizeof(LNode));
if(p == NULL) {
exit(OVERFLOW);
}
p->next = NULL;
// 只有头结点时,首位游标指向自身
(*L).head = (*L).tail = p;
(*L).len = 0;
return OK;
}
/*━━━━━━━━━━━━━━━━━━━━━━ 链表扩展操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 向尾部添加
*
* 将s所指的一串结点链接在链表L后面
*/
Status Append(ELinkList* L, Link s) {
int count;
if(L == NULL || (*L).head == NULL || s == NULL) {
return ERROR;
}
count = 0;
(*L).tail->next = s;
// 确定新的尾结点位置
while(s != NULL) {
(*L).tail = s;
s = s->next;
count++;
}
(*L).len += count;
return OK;
}
@@ -0,0 +1,75 @@
/*=======================
* 扩展的单链表(线性链表)
*
* 包含算法: 2.20
========================*/
#ifndef ELINKLIST_H
#define ELINKLIST_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <limits.h> // 提供一些极限常量
#include "Status.h" //**▲01 绪论**//
/*
* ████ 注意 ████
*
* 教材中的线性链表命名为LinkList,
* 这里为了与单链表区分,故将其命名为ELinkList。
* 线性链表可以理解成对普通链表的一种扩展。
*/
/* 线性链表元素类型定义 */
typedef int ElemType;
/*
* 线性链表结构
*
* 注:这里的线性链表存在头结点
*/
typedef struct LNode {
ElemType data;
struct LNode* next;
} LNode, * Link, * Position;
/* 维护线性链表头尾指针及长度信息 */
typedef struct {
Link head, tail; // 分别指向线性链表中的头结点和尾结点
int len; // 指示线性链表中数据元素的个数
} ELinkList;
/*━━━━━━━━━━━━━━━━━━━━━━ 内存操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 内存分配
*
* 为线性链表申请一个结点,并存入指定的数据e。
*
*【备注】
* static修饰的含义是该函数仅限当前文件内使用
*/
Status MakeNode(Link* p, ElemType e);
/*━━━━━━━━━━━━━━━━━━━━━━ 链表常规操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 初始化
*
* 初始化成功则返回OK,否则返回ERROR。
*/
Status InitList(ELinkList* L);
/*━━━━━━━━━━━━━━━━━━━━━━ 链表扩展操作 ━━━━━━━━━━━━━━━━━━━━━━*/
/*
* 向尾部添加
*
* 将s所指的一串结点链接在链表L后面
*/
Status Append(ELinkList* L, Link s);
#endif
@@ -0,0 +1,95 @@
/*=========================
* 串的堆分配存储表示(堆串)
*
* 包含算法: 4.4
==========================*/
#include "HString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(HString* T, const char* chars) {
int i, j;
// 求chars的长度
i = (int) strlen(chars);
// 没有有效元素
if(i == 0) {
(*T).ch = NULL;
(*T).length = 0;
return OK;
}
// 存在有效元素时,需要分配存储空间
(*T).ch = (char*) malloc(i * sizeof(char));
if(!((*T).ch)) {
exit(OVERFLOW);
}
for(j = 0; j < i; j++) {
(*T).ch[j] = chars[j];
}
(*T).length = i;
return OK;
}
/*
* 比较
*
* 比较串S和串T,返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrCompare(HString S, HString T) {
int i;
for(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;
}
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(HString* T, HString S) {
int i;
if(S.length == 0) {
(*T).ch = NULL;
(*T).length = 0;
} else {
// 分配空间
(*T).ch = (char*) malloc(S.length * sizeof(char));
if(!(*T).ch) {
exit(OVERFLOW);
}
// 复制元素
for(i = 0; i < S.length; i++) {
(*T).ch[i] = S.ch[i];
}
// 复制长度信息
(*T).length = S.length;
}
return OK;
}
@@ -0,0 +1,53 @@
/*=========================
* 串的堆分配存储表示(堆串)
*
* 包含算法: 4.4
==========================*/
#ifndef HSTRING
#define HSTRING
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/*
* 串的堆存储表示
*
* 注:有效元素从ch的0号单元开始存储
*/
typedef struct {
char* ch; // 若是非空串,则按串长分配存储区,否则ch为NULL
int length;
} HString;
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(HString* T, const char* chars);
/*
* 比较
*
* 比较串S和串T,返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrCompare(HString S, HString T);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(HString* T, HString S);
#endif
@@ -0,0 +1,7 @@
Êé ºÅ Êé Ãû
005 Computer Data Structures
010 Introduction to Data Structures
023 Fundamentals of Data Structures
034 The Design and Analysis of Computer Algorithms
050 Introduction to Numerical Analysis
067 Numerical Analysis
@@ -0,0 +1,27 @@
#include <stdio.h> // 提供system原型
#include "WordList.h" //**▲04 串**//
int main(int argc, char** argv) {
FILE* fp;
char line[MaxLineLen];
char* bookinfo = "TestData.txt"; // 书目文件名
char* bookidx = "BookIdx.txt"; // 关键词索引文件名
// 创建索引表
Main(bookinfo, bookidx);
// 显示索引表到屏幕
if((fp = fopen(bookidx, "r"))!=NULL) {
printf("---------索引表生成功!---------\n\n");
while(feof(fp)==FALSE) {
fgets(line, MaxLineLen, fp);
printf("%s", line);
}
} else {
printf("---------未发现索引表!---------\n");
}
return 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,130 @@
/*===========================================
* 索引表
*
* 包含算法: 4.9、4.10、4.11、4.12、4.13、4.14
============================================*/
#ifndef WORDLIST_H
#define WORDLIST_H
#include <stdio.h> // 提供fopen、fclose、feof、fgets原型
#include <stdlib.h> // 提供exit、strtol原型
#include <string.h> // 提供strlen、strcmpi、strlwr原型
#include "Status.h" //**▲01 绪论**//
#include "ELinkList.h" //**▲02 线性表**//
#include "HString.h" //**▲04 串**//
/* 宏定义 */
#define MaxBookNum 1000 // 允许的最大书目数(假设最多只对1000本书建索引表)
#define MaxKeyNum 2500 // 索引表最大容量(索引项数量的最大值)
#define MaxLineLen 500 // 书目串(行)的最大长度
#define MaxWordNum 100 // 词表的最大容量
/* 类型定义 */
// 布尔类型
typedef Status Boolean;
// 词表类型(顺序表)
typedef struct {
char* item[MaxWordNum]; // 词表集合
int last; // 词表的长度
} WordListType;
// 索引项类型(索引表的行)
typedef struct {
HString key; // 关键词
ELinkList bnolist; // 存放书号索引的链表
} IdxTermType;
/*
* 索引表类型
*
*【注】
* 0号单元存储表头信息,这一点与教材有所不同
*/
typedef struct {
IdxTermType item[MaxKeyNum + 1]; // 索引项的集合
int last; // 索引表中包含的索引项数目
} IdxListType;
/* 全局变量(变量名称前面都加了g标记) */
// 书目缓存区
char gBuf[MaxLineLen];
// 关键词词表(普通词表),已经排除了常用词
WordListType gWdList;
/*
* ████████ 算法4.9 ████████
*
* 从文件bookinfo中读取书目信息,并依此创建相应的关键词索引表,然后将索引表写入文件bookidx。
*/
void Main(char* bookinfo, char* bookidx);
/*
* 初始化索引表
*
*【注】
* 教材中将索引表表头置为空串,但这里设定了一个有意义的表头
*/
void InitIdxList(IdxListType* idxlist);
/*
* 从文件f中读取一条书目信息存入书目缓冲区gBuf。
*/
void GetLine(FILE* f);
/*
* 从缓冲区gBuf中提取书名关键词到词表gWdList,书号存入bno。
*/
void ExtractKeyWord(ElemType* bno);
/*
* ████████ 算法4.10 ████████
*
* 将书号bno对应的书名关键词按词典顺序插入到索引表idxlist。
*/
Status InsIdxList(IdxListType* idxlist, int bno);
/*
* ████████ 算法4.11 ████████
*
* 用wd返回词表gWdList中第i个关键词。
*/
void GetWord(int i, HString* wd);
/*
* ████████ 算法4.12 ████████
*
* 查询在索引表idxlist中是否存在与wd相等的关键词。
* 若存在,则返回wd在词表中的位置,并置b为TRUE。
* 若不存在,则返回wd应插入的位置,并置b为FALSE。
*/
int Locate(IdxListType idxlist, HString wd, Boolean* b);
/*
* ████████ 算法4.13 ████████
*
* 在索引表的索引i(>=0)处插入关键词wd,并初始化书号索引的链表为空表。
*/
void InsertNewKey(IdxListType* idxlist, int i, HString wd);
/*
* ████████ 算法4.14 ████████
*
* 为索引表在索引i(>0)处的关键词插入书号。
*/
Status InsertBook(IdxListType* idxlist, int i, int bno);
/*
* 将生成的索引表idxlist输出到文件g。
*/
void PutText(FILE* g, IdxListType idxlist);
// 判断str是否为常用词
static Status isCommonWords(char* str);
#endif
Binary file not shown.
+12
View File
@@ -47,6 +47,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "0402_HString", "0402_HStrin
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "0403_LString", "0403_LString\0403_LString.vcxproj", "{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "0404_KMP", "0404_KMP\0404_KMP.vcxproj", "{5D2A1F0B-F177-43A9-873A-56C7E08E6987}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "0405_WordList", "0405_WordList\0405_WordList.vcxproj", "{FA2740D7-2D96-4F57-AE79-FCDA5C13CA86}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -145,6 +149,14 @@ Global
{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}.Debug|Win32.Build.0 = Debug|Win32
{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}.Release|Win32.ActiveCfg = Release|Win32
{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}.Release|Win32.Build.0 = Release|Win32
{5D2A1F0B-F177-43A9-873A-56C7E08E6987}.Debug|Win32.ActiveCfg = Debug|Win32
{5D2A1F0B-F177-43A9-873A-56C7E08E6987}.Debug|Win32.Build.0 = Debug|Win32
{5D2A1F0B-F177-43A9-873A-56C7E08E6987}.Release|Win32.ActiveCfg = Release|Win32
{5D2A1F0B-F177-43A9-873A-56C7E08E6987}.Release|Win32.Build.0 = Release|Win32
{FA2740D7-2D96-4F57-AE79-FCDA5C13CA86}.Debug|Win32.ActiveCfg = Debug|Win32
{FA2740D7-2D96-4F57-AE79-FCDA5C13CA86}.Debug|Win32.Build.0 = Debug|Win32
{FA2740D7-2D96-4F57-AE79-FCDA5C13CA86}.Release|Win32.ActiveCfg = Release|Win32
{FA2740D7-2D96-4F57-AE79-FCDA5C13CA86}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Binary file not shown.