13.C++栈与队列考研基础

目录

一、顺序栈

1.初始化栈

2.入栈

3.出栈(弹出栈顶元素)

4.取栈顶元素

5.判断为空

6.判满

7.区别S.top==0

(1)初始化

(3)入栈

(4)出栈

(5)读取栈顶元素

(6)判空

(7)判满

二、共享栈

1.定义

2.初始化

3.判满

三、链栈

1.初始化

2.入栈

3.出栈

4.读取栈顶元素

5.判空

6.区别:不带头结点

(1)初始化

(2)入栈

(3)出栈

四、队列(循环队列)

1.基本操作

(1)初始化

(2)判断为空

(3)入队

(3)出队

(4)获取队头元素

(5)判满

2.不想浪费存储空间

(1)设置tag

1)定义

2)初始化

3)入队

4)出队

5)判空

6)判满

7)输出队列

(2)添加size

1)定义

2)初始化

3)入队

4)出队

4)判空

5)判满

6)输出队列

五.链表队列

(1)初始化

(2)入队

(3)出队

六、栈应用

1.括号匹配

2.表达式求值

(2)中<->后

(3)中<->前

(4)后缀求值

(5)中缀求值

七、真题2019-42


一、顺序栈

#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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

blue_blooded

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值