p=(Lnode*)malloc(sizeof(LNode));//生成新结点
scanf(&p->data);//输入元素值
p->next=NULL;
if(L->head->next==NULL)L->head->next=p;
elseq->next=p;
q=p;//插入到表尾
}
}//CreateList_L2
4、循环链表:
最后一个结点的指针域的指针又指回第一个结点的链表。
和单链表的差别仅在于:
判别链表中最后一个结点的条件不再是“后继是否为空”,而是“后继是否为头结点”。
5、双向链表的操作特点:
1、“查询”和单链表相同;2、“插入”和“删除”时需要同时修改两个方向上的指针
TypedefstructDuLnode{
ElemTypedata;//数据域
structDuLNode*prior;//指向前驱的指针
structDuLNode*next;//指向后继的指针
}DuLNode;
TypedefstructDulList{
DulList*head;
}DullinkList;
插入:
在双向链表中的p结点前插入一个s结点
{s->prior=p->prior;/*①*/
s->next=p;/*②*/
p->prior->next=s;/*③*/
p->prior=s;/*④*/
}
删除:
在双向链表中删除p结点
{p->prior->next=p->next;/*①*/
p->next->prior=p->prior;/*②*/
free(p);/*③*/
}
第三章
1、栈、队列的特点:
☐从数据元素间的逻辑关系看是线性表
☐从操作方式与种类看不同于线性表:
栈与队列是操作受限的线性表
2、栈的基本概念栈---是限制仅在线性表的一端进行插入和删除运算的线性表。
栈顶(TOP)--允许插入和删除的一端。
栈底(bottom)--不允许插入和删除的一端。
空栈--表中没有元素。
栈--又称为后进先出的线性表
3、栈中元素的特性:
1、具有线性关系2、后进先出
4、栈的进栈出栈规则:
a)按序进栈:
有n个元素1,2,…,n,它们按1,2,…,n的次序进栈(i进栈时,1~(i-1)应该已经进栈);
b)栈顶出栈:
栈底最后出栈;
c)时进时出:
元素未完全进栈时,即可出栈。
5、栈的表示与实现
顺序栈即栈的顺序存储结构:
一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。
/*栈的顺序存储结构描述*/
#defineSTACK_INIT_SIZE100/*存储空间的初始分配量*/
#defineSTACKINCREMENT10/*存储空间的分配增量*/
typedefstruct{
SElemType*base;/*存储空间基址*/
inttop;/*栈顶指针*/
intstacksize;/*当前分配的存储容量*/
}SqStack;
1、附设一个栈底指针base,总是指向栈底。
2、附设一个栈顶指针top。
空栈时,top=base;非空栈时,总是指向栈顶元素+1的位置。
☐栈满s->top==s->stacksize
☐栈空s->top==0
☐插入一个栈顶元素,指针top增1;
☐删除一个栈顶元素,指针top减1;
☐非空栈中的栈顶指针始终在栈顶元素的下一个位置上
3、进栈出栈
voidStackPush_sq(sqStack*s,inte){
int*newbase;
if(s->top==s->stacksize)
{newbase=(int*)realloc(s->base,(s->stacksize+STACKINCRMENT)*sizeof(int));
if(!
newbase){printf("overflow!
");exit
(1);}
s->base=newbase;
s->stacksize+=STACKINCRMENT;
}
s->base[s->top]=e;
s->top++;
}
intStackPop_sq(sqStack*s){
if(s->top==0){
printf("thestackisempty!
\n");
exit
(1);}
else{s->top--;
return(s->base[s->top]);}
}
链栈:
注意:
链栈中指针的方向指向前驱结点!
例:
EXP=a×b+(c-d/e)×f
v前缀:
+×ab×-c/def
v中缀:
a×b+c-d/e×f
v后缀:
ab×cde/-f×+
6、队列
⏹队列:
只允许在表的一端进行插入,而在表的另一端进行删除的线性表。
☐队尾(rear)——允许插入的一端
☐队头(front)——允许删除的一端
⏹队列特点:
先进先出(FIFO)
7、队列类型的实现
⏹链队列——队列的链式表示和实现
⏹顺序队列——队列的顺序表示和实现用一组连续的存储单元依次存放队列中的元素
8、顺序队列运算时的头、尾指针变化
设两个指针front,rear,约定:
rear指示队尾元素;front指示队头元素前一位置初值front=rear=0
空队列条件:
Q.front==Q.rear
队列满:
Q.rear-Q.front=MAXQSIZE
入队列:
Q.base[rear++]=x;
出队列:
x=Q.base[++front];
存在问题:
设数组维数为M,则:
⏹当rear-front=m时,再有元素入队发生溢出——真溢出
⏹当rear已指向队尾,但队列前端仍有空位置时,再有元素入队发生溢出——假溢出!
队列的顺序存储结构
#defineMAXQSIZE100/*队列的最大长度*/
Typedefstruct{
QElemType*base;/*动态分配存储空间*/
intfront;/*头指针*/
intrear;/*尾指针*/
}SqQueue;
/*将循环队列Sq初始化置为空循环队列*/
voidInitQueue(SqQueue*Sq)
{Sq->base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemtype));
if(!
Sq->base)exit
(1);
Sq->front=Sq->rear=0;
}/*InitQueue*/
/*在循环队列Sq的尾部入队一个新元素x*/
voidEnQueue(SqQueue*Sq,ElemTypex)
{if((Sq->rear+1)%MAXQSIZE==Sq->front)
exit
(1);/*队列已满*/
Sq->base[Sq->rear]=x;
Sq->rear=(Sq->rear+1)%MAXQSIZE;
}/*EnQueue*/
/*循环队列Sq出队一个元素,并存人y中*/
intDelQueue(SqQueue*Sq)
{if(Sq->front==Sq->rear)
exit
(1);/*队列已空*/
y=Sq->base[Sq->front];
Sq->front=(Sq->front+1)%MAXQSIZE;
returny;
}/*DelQueue*/
9、循环队列:
将数组首尾相接(即:
base[0]连在base[m-1]之后)。
入/出队列运算
利用“模运算”,则:
Ø入队:
Q.rear=(Q.rear+1)%MAXQSIZE
Ø出队:
Q.front=(Q.front+1)%MAXQSIZE
即一个大小为MAXQSIZE的循环队列最多有MAXQSIZE-1个元素
队满和队空判断条件:
队空:
Q.rear=(Q.front)
队满:
(Q.rear+1)%MAXQSIZE=Q.front
10、链队列
typedefstructQNode{
QElemTypedata;
structQNode*next;
}QNode;
typedefstruct{
QNode*front;/*队头指针*/
QNode*rear;/*队尾指针*/
}LQueue;
/*在链队列Lq的尾部插入一个新的元素x*/
voidEnQueue_L(LQueue*Lq,ElemTypex)
{QNode*p;
p=(QNone*)malloc(sizeof(QNone));
p->data=x;
p->next=NULL;
Lq->rear->next=p;Lq->rear=p;
}/*EnQueue_L*/
/*删除队列Lq的队头元素,并存入y中*/
intDelQueue-L(LQueue*Lq){
if(Lq->front==Lq->rear)
exit
(1);/*队列已空*/
p=Lq->front->next;/*p指向队头结点*/
y=p->data;
Lq->front->next=p->next;
if(Lq->rear==p)
Lq->rear=Lq->front;/*尾指针指向头结点*/
free(p);
returny;
}/*DelQueue-L*/
第四章
一、1、串的基本概念
⏹串---由零个或多个字符组成的有限序列,一般记为:
s='a1a2...an'(n≥0)
⏹串中字符的个数n称为串的长度;零个字符,即长度为零的串称为空串,用或''表示。
空串不等于空格串,空格串:
由一个或多个空格组成的串
子串:
串中任意个连续的字符组成的子序列
主串:
包含子串的串相应地称为主串
相等:
两个串的长度相等,并且对应位置的字符都相同。
2、串结构与线性表结构的比较:
逻辑结构:
极为相似,区别仅在于串的数据对象约束为字符集。
基本操作:
有很大差别1、线性表大多以“单个元素”作为操作对象2、串通常以“串的整体”作为操作对象
3、串类型定义
4、串赋值StrAssign、串复制Strcopy、串比较StrCompare、求串长StrLength、串联接Concat以及求子串SubString等六种操作构成串类型的最小操作子集。
1、StrAssign(&T,chars)初始条件:
chars是字符串常量。
操作结果:
把chars赋为T的值。
等价于C语言中的strset函数
2、StrCopy(&T,S)初始条件:
串S存在。
操作结果:
由串S复制得串T。
等价于C语言中的strcpy函数
3、StrCompare(S,T)初始条件:
串S和T存在。
操作结果:
若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。
等价于C语言中的strcmp函数(按ASCII码值进行大小比较)
4、StrLength(S)初始条件:
串S存在。
操作结果:
返回S的元素个数,称为串的长度。
等价于C语言中的strlen函数
5、Concat(&T,S1,S2)初始条件:
串S1和S2存在。
操作结果:
用T返回由S1和S2联接而成的新串。
例如:
Concate(T,man,kind)求得T=mankind等价于C语言中的strcat函数
6、SubString(&Sub,S,pos,len)初始条件:
串S存在,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1。
操作结果:
用Sub返回串S的第pos个字符起长度为len的子串。
子串为“串”中的一个字符子序列。
例如:
SubString(sub,'commander',4,3),求得sub='man';
SubString(sub,'commander',1,9),求得sub='commander';
SubString(sub,'commander',9,1),求得sub='r';
起始位置pos和子串长度len之间存在约束关系,pos+len<=StrLength(S)+1
SubString('student',5,0)=?
——长度为0的子串为“合法”串
5、Index(S,T,pos)初始条件:
串S和T存在,T是非空串,1≤pos≤StrLength(S)。
操作结果:
若主串S中存在和串T值相同的子串,则返回它在主串S中第pos个字符之后第一次出现的位置;否则函数值为0。
“子串在主串中的位置”指子串中的第一个字符在主串中的位序。
假设S=abcaabcaaabc,T=bcaIndex(S,T,1)=2Index(S,T,3)=6Index(S,T,8)=0
6、Replace(&S,T,V)初始条件:
串S,T和V均已存在,且T是非空串。
操作结果:
用V替换主串S中出现的所有与(模式串)T相等的不重叠的子串。
例如:
假设S=abcaabcaaabca,T=bca若V=x,则经置换后得到S=abcaabcaaabca
7、StrInsert(&S,pos,T)初始条件:
串S和T存在,1≤pos≤StrLength(S)+1。
操作结果:
在串S的第pos个字符之前插入串T
例如:
S='chater',T='rac',则执行StrInsert(S,4,T)之后得到S='character'
二、串的表示和实现
1、定长顺序存储表示:
用一组地址连续的存储单元存储串值的字符序列,称为顺序串。
可用一个数组来表示。
特点:
①串的实际长度可在这个预定义长度的范围内随意设定,超过预定义长度的串值则被舍去,称之为“截断”。
②按这种串的表示方法实现的串运算时,其基本操作为“字符序列的复制”
顺序存储结构中,串操作的基本操作为“字符序列的复制”,其时间复杂度基于复制的字符序列的长度。
定长顺序串结构类型
#defineMAXSTRLEN150
typedefstruct{
charc[MAXSTRLEN];
intlen;
}SString;
2、堆分配存储表示:
特点:
仍以一组地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配而得的。
串操作实现的算法为:
先为新生成的串分配一个存储空间,然后进行串值的复制。
3、串的模式匹配算法
intIndex(SStringS,SStringT,intpos){//从主串s的下标pos起,串t第一次出现的位置,成功返回位置序号,不成功返回0
i=pos;j=1;//主串从pos开始,模式串从1开始
while(i<=S.len&&j<=T.len)
{
if(S.c[i]==T.c[i]){++i;++j;}//相等时,同时推进
else{i=i-j+2;j=1;}
}
if(j>T.len)returni-T.len;//匹配成功时,返回起始位置
elsereturn0;
}//Index
4、计算模式串的next函数值和修正的next函数值
第六章
一、树的定义
1、树型结构:
(非线性结构)至少存在一个数据元素有两个或两个以上的直接前驱(或直接后继)元素的数据结构。
树的定义:
是n(n≥0)个结点的有限集合T,对于任意一棵非空树,它满足:
有且仅有一个特定的称为根(root)的结点;当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,….,Tm,其中每个集合本身又是一棵树,称为根的子树。
上述树的定义是一个递归定义。
2、基本术语
结点:
包含一个数据元素及若干指向其子树的分支。
结点的度:
结点拥有的子树数。
叶子(或终端)结点:
度为零的结点。
分支(或非终端)结点:
度大于