目录
一、顺序栈
#define MaxSize 50
typedef int ElemType;
//初始化:顺序存储
typedef struct {
ElemType data[MaxSize];//数组
int top;//始终指向栈顶的一个变量
}SqStack;
1.初始化栈
void InitStack(SqStack &S){
S.top = -1;//栈为空就是初始化栈
}
2.入栈
bool Push(SqStack &S,ElemType x){
if(S.top == MaxSize-1){//是否栈满
return false;
}
S.data[++top] = x;
}
3.出栈(弹出栈顶元素)
bool Pop(SqStack &S,ElemType &m){
if(StackEmpty(S)){
return false;
}
m = S.data[S.top--];
return true;
}
4.取栈顶元素
bool GetTop(SqStack S,ElemType &m){
//m需要赋值,so加引用
if(StackEmpty(S)){
return false;
}
m = S.data[S.top];
return true;
}
5.判断为空
bool StackEmpty(SqStack S){
return -1 == S.top;
}
6.判满
bool isFull(SqStack S) {
return S.top == MaxSize - 1;
}
7.区别S.top==0
(1)初始化
void InitStack0(SqStack &S) {
S.top = 0;
}
(3)入栈
bool Push0(SqStack &S, ElemType e) {
if (S.top == MaxSize) {
return false;
}
S.data[S.top++] = e;
return true;
}
(4)出栈
bool Pop0(SqStack &S, ElemType &e) {
if (S.top == 0) {
return false;
}
//先下移在读取
e = S.data[--S.top];
return true;
}
(5)读取栈顶元素
bool GetTop0(SqStack S, ElemType &e) {
if (S.top == 0) {
return false;
}
e = S.data[S.top - 1];
return true;
}
(6)判空
bool isEmpty0(SqStack S) {
return S.top == 0;
}
(7)判满
bool isFull0(SqStack S) {
//入栈时赋值再相加,因此在data[9]赋值之后top++=10
return S.top == MaxSize;
}
二、共享栈
1.定义
//共享栈
typedef struct {
ElemType data[MaxSize];
int top1;
int top0;
} ShStack;
2.初始化
void InitShStack(ShStack &SS) {
SS.top0 = -1;
SS.top1 = MaxSize;
}
3.判满
//判满
bool isFull(ShStack SS) {
return SS.top0 + 1 == SS.top1;
};
三、链栈
1.初始化
void InitLinkStack(LiStack* &LS){
LS = (LiStack*) malloc(sizeof(LiStack));
LS ->next = NULL;
}
2.入栈
bool Push(LiStack* &LS,ElemType e){
LiStack *s;
s = (LiStack*)malloc(sizeof(LiStack));
if(s == NULL) return false;//内存没空间
s->data = e;
s->next = LS->next;
LS->next = s;
free(s);
return true;
}
3.出栈
bool Pop(LiStack* &LS,ElemType &e){
if(LS ->next == NULL) return false;
LiStack *s;
s = LS ->next;
e = s->data;
LS = s;
free(s);
return true;
}
4.读取栈顶元素
bool GetTop(LiStack* LS,ElemType &e){
if(LS ->next == NULL) return false;
LiStack *s;
s = LS ->next;
e = s->data;
return true;
}
5.判空
bool isEmpty(LiStack* LS){
return LS ->next == NULL;
}
6.区别:不带头结点
(1)初始化
void InitLinkStack0(LiStack* &LS){
LS = NULL;
}
(2)入栈
bool Push0(LiStack* &LS,ElemType e){
LiStack *s,*r;
if(LS == NULL){//空栈
s = (LiStack*)malloc(sizeof(LiStack));
if(s == NULL) return false;//内存没空间
s->data = e;
s->next = NULL;
LS = s;
}
//非空
s= LS;
r = (LiStack*)malloc(sizeof(LiStack));
if(r == NULL) return false;//内存没空间
r ->data= e;
r->next = s;
LS = r;
return true;
}
(3)出栈
bool Pop0(LiStack* &LS,ElemType &e){
if(LS == NULL) return false;
LiStack *s;
s = LS;
LS = s->next;
e = s->data;
free(s);
return true;
}
四、队列(循环队列)
1.基本操作
#define MaxSize 10
//队列结构体,数组实现
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];
int front,rear;//队列头尾
}SqQueue;
(1)初始化
void InitQueue(SqQueue &Q){
Q.front= Q.rear = 0;
}
(2)判断为空
bool isEmpty(SqQueue Q){
return Q.front == Q.rear;
}
(3)入队
bool EnQueue(SqQueue &Q,ElemType x){
if(Q.front == (Q.rear + 1)%MaxSize){//队列满
return false;
}
Q.data[Q.rear] =x;
Q.rear = (Q.rear +1 )%MaxSize;//有可能大于最大下标
}
(3)出队
bool DeQueue(SqQueue &Q,ElemType &x){
if(Q.front==Q.rear){
return false;
}
x = Q.data[Q.front];
Q.front = (Q.front + 1) % MaxSize;
return true;
}
(4)获取队头元素
bool GetTop(LinkQueue Q, ElemType &e) {
LinkNode *s = Q.front;
s = s->next;
e = s->data;
return true;
}
(5)判满
bool isFull(LinkQueue Q){
return (Q.rear+1)%MaxSize == Q.front;
}
2.不想浪费存储空间
(1)设置tag
1)定义
typedef int ElemType;
#define MaxSize 5
typedef struct {
ElemType data[MaxSize];
int front,rear;
int tag;
}SeQueue;
2)初始化
void InitQueue(SeQueue &Q){
Q.front = Q.rear = 0;
Q.tag = 0;
}
3)入队
bool EnQueue(SeQueue &Q,ElemType e){
if(Q.front == Q.rear && Q.tag == 1) return false;
Q.data[Q.rear]=e;
//取余之后栈就可以循环使用了,此时存储空间在逻辑上就成了环状
Q.rear = (Q.rear+1)%MaxSize;
Q.tag = 1;
return true;
}
4)出队
bool DeQueue(SeQueue &Q,ElemType &e){
if(Q.front == Q.rear && Q.tag == 0) return false;
e = Q.data[Q.front];
Q.front = (Q.front+1)%MaxSize;//取余
Q.tag = 0;
return true;
}
5)判空
bool isEmpty(SeQueue Q){
return Q.front == Q.rear && Q.tag == 0;
}
6)判满
bool isFull(SeQueue Q){
return Q.front == Q.rear && Q.tag == 1;
}
7)输出队列
void print(SeQueue Q){
while(!(Q.front == Q.rear && Q.tag == 0)){
//当入队恰好满队,此时Q.front == Q.rear && Q.tag == 1
//出队只能让former不成立,so监测当只剩最后一个令Q.tag=0,则出了最后一个,上述条件成立
printf("%-3d",Q.data[Q.front]);
Q.front= (Q.front+1)%MaxSize;
if((Q.front +1)%MaxSize == Q.rear) Q.tag = 0;
}
printf("\n");
}
(2)添加size
1)定义
typedef int ElemType;
#define MaxSize 10
typedef struct {
ElemType data[MaxSize];
int front,rear;
int size;
}SeQueue;
2)初始化
void InitQueue(SeQueue &Q){
Q.front = Q.rear = 0;
Q.size = 0;
}
3)入队
bool EnQueue(SeQueue &Q,ElemType e){
if(Q.rear == MaxSize) return false;
Q.data[Q.rear] = e;
//取余之后栈就可以循环使用了,此时存储空间在逻辑上就成了环状
Q.rear = (Q.rear+1) % MaxSize;
Q.size += 1;
return true;
}
4)出队
bool DeQueue(SeQueue &Q,ElemType &e){
if(Q.size==0) return false;
e = Q.data[Q.front];
Q.front = (Q.front+1)%MaxSize;//取余
Q.size -=1;
return true;
}
4)判空
bool isEmpty(SeQueue Q){
return Q.size == 0;
}
5)判满
bool isFull(SeQueue Q){
return Q.rear == MaxSize;
}
6)输出队列
void print(SeQueue Q){
while(Q.size > 0){
printf("%-3d",Q.data[Q.front]);
Q.front = (Q.front + 1)%MaxSize;
Q.size--;
}
printf("\n");
}
五.链表队列
typedef int ElemType;
//队列的链式存储 LinkQueue
//有头尾指针的单链表
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct {
LinkNode *front,*rear;//队头队尾(链表头尾)
}LinkQueue;
(1)初始化
申请空间,头尾指针指向同一个结点
void InitQueue(LinkQueue &Q){
Q.front= Q.rear = (LinkNode*)malloc(sizeof (LinkNode));
Q.front->next =NULL;
}
(2)入队
申请空间,存数据,尾指针移动,链接
void EnQueue(LinkQueue &Q,ElemType x){
LinkNode *pnew = (LinkNode*)malloc(sizeof (LinkNode));
pnew ->data = x;
pnew ->next = NULL;//否则无法停止
Q.rear ->next = pnew;//尾指针指向pnew
Q.rear = pnew;//新的尾部
}
(3)出队
申请一个指针指向待出结点,取值,头指针移动,断链
bool DeQueue(LinkQueue &Q,ElemType &x){
if(Q.rear == Q.front){//空的
return false;
}
LinkNode* q = Q.front ->next;//第一个结点
x = q->data;//获取出队的元素值
Q.front->next = q ->next;
if(Q.rear == q){//只剩1个结点
Q.rear = Q.front;
}
free(q);//断链
return true;
}
六、栈应用
1.括号匹配
基础代码不再展示
bool bracketCheck(ElemType arr[],int length){
SqStack S;
InitStack(S);
for (int i = 0; i < length; ++i) {
if ('(' == arr[i] || '[' == arr[i] || '{' == arr[i])//左括号
Push(S, arr[i]);
else {//右括号
if(isEmpty(S)) return false;//扫描到右括号时栈为null
ElemType e;
Pop(S, e);
if (e == '(' && arr[i] != ')') return false;
if (e == '[' && arr[i] != ']') return false;
if (e == '{' && arr[i] != '}') return false;
}
}
return isEmpty(S);
}
2.表达式求值
(2)中<->后
伪代码,仅供参考,作为答案还需参考正规写法
void ITS(ElemType arr[],int len){
SqStack S1,S2;
InitStack(S1);//放符号
InitStack(S2);//最后输出
if(数字){
Push(S2,arr[i]); //直接入S2栈
}else if(界限符号){
//左括号入栈S1,右括号依次popS1,直到(
}else{ // 运算符
if(+ or -){
// S1栈顶元素不是(就pop,入S2
}else if(* or /){
// S1栈顶元素是 * or / pop,入S2
}
}
//全部完成之后依次弹出S2中eles
}
(3)中<->前
(4)后缀求值
(5)中缀求值
七、真题2019-42
keyword:重复使用、占用空间只增不减--循环队列
(1)链式
(2)有一个空闲结点的两段式单向链表两段式:一段存数据一段存指针(next)
队空:front == rear
队满:rear ->next == front
reason:满了要增加空间,申请一个空间之后,rear后移,next为front
(3)(4)
第一个结点放数据,放完之后申请空间,rear后移
rear ->data = x,pnew malloc,rear=rear->next;出队:取值,front=front ->next
//代码实现
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode* next;//指向下一个结点
}LNode, * LinkList;
void EnQueue(LinkList front, LinkList& rear, ElemType val)
{
LinkList pnew;
if (rear->next == front)
{
//队列满,申请一个结点的空间,放入队列
pnew= (LinkList)malloc(sizeof(LNode));
rear->data = val;//把入队元素放入 rear 指向结点
rear->next = pnew;//放了一个结点,其相当于做了分割
pnew->next = front;
rear = pnew;
}
else {//如果队列不满,直接放值,让 rear 后移一个结点
rear->data = val;
rear = rear->next;
}
}
void DeQueue(LinkList& front, LinkList rear)
{
if (front == rear)
{
printf("queue is empty\n");
}
else {
printf("dequeue element is %d\n", front->data);
front = front->next;
}
}
void CircleQueue(LinkList& front, LinkList& rear)
{
//队列头和队列尾都指向一个结点,这时队列既是空的,也是满的
front = (LinkList)malloc(sizeof(LNode));
rear = front;
rear->next = front;
//入队
EnQueue(front, rear, 3);
EnQueue(front, rear, 4);
//出队
DeQueue(front, rear);
DeQueue(front, rear);
DeQueue(front, rear);
}
int main()
{
LinkList front, rear;
CircleQueue(front, rear);
return 0;
}