【数据结构】课堂复习笔记3——栈与队列
发表于更新于
字数总计:1.5k阅读时长:6分钟阅读量: 杭州
编程【数据结构】课堂复习笔记3——栈与队列
Kendal学习的网课是青岛大学-王卓的数据结构与算法基础系列课程,可在bilibili上观看。并配合zjut课堂笔记整理,仅用于学习和复习
三、栈和队列
3.1 栈和队列的定义和特点
3.1.1 栈
- 定义:只能在表的一端(栈顶)进行插入和删除运算的线性表
- 逻辑结构:与线性表相同,仍为一对一关系
- 存储结构:用顺序栈或链栈存储均可,但以顺序栈更常见
- 运算规则:只能在栈顶运算,且访问结点时依照后进先出(LIFO)或先进后出(FILO)的原则
- 实现方式:基本操作有入栈、出栈、读栈顶元素值、建栈、判断栈满、栈空等
3.1.2 队列
- 定义:只能在表的一端(队尾)进行插入,在另一端(队头)进行删除运算的线性表
- 逻辑结构:与线性表相同,仍为一对一关系
- 存储结构:用顺序队列或链队存储均可
- 运算规则:先进先出(FIFO)
- 实现方式:关键是编写入队和出队函数,具体实现依顺序队或链队的不同而不同
3.2 栈的表示和操作的实现
3.2.1 顺序栈
顺序栈的表示:
#define MAXSIZE 100 typedef struct { SElemType *base; SElemType *top; int stacksize; }SqStack;
|
顺序栈的初始化:
Status InitStack( SqStack &S ) { S.base =new SElemType[MAXSIZE]; if( !S.base ) return OVERFLOW; S.top = S.base; S.stackSize = MAXSIZE; return OK; }
|
判断顺序栈是否为空:
bool StackEmpty( SqStack S ) { if(S.top == S.base) return true; else return false; }
|
求顺序栈的长度:
int StackLength( SqStack S ) { return S.top – S.base; }
|
清空顺序栈:
Status ClearStack( SqStack S ) { if( S.base ) S.top = S.base; return OK; }
|
销毁顺序栈:
Status DestroyStack( SqStack &S ) { if( S.base ) { delete S.base ; S.stacksize = 0; S.base = S.top = NULL; } return OK; }
|
顺序栈的入栈:
Status Push( SqStack &S, SElemType e) { if( S.top - S.base== S.stacksize ) return ERROR; *S.top++=e; return OK; }
|
顺序栈出栈:
Status Pop( SqStack &S, SElemType &e) { if( S.top == S.base ) return ERROR; e= *--S.top; return OK; }
|
取顺序栈栈顶元素:
Status GetTop( SqStack S, SElemType &e) { if( S.top == S.base ) return ERROR; e = *( S.top – 1 ); return OK; }
|
3.2.2 链栈
链栈的表示:运算受限,只在链表头部进行操作
typedef struct StackNode { SElemType data; struct StackNode *next; } StackNode, *LinkStack; LinkStack S;
|
- 链表的头指针就是栈顶
- 不需要头结点
- 基本不存在满栈的情况
- 空栈相当于头指针指向空
- 插入和删除仅在栈顶处执行
链栈的初始化:
void InitStack(LinkStack &S ) { S=NULL; }
|
判断链栈是否为空:
Status StackEmpty(LinkStack S) { if (S==NULL) return TRUE; else return FALSE; }
|
链栈的入栈:
Status Push(LinkStack &S , SElemType e){ p=new StackNode; if (!p) exit(OVERFLOW); p->data=e; p->next=S; S=p; return OK; }
|
链栈的出栈:
Status Pop (LinkStack &S,SElemType &e) { if (S==NULL) return ERROR; e = S-> data; p = S; S = S-> next; delete p; return OK; }
|
取栈顶元素:
SElemType GetTop(LinkStack S) { if (S==NULL) exit(1); else return S–>data; }
|
3.3 栈与递归
- 递归的定义:
- 若一个对象部分地包含自己,或用它给自己定义,则称这个对象是递归的
- 若一个过程直接地或间接地调用自己,则称这个过程是递归的过程
- 分治法:能分解成相对简单且解法相同或类似的子问题求解
- 能转变成一个新问题,解法相同或类同,不同的仅是处理的对象,且对象变化有规律
- 可以通过上述转化而使问题简化
- 必须有一个明确的递归出口,即递归的边界
void p (参数表) { if (递归结束条件)可直接求解步骤;-----基本项 else p(较小的参数);------归纳项 }
|
3.3.1 函数调用过程
- 调用前, 系统完成:
- 将实参,返回地址等传递给被调用函数
- 为被调用函数的局部变量分配存储区
- 将控制转移到被调用函数的入口
- 调用后, 系统完成:
- 保存被调用函数的计算结果
- 释放被调用函数的数据区
- 依照被调用函数保存的返回地址将控制转移到调用函数
3.4 队列的表示和操作的实现
队列的顺序表示:一维数组base[M]
#define M 100 Typedef struct { QElemType *base; int front; int rear; }SqQueue;
|
空队标志:front= =rear 入队:base[rear++]=x;
出队:x=base[front++];
3.4.1 循环队列
base[rear]=x; rear=(rear+1)%M;
|
出队:
x=base[front]; front=(front+1)%M;
|
队列的初始化:
Status InitQueue (SqQueue &Q){ Q.base =new QElemType[MAXQSIZE] if(!Q.base) exit(OVERFLOW); Q.front=Q.rear=0; return OK; }
|
求队列的长度:
int QueueLength (SqQueue Q){ return (Q.rear-Q.front+MAXQSIZE)%MAXQsize; }
|
循环队列入队:
Status EnQueue(SqQueue &Q,QElemType e){ if((Q.rear+1)%MAXQSIZE==Q.front) return ERROR; Q.base[Q.rear]=e; Q.rear=(Q.rear+1)%MAXQSIZE; return OK; }
|
循环队列出队:
Status DeQueue (LinkQueue &Q,QElemType &e){ if(Q.front==Q.rear) return ERROR; e=Q.base[Q.front]; Q.front=(Q.front+1)%MAXQSIZE; return OK; }
|
3.4.2 链队列
typedef struct QNode{ QElemType data; struct Qnode *next; }Qnode, *QueuePtr; typedef struct { QueuePtr front; QueuePtr rear; }LinkQueue;
|
链队列的初始化:
Status InitQueue (LinkQueue &Q){ Q.front=Q.rear=(QueuePtr) malloc(sizeof(QNode)); if(!Q.front) exit(OVERFLOW); Q.front->next=NULL; return OK; }
|
销毁链队列:
Status DestroyQueue (LinkQueue &Q){ while(Q.front){ Q.rear=Q.front->next; free(Q.front); Q.front=Q.rear; } return OK; }
|
链队列的入队:
Status EnQueue(LinkQueue &Q,QElemType e){ p=(QueuePtr)malloc(sizeof(QNode)); if(!p) exit(OVERFLOW); p->data=e; p->next=NULL; Q.rear->next=p; Q.rear=p; return OK; }
|
链队列出队:
Status DeQueue (LinkQueue &Q,QElemType &e){ if(Q.front==Q.rear) return ERROR; p=Q.front->next; e=p->data; Q.front->next=p->next; if(Q.rear==p) Q.rear=Q.front; delete p; return OK; }
|
链队列求头元素:
Status GetHead (LinkQueue Q, QElemType &e){ if(Q.front==Q.rear) return ERROR; e=Q.front->next->data; return OK; }
|