DS博客作业02--栈和队列

| 这个作业属于哪个班级 | 数据结构--网络2011/2012 |
| ---- | ---- | ---- |
| 这个作业的地址 | DS博客作业02--栈和队列 |
| 这个作业的目标 | 学习栈和队列的结构设计及运算操作 |
| 姓名 | 吴俊豪 |

0.PTA得分截图

1.本周学习总结

1.1栈

顺序栈

结构:


如图所示,顺序栈即一堆按照顺序排列的,拥有连续内存地址的储蓄结构的栈,数据由栈顶进入和导出,因此其对数据读取(尤其是栈底数据)时相较于数组和链表的效率略低,但其仅能从栈顶进出的特性对一些特殊(配对类)的问题效果拔群.

操作函数

结构体创建:
typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode {
    ElementType *Data;  /* 存储元素的数组 */
    Position Top;       /* 栈顶指针       */
    int MaxSize;        /* 堆栈最大容量   */
};
typedef PtrToSNode Stack;
创建并初始化顺序栈
Stack CreateStack( int MaxSize )
{
    Stack S = (Stack)malloc(sizeof(struct SNode));
    S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    S->Top = 0;//栈顶
    S->MaxSize = MaxSize;
    return S;
}
入栈与出栈
bool Push(Stack S, ElementType X)//入栈
{
    if (S->Top == S->MaxSize)//满栈
    {
        printf("Stack Full\n");
        return false;
    }
    S->Top++;
    S->Data[S->Top] = X;
    return true;
}

ElementType Pop(Stack S)//出栈
{
    int e;
    if (S->Top == 0)空栈
    {
        printf("Stack Empty\n");
        return ERROR;
    }
    e = S->Data[S->Top];
    S->Top--;
    return e;
}

注:入栈记得检查栈满,出栈记得检查栈空.

链栈

结构


链栈,顾名思义,就是和单链表长的八成像的栈结构,区别在于只能在栈顶进行数据操作.

操作函数

创建结构体
typedef struct SNode          //定义链栈结点类型
{
    ElemType data;
    struct SNode *next;        //指向后继结点
} LNode,*LinkStack;
创建并初始化链栈

bool InitStack(LinkStack &S)

{
    S=NULL;
    return true;
}

入栈与出栈

bool Push(LinkStack &S, int e) //入栈

{
    LinkStack p;
    p = new Snode; //现场申请现场用
    p->data = e; //将e附在新结点的data里
    p->next = S;
    S = p;
    return true;
}

bool Pop(LinkStack &S, int &e) //出栈

{
    LinkStack p;
    if (S == NULL) //栈满
    {
        return false;
    }
    e = S->data; //备份数据
    p = S;
    S = S->next; 
    delete p; //释放空间
    return true;
}

注:由于入栈时链栈空间可以主动按需申请,因此无需考虑栈满情况

1.2 栈的引用

对于常规计算中出现的优先级问题, 用以往我们学过的字符串似乎比较棘手, 所以可以尝试采用栈来处理优先级.
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
例如:

2+3*(7-4)+8/4

得出

2 3 7 4 - * + 8 4 / +

1.3 队列

结构

操作函数

结构体定义

typedef struct QNode{
	QElemtype *base;
	int front;
	int rear;
}SqQueue; 

队列创建

void InitQueue(SqQueue *Q)
{
	Q->base=(QElemtype*)malloc(sizeof(QElemtype)*QUEUESIZE);
	assert(Q->base!=NULL);
	Q->front=Q->rear=0; 
}

队尾数据入队

Status EnQueue(SqQueue *Q,QElemtype e)
{
	if(Q->rear==QUEUESIZE)
	{
		return ERROR;
	}
	Q->base[Q->rear]=e;
	Q->rear++;
	return OK;
}

队首数据出队

Status GetHead(SqQueue *Q,QElemtype *e)
{
	if(Q->front==Q->rear)
	{
		return ERROR;
	}
	*e=Q->base[Q->front];
	return OK;
}

环形队列


拼的不是很圆这是有够抱歉的呢
具体操作步骤和队列大差不差,就是栈满情况为front=rear%m(m为储存节点个数)

2. PTA实验作业

2.1 符号配对

[https://gitee.com/konjac_wjh/web-2011---blog-code/issues/I3G2DB]

2.1.1 解题思路

遍历一遍字符串->抓左括号来入栈->右括号停下查看->匹配就把左出栈->遍历结束在看栈->是为空栈无遗憾 skr~(

2.1.2 知识点

创建栈,进出栈

2.2 银行业务队列简单模拟

[https://gitee.com/konjac_wjh/web-2011---blog-code/issues/I3G2GN]

2.2.2 解题思路

把客人按序号奇数偶数从队尾分装进两个队列, 再用循环按照2A1B输出即可

2.2.2 知识点

创建队列,进出队列

3. 阅读代码

  1. 无法吃午餐的学生数量

3.1 题目及解题代码

学校的自助午餐提供圆形和方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。
餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮:
如果队列最前面的学生 喜欢 栈顶的三明治,那么会 拿走它 并离开队列。
否则,这名学生会 放弃这个三明治 并回到队列的尾部。
这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。
给你两个整数数组 students 和 sandwiches ,其中 sandwiches[i] 是栈里面第 i​​​​​​ 个三明治的类型(i = 0 是栈的顶部), students[j] 是初始队列里第 j​​​​​​ 名学生对三明治的喜好(j = 0 是队列的最开始位置)。请你返回无法吃午餐的学生数量。
来源:力扣(LeetCode)
链接:[https://leetcode-cn.com/problems/number-of-students-unable-to-eat-lunch]

int countStudents(int* students, int studentsSize, int* sandwiches, int sandwichesSize){
    int arr[2];
    memset(arr, 0, sizeof(arr));
    for (int i=0; i<studentsSize; ++i) {
        ++arr[students[i]];
    }
    for (int i=0; i<sandwichesSize; ++i) {
        if (arr[sandwiches[i]] == 0) break;
        --arr[sandwiches[i]];
    }
    return arr[0] + arr[1];
}

3.2 该题的设计思路

若喜欢栈顶的甜点的学生存在,那么不管他们在队伍的哪个位置,必定会遍历到他。否则,一定无法继续拿掉栈顶甜点。

3.3 难点&优势

难点

要将学生依次入队再依次和甜点数组进行比较,如果相等,则此学生出队,三明治数组元素后移一位。如果不相等,则将学生队列中的队头移至队尾,重复比较。用此方法解有一个问题,就是什么时候循环比较的过程可以结束
由题目可知,当学生队列中的每一个都不喜欢三明治数组里的头元素则循环结束,所以可定义一个用来判断循环能否结束的函数来控制循环次数。最后如果学生队列为空,则返回0,反之,则返回学生队列中的元素个数。

优势

对队列的操作大多为基础且易于理解,用一个新循环来判断循环是否应该结束.

posted @ 2021-04-05 21:51  Qurare  阅读(155)  评论(1编辑  收藏  举报