目录
一.栈
栈的定义
栈:栈其实就是一张特殊的线性表,他是一张只能在一头做插入和删除操作的线性表。
栈的特点:数据元素先进后出。
栈顶top:能够做插入和删除操作的一端。(top指向栈顶元素数组的下标)
空栈:不含任何数据元素的栈;规定top=-1。
插入操作叫:进栈、压栈、入栈。
删除操作叫:出栈、弹栈。
进栈出栈的不同情况
栈的特点是后进先出,那么不同的进栈方式就会对应不同的出栈方式。以下我们来看一个例子:
问题:现在有A、B、C三个元素依次放入栈中,有多少种不同的出栈方式?
我们已经知道栈的出栈只能是从栈顶一次出,那么不同的出栈方式其实是取决于不同的进栈方式的。下面我们来讨一下。
①:A B C 依次进入,对应的出栈顺序是:C B A
②:A进A 出,B进B出,C进C出,对应的出栈顺序:A B C
③:A B进,B A出,C进C出,对应的出栈顺序是:B A C
④:A B进,B出,C进,C A 出,对应的出栈顺序是: B C A
⑤:A进,A 出,B C 进,C B 出,对应的出栈顺序是:A C B
栈的顺序存储结构
栈的顺序存储可以对比线性表的顺序存储。
结构定义
typedef int SElemType;
typedef struct{
SElemType data[MAXSIZE];
int top;
}SqStack;
进栈操作
算法步骤:
- 判断栈是否已满
- 如果未满,栈顶指针移向下一个位置
- 将要插入的元素存在栈顶
typedef int Status;
Status push(SqStack *S,SElemType e){
if(S->top==MAXSIZE-1)//栈满
return ERROR;
S->top++;//栈顶挪向下一个位置
S->data[S->top]=e;//将e存到栈顶
return OK;
}
出栈操作
算法步骤:
- 判断栈是否为空
- 如果不空,返回将要删除位置的值
- top指针指向前一个位置
Status pop(SqStack *S,SElemType *e){
if(S->top ==-1)//栈空
return ERROR;
*e=S->data[S->top ];//记录将要删除的位置的值
S->top --;//栈顶指针向下移动一位
// free();没有动态分配不用释放内存
return OK;
}
共享空间
基本概念
两栈共享空间:用一个数组存两个栈,两个栈的栈底分别为数组的两头。让两个栈的元素向中间延伸。
栈空:top1=-1,top2=MAXSIZE-1(MAXSIZE为数组长度)
栈满:top1+1=top2
结构定义
typedef struct{
SElemType data[MAXSIZE];
int top1;
int top2;
}SqDoubleStack;
进栈操作
Status push(SqDoubleStack *S,SElemType e, int StackNumber){//用StackNumber区分是对栈1进行操作还是对栈2进行操作
if(S->top1-1==S->top2)//栈满
return ERROR;
if(StackNumber==1){//对1栈进行操作
S->top1++;
S->data [S->top1 ]=e;
}
else if(StackNumber==2){//对栈2进行操作
S->top2 --;
S->data [S->top2 ]=e;
}
return OK;
}
出栈操作
Status pop(SqDoubleStack *S,SElemType *e, int StackNumber){
if(S->top1 ==-1&&S->top2 ==MAXSIZE-1)//栈空
return ERROR;
if(StackNumber==1){
*e=S->data [S->top1];
S->top1--;
}
else if(StackNumber==2){
*e=S->data [S->top2];
S->top2--;
}
return OK;
}
栈的链式存储结构(链栈)
结构定义
typedef struct LinkStack{
SElemType data;
struct LinkStack *next;
int num;//记录表长
}LinkListNode,*LinkListStack;
//链表的头指针就相当于栈顶,不用再定义头指针,就把栈顶当作头指针来用
进栈操作
Status push(LinkListStack S,SElemType e){
//LinkListStack top;
LinkListStack p;
p=(LinkListStack)malloc(sizeof(LinkListNode));//为新节点分配空间
p->next =S->next ;
S->next=p;
p->data =e;
S->num++;
return OK;
}
出栈操作
Status pop(LinkListStack S,SElemType *e){
if(S->next ==NULL)
return ERROR;
LinkListStack p;
p=S->next ;
*e=p->data ;
S->next =p->next ;
free(p);
S->num --;
return OK;
}
四则运算表达式求值
二.队列
队列的定义
队列:一张只能在表头做删除操作,只能在表尾做插入操作的线性表。
如果把栈比作一个有瓶底的瓶子,那么队列就是一个没有瓶底的瓶子。栈只能在瓶口操作,队列在瓶底放入东西,在瓶口拿出东西。
队头:做删除操作的一头。
队尾:做插入操作的一头。
特点:先进先出
循环队列
由于在普通队列中,当队列头部的元素出队后,头指针后移,但头部空出的位置无法再利用,导致队列的空间浪费。所以出现了循环队列,循环队列通过使用数组,将队列的头尾连接在数组的两端,使得当队列尾到达数组的末尾时,它可以从数组的开始位置重新开始,形成一个循环。
循环队列:循环队列是一种基于数组或链表实现的队列数据结构,其特点在于队列的尾部和头部相邻,形成一个循环。
循环队列的两个指针:一个是队头指针(front),用于指向队列的第一个元素,另一个是队尾指针(rear),用于指向队列中最后一个元素的下一个位置。
队列为空:front=rear=0;
队列为满:(rear+1)%QueueSize=front;(QueueSize为队列的最大空间)
队列长度:lehgth=(rear - front + QueueSize)%QueueSize;
队尾后移:(rear + 1)%QueueSize;
队头后移:(front + 1)%QueueSize;
队列的顺序存储结构
结构定义
typedef int Elemtype;
typedef struct{
Elemtype data[MAXSIZE];
int front,rear;
}SqQueue;
初始化
Status InitQueue(SqQueue *Q){
Q->front =0;
Q->rear =0;
return OK;
}
入队操作
Status EnQueue(SqQueue *Q,Elemtype e){//用*Q才能够通过指针传递队列,并且 EnQueue 函数能够修改原始队列。
if((Q->rear+1)%MAXSIZE==Q->front)
return ERROR;
Q->data[Q->rear]=e;
Q->rear=(Q->rear +1)%MAXSIZE;
return OK;
}
出队操作
Status DeQueue(SqQueue *Q,Elemtype *e){
if(Q->front ==Q->rear )
return ERROR;
*e=Q->data[Q->front];
Q->front =(Q->front +1)%MAXSIZE;
return OK;
}
求队长
int QueueLength(SqQueue Q){
return (Q.rear -Q.front +MAXSIZE)%MAXSIZE;
}
队列的链式存储结构
链队列:对链表头做删除操作,对链表尾做插入操作的特殊链表。
front指针指向链表的头节点,rear指向链表的最后一个节点。
结构定义
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
QueuePtr front,rear;
}LinkQueue;
进栈操作
Status EnQueue(LinkQueue *LQ,QElemType e){
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));
LQ->rear->next =p;
LQ->rear =p;
return OK;
}
出栈操作
Status DeQueue(LinkQueue *QL,QElemType *e){
if(QL->front==QL->rear )//队列为空
return ERROR;
QueuePtr p;
p=QL->front->next ;
*e=p->data ;
QL->front->next =p->next ;
if(QL->rear ==p)//如果p节点就是队尾
QL->rear=QL->front; //将rear指向头节点,front就是头节点
free(p);
return OK;
}
注意这里用malloc和free函数要有头文件#include <stdlib.h>