版权声明:个人整理,仅供参考,请勿转载,如有侵权,请联系[email protected] https://blog.csdn.net/mooe1011/article/details/88089325
考研时个人整理的,参考王道、严蔚敏等数据结构。
上一章——线性表:https://blog.csdn.net/mooe1011/article/details/88036093
下一章——树:https://blog.csdn.net/mooe1011/article/details/88089462
1. 栈
- 初始化S.top=-1,栈顶元素S.data[S.top]
- 注 如果栈顶指针为S.top=0,则进栈S.data[S.top++]=x,出栈x=S.data[–S.top],相应栈空栈满条件也会变化
- 共享栈 topl(左边)=-1,topr(右边)=MaxSize为空;当topr-topl=1为满
- 链式栈Lhead指向栈顶元素
- 链式入队,相当于头插法,p->next=Lhead->next;Lhead->next=p;
- n个不同元素进栈,出栈序列为(卡特兰数):
- 代码
顺序栈
#define MaxSize 50
typedef struct {
int data[MaxSize];
int top;
}SqStack; //与顺序表差不多
链式栈
typedef struct LinkNode{
int data;
struct LinkNode *next;
}*Listack;
-
检查越界
- 栈满if(S.top==MaxSize-1)
- 栈空if(S.top==-1)
-
进出栈
- 进栈 S.data[++S.top]=x; (先加)
- 出栈 x=S.data[S.top–]; (后减)
-
判断栈序列是否合法
int Judge (char A[]){
int i=j=k=0;
while(A[i]!='\0'){
switch(A[i]){
case 'I':j++;break; //I代表入栈,O代表出栈,IOOO非法,IIOO合法
case 'O':k++;
if (k>j){
printf("非法\n");exit(0);
}
}
i++;
}
if (j!=k){
printf("非法\n");
return false;
} else {
printf("合法\n");
return true;
}
}
2. 队列
- 初始化:Q.front=Q.rear=0;
- 出队:Q.front=(Q.front+1)%MaxSize;
- 入队:Q.rear=(Q.rear+1)%MaxSize;
- 队满:(Q.rear+1)%MaxSize==Q.front
- 队空:Q.front=Q.rear(牺牲一个单元来区分队空) / 链表则是Q.front== NULL&&Q.rear== NULL;
- 队长:(Q.rear-Q.front+MaxSize)%MaxSize
- 链表删除元素时,只有一个结点时,删除后队列为空,要修改尾指针rear=front
- 代码
- 顺序
#define MaxSize 50
typedef struct{
int data[MaxSize];
int front,rear;
}SqQueue;
- 入队
if ((Q.rear+1)%MaxSize==Q.front)
return false;
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%MaxSize;
- 出队
if (Q.rear==Q.front)
return false;
x=Q.data[Q.front];
Q.front=(Q.front+1)%MaxSize;
- 链表,Q.rear指向链尾
typedef struct{ //结点
int data;
struct LinkNode *Next;
}LinkNode;
typedef struct{ //同时带头尾指针的单链表
LinkNode *front,*rear;
}LinkQueue;
-
初始化
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
Q.front->next=NULL; -
入队
s=(LinkNode*)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
Q.rear->next=s;
Q.rear=s;
- 出队
if(Q.front==Q.rear) return false;
p=Q.front->next;
x=p->data;
Q.front->next=p->next;
if(Q.rear==p) //只有一个结点
Q.rear=Q.front;
free(q);
3. 应用
- 栈的应用:括号匹配、迷宫求解、进制转换; 队的应用:缓冲区、广度优先搜索、树的层次遍历
-
括号匹配
bool BracketCheck(char *str){ InitStack(s); int i=0; while (str[i]!='\0'){ switch(str[i]){ case '(':Push(S,'(');break; case '[':Push(S,'[');break; case '{':Push(S,'{');break; case ')':Pop(S,e); if(e!='(') return false; break; .... //其他同理 default :break; } i++; } if (!IsEmpty(S)){ printf("不匹配\n"); return false; } else { printf("匹配\n"); return true; } }
-
后缀式求值
int Op(int a,char op,int b){
switch(Op){
case '+':return a+b;break;
case '-':return a-b;break;
case '*':return a*b;break;
case '/':
if(b==0){
cout<<"ERROR"<<endl;
return false;
} else return a/b;
}
}
int com(char exp[]){
int a,b,c,i=0; //a、b为操作数;c为结果
char Op;
InitStack(s);
while (exp[i]!='\0'){
if(exp[i]>='0'&&exp[i]<='9'){ //注意只算一位就可以了
Push(S,exp[i]-'0'); //字符型转换为整形
} else {
Op=exp[i];
Pop(S,b);
Pop(S,a);
c=Op(a,Op,b);
Push(S,c);
}
}
}
4. 矩阵压缩存储
-
数组
- 一维:LOC(ai)=LOC(a0)+i*L
- 二维(以行优先,h为列下标):LOC(ai,j)=LOC(a0,0)+[i*(h+1)+j]*L
-
矩阵压缩
- 对称:n阶压缩后有(1+n)n/2个元素;
ai,j与数组Bk的关系为(k从零开始)- 当i>=j时,下三角及对角线元素,
- 当i<j时,上三角元素,
- 下三角(上三角类似,具体看书):压缩后有(1+n)n/2+1个元素;
- 当i>=j时,下三角及对角线元素,
- 当i<j时,上三角元素,全为0;
- 带状矩阵 下标k=行i×2+列j-3
- 稀疏矩阵 (行标、列标、值)
- 对称:n阶压缩后有(1+n)n/2个元素;
5. 广义表
- 线性表的推广
- 第一个元素a1称为表头,其余称为表尾
- 列表的元素可以是子表,子表的元素还可以是子表
- 广义表表尾总是广义表(真题)
- A=(),B=(e),D=(A,B,C)
- C=(a,(b,c,d))表示长度为2,两个元素,分别为a和子表(b,c,d)
- Gethead(B)=e;GetTail(B)=(),空表,没有尾
- Gethead(D)=A;GetTail(D)=(B,C),出第一个为表头,其余为表尾
- GetHead((B,C))=B,GetTail((B,C))=©,注意括号
如果您看了这篇文章觉得有用的话,请随意打赏,您的支持将鼓励我继续创作,谢谢!