数据结构第一次小结
数据结构
一、思维导图
二、重要概念的笔记
1、顺序存储结构中只需存放元素自身的信息,因此,存储密度大,空间利用率高
2、顺序表的元素位置可以用元素的下标通过简单的解析式计算出来,所以可以随机存取元素。
3、单链表:在每个结点中包含有数据域外,只设置一个指针域,用于指向其后继结点。
4、双链表:在每个结点中包含有数值域外,设置有两个指针域,分别用于指向其前驱结点和后继结点。
5、循环链表:循环链表是另一种形式的链式存储结构。它的特点是表中尾结点的指针域不变,而是指向表头结点,整个链表形成一个环
6、栈:进栈: Push(S,x)、可形象地理解为压入,这时栈中会多一个元素。
退栈: Pop(S) 、 可形象地理解为弹出,弹出后栈中就无此元素了。
取栈顶元素:StackTop(S),不同与弹出,只是使用栈顶元素的值,该元素仍在栈顶不会改变。
7、 可以用栈来转换一些递归函数。
8循环队列判断队空条件:
r.front==r.rear;
判断队满的条件:
r.front==(r.rear+1)%MaxSize;
三、疑难问题及解决方案
1、计算next[j]函数以及nextval[j]的值;
解决方案:刚开始由于概念过于抽象导致无法理解,后面通过多次画图以及课堂上的练习从而掌握;
其做法如下:KMP算法的关键在于求算next[]数组的值,即求算模式串每个位置处的最长后缀与前缀相同的长度,下面按照递推的思想总结一下求解next[]数组:
根据定义next[1]=0,假设next[j]=k, 即P[1..k-1] == P[j-k,j-1]
1)若P[j] == P[k],则有P[1..k] == P[j-k,j],很显然,如果next[j]=k; 则next[j+1]=next[j]+1=k+1;否则next[j+1]=k+1!=next[j]+1;(当初就想着记公式简单可以直接套用呢,结果只记住next[j+1]=next[j]+1以至于后来迷糊了)
2)若P[j]!=P[k],则可以把其看做模式匹配的问题,即匹配失败的时候,k值如何移动,显然k=next[k];
然后在根据next值求nextval;
部分代码如下:
void getNext(char *p,int *next)
{
int j,k;
next[1]=0;
j=1;
k=0;
while(j<strlen(p)-1)
{
if(k==0||p[j]==p[k]) //匹配的情况下,p[j]==p[k],next[j+1]=k+1;
{
j++;
k++;
next[j]=k;
}
else //p[j]!=p[k],k=next[k]
k=next[k];
}
}
/* 求模式串T的next函数修正值并存入数组nextval */
void get_nextval(String T, int *nextval)
{
int i,j;
i=1;
j=0;
nextval[1]=0;
while (i<T[0]) /* 此处T[0]表示串T的长度 */
{
if(j==0 || T[i]== T[j]) /* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
{
++i;
++j;
if (T[i]!=T[j]) /* 若当前字符与前缀字符不同 */
nextval[i] = j; /* 则当前的j为nextval在i位置的值 */
else
nextval[i] = nextval[j]; /* 如果与前缀字符相同,则将前缀字符的 */
/* nextval值赋值给nextval在i位置的值 */
}
else
j= nextval[j]; /* 若字符不相同,则j值回溯 */
}
}