文章目录
4.2 栈的定义
- 栈定义:是限定仅在表尾进行插入和删除的线性表
- 允许插入和删除的一端叫栈顶,另一端叫栈底
- FILO
- 栈的插入操作进栈(压栈、入栈)
- 栈的删除操作出栈(弹栈)
4.3 栈的抽象数据类型
Data
Operation
InitStact(*S);
DestoryStack(*S);
ClearStack(*S);
StackEmpty(S);
GetTop(S,*e);
Push(*S,e); //入栈
Pop(*S,*e);//出栈
StackLength(S);
4.4 栈的顺序存储结构及实现
typedef int ElemType;
typedef struct{
ElemType data[MAXSIZE];
int top; //栈顶指针
}SqStack;
4.4.2 进栈操作
Status Push(SqStack *S,ElemType e){
if(S->top == MAXSIZE - 1){
return ERROR;
}
S->top++;
S->data[S->top] = e;
return OK;
}
4.4.3 出栈操作
Status Pop(SqStack *S,ElemType *e){
if(S->top == -1){
return ERROR;
}
*e = S->data[S->top];
S->top--;
return OK;
}
4.5 两栈共享空间
typedef struct{
ElemType data[MAXSIZE];
int top1; //栈1栈顶指针
int top2; //栈2栈顶指针
}SqDoubleStack;
//入栈操作
//stackNum 判断 栈1 还是 栈2
Status Push(SqDoubleStack *S,ElemType e,int stackNum){
it(S->top1 + 1 == S->top2){
return ERROR;
}
if(stackNum == 1){
S->data[++S->top1] = e;
}else if {
S->data[--S->top2] = e;
}
}
//出栈操作
Status Pop(SqDoubleStack *S,ElemType *e,int stackNum){
if(stackNum == 1){
if(S->top1==-1){
return ERROR;
}
*e = S->data[S->top1--];
} else if {
if(S->top2==MAXSIZE){
return ERROR;
}
*e = S->datap[S->top2++];
}
it(S->top1 + 1 == S->top2){
return ERROR;
}
if(stackNum == 1){
S->data[++S->top1] = e;
}else if {
S->data[--S->top2] = e;
}
}
4.6 栈的链式存储结构及实现
4.6.1 栈的链式存储结构
- 简称链表。
- 空栈:top = NULL;
//栈结点
typedef struct StackNode{
ElemType data; //元素
struct StackNode *next; //结点指针
}StackNode,*LinkStackPtr;
typedef struct LinkStack{
LinkStackPtr top;
int count;
}LinkStack;
4.6.2 进栈操作
//入栈
Status Push(LinkStact *S,ElemType e){
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
s->data = e;
s->next = S->top; //把栈顶元素赋值给新结点直接后继元素
S->top = s; //将新新结点 s 赋值给 栈顶元素;
S->count++; //长度+1
return OK
}
//出栈
Status Pop(LinkStack *S,ElemType *e){
ListStackPtr p;
if(StackEmpty(*s)){
return ERROR;
}
*e = S->top->data;
p=S->top; //将栈顶元素赋值给p;
S->top = S->top->next; //栈顶元素指针下移一位
free(p); //释放p结点
S->count--; //长度-1
return OK;
}
- 如果栈的使用哦过程中元素变化不可预料,使用链栈,反之只用顺序栈。
4.7 栈的作用
4.8 栈的应用–递归
4.8.1 菲波那切数列
int Fbi(int i){
if(i < 2){
return i == 0 ? 0 : 1;
} else{
return Fbi(i-1) + Fbi(i+2);
}
}
4.8.2 递归定义
- 直接调用自己或通过一系列调用语句间接调用自己函数,称为递归函数。
4.9 栈的应用-四则运算表达式求值
4.9.1 后缀(逆波兰)表达法定义
中缀表达式:9 + (3-1) * 3 + 10 / 2
后缀表达式:9 3 1 - 3 * 10 2 / +
所有的符号都是在运算数字后面出现
4.9.2 后缀表达式计算结果
- 从左到右,遇到数字就进栈,遇到符号,就将处于栈顶的两个数字出栈,进行运算,运算结果进栈。
4.9.3 中缀表达式转后缀表达式
1.从左到右,数字输出,符号,判断栈顶符号优先级,是右括号或优先级低于栈顶符号,这栈顶元素依次出栈并输出,并将当前符号出栈。
4.10 队列的定义
- 只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
- 先进先出(FIFO)
- 允许插入一端叫队尾,允许删除一端叫对头
ADT
Data
Operation
InitQueue(*Q);
DestroyQueue(*Q);
ClrearQueue(*Q);
QueueEmpty(Q);
GetHead(Q,*e);
EnQueue(*Q,e); //插入
DeQueue(*Q,*e); //删除
QueueLength(Q);
4.12 循环队列
| | | a3| a4 | a5 |
font rear
假溢出
4.12.2 循环队列定义
- 队列的这种头尾相接的顺序存储结构称为循环队列
- 问题
当 fron == rear 队列满了还是空队列
1.设置标志位 flag
2.设置一个空闲单元
- 队列满(rear + 1)% QueueSize == front
- 计算队列长度:(rear - front + QueueSize) % QueueSize
//结构
typedef int QElemType;
typedef struct{
QElemType data[MAXSIZE];
int font;
int rear;
}SqQueue;
//初始化
Status InitQueue(SqQueue *Q){
Q->font = 0;
Q->rear = 0;
return OK;
}
//长度
int QueueLength(SqQueue Q){
retutn (Q.rear - Q.font + MAXSIZE) % MAXSIZE;
}
//插入
Status EnQueue(SqQueue *Q,QElemType e){
if((Q->rear + 1) % MAXSIZE == Q->front){
return ERROR;
} else {
Q->data[Q->rear] = e;
Q->rear = (Q->rear + 1) % MAXSIZE; //rear 移动一位
return OK;
}
}
//删除
Status DeQueue(SqQueue *Q,QElemType *e){
if(Q->front == Q->rear){
return ERROR;
}else{
*e = Q->data[Q->front];
Q->front = (Q->front + 1) % MAXSIZE;//font 向后移动一位
}
}
4.13 队列链式存储结构及实现
- 其实就是线性表的单链表,尾进头出,链队列。
//结构
typedef int QElemType;
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr ;
typedef struct {
QueuePtr front,rear; //对头、队尾指针
}LinkQueue;
//入队
Status Enqueue(LinkQueue *Q,QElemType e){
QueuePtr s = (QueuePtr) malloc(sizeof(QNode));
if(!s){
exit(OVERFLOW);
}
s->data = e;
s->next = NULL;
Q->rear->next = s;
Q->rear=s; //后移
return OK;
}
//出队
Status DeQueue(LinkQueue *Q,QElemType *e){
QueuePtr p;
if(Q->front == Q->rear){
return ERROE;
}
p = Q->font->next;
*e = p->data;
Q->front->next = p->next;
if(Q->rear == p){ //如果对头是队尾,删除后将rear指向头结点
Q->rear = Q->front;
}
free(p);
return OK;
}