第四章学习小结
1.本章学习内容小结:
1)串(穿的数据约束为字符集)
顺序存储:
//串的定长顺序存储结构 typedef struct { char ch[MAXLEN+1];//存储串的一维数组,MAXLEN为串的最大长度 int length;//串的当前长度 }SString; //串的堆式顺序存储结构 typedef struct { char *ch; int length;//串的当前长度 }SString;
链式存储:
#define CHUNKSIZE 80//块大小 typedef struct Chunk {//定义结点 char ch[CHUNKSIZE]; struct Chunk *next; }Chunk; typedef struct { Chunk *head,*tail;//头尾指针 int length;//串的当前长度 }Lstring;
模式匹配(KMP算法):
- 利用已经部分匹配这个有效信息,保持i指针不回溯,通过修改j指针,让模式串尽量地移动到有效的位置,关键在于当某一个字符与主串不匹配时,j指针要移动修改到哪里。
- 当前si和pj比较不相等,(1)当模式串中不存在可相互重叠的真子串,下一次可直接比较si和p0;(2)当模式串中存在可相互重叠的真子串时,j要移动的下一个位置为k,k满足:模式串中最前面的k个字符和j之前的最后k个字符是一样的。
- 计算每一个位置j对应的k,用一个数组next来保存,next[j] = k,表示当T[i] != P[j]时,j指针的下一个位置。
//j从0开始 position KMP(string a,string b) { int m=a.length(),n=b.length(); int p,q,*next; if(m<n) return 0; next=new int[n]; getNext(b,next,n); p=0; q=0; while(p<m&&q<n) { if(q==-1||a[p]==b[q])//当q为-1时,要移动的是p,q也要归0 { p++; q++; } else q=next[q];//不回溯 } return (q==n)?(p-n):0;//返回下标 } void getNext(string b,int *next)//int next[] { int n=b.length(); next[0]=-1; int j=0,k=-1; while(j<n-1) { if(k==-1||b[j]==b[k]) { ++j;++k; if(b[j]!=b[k]) next[j]=k; else next[j]=next[k];//当b[j] == b[next[j]] } else k=next[k]; } }
2)数组(是逻辑结构,区别于高级语言的数组,可以顺序、链式存储)
矩阵可以用数组存储 (稀疏矩阵:零多,非零元较少)
3)广义表 LS=(a1,a2……,an)长度为n,ai可以是单个元素(原子)或广义表(子表)
【A=():空表,长度为零 、 A=(a,(b,c))长度为2】
//---广义表的首尾链表存储结构---// typedef enum{ATOM,LIST}ElemTag; //ATOM == 0:原子,LIST == 1:字表 typedef struct GLNode{ ElemTag tag; //公共部分,用于区分原子节点和表节点 union share{ //原子节点和表节点的联合部分 AtomType atom; //atom是原子节点的值域,AtomTpye由用户定义 struct{struct GLNode *hp,*tp;}ptr;//ptr是表节点的指针域,ptr.hp和ptr.tp分别指向表头和表尾 }; }*GList
2.心得体会:
求两无序集合的交集(交集要有序):主要是时间复杂度的问题,还是先将两集合排序再按有序集合求交集的方法求出交集这趟才不会超时,其中排序经查询后用了sort函数;
模式匹配:最大的问题就是理解KMP,感觉算法里面的next函数的k的确定最绕;
3.目标回顾:课程进度跟着有点落后
目标:不松懈,不拖拉,认认真真跟进度,多花心思理解难点。