代码改变世界

DS博客作业02

  米奈希尔。  阅读(86)  评论(1编辑  收藏  举报

| 这个作业属于哪个班级 | C语言--网络2011/2012 |
| ---- | ---- | ---- |
| 这个作业的地址 | DS博客作业02--栈和队列 |
| 这个作业的目标 | 学习栈和队列的结构设计及运算操作。 |
|姓名 | 罗发槺 |

0.PTA得分截图

1.本周学习总结(0-5分)

1.1 栈

  • 栈(stack)是一种只能在一端进行插入或删除操作的线性表。表中允操作的一端称为栈顶(top),
    表的另一端称为栈底(bottom),如图3.1所示。栈顶的当前位置是动态的,栈顶的当前位置由一个被称
    为栈顶指针的位置指示器来指示。当栈中没有数据元素时称为空栈。栈的插人操作通常称为进栈或入
    栈( push),栈的删除操作通常称为出栈或退栈(pop)。
  • 栈的主要特点是“后进先出”(Last In First Out,LIFO),即后进栈的元素先出栈。每次进栈的
    数据元素都放在原来栈顶元素之前成为新的栈顶元素,每次出栈的数据元素都是当前栈顶元素。栈也
    称为后进先出表。

1.11顺序栈的结构、操作函数

    1. 顺序栈的结构体定义
typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode {
    ElementType *Data;  /* 存储元素的数组 */
    Position Top;       /* 栈顶指针       */
    int MaxSize;        /* 堆栈最大容量   */
};
typedef PtrToSNode Stack;
  • 2.初始化栈
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;
}
  • 3.进栈
bool Push(Stack S, ElementType X)
{
    if (S->MaxSize == S->Top)
    {
        puts("Stack Full");
        return 0;
    }
    S->Data[S->Top++]=X;
    return 1;
}
  • 4.出栈
ElementType Pop(Stack S)
{
    if (!S->Top)
    {
        puts("Stack Empty");
            return ERROR;
    }
    return S->Data[--S->Top];
}
  • 5.输出栈的元素
void PrintStack(Stack S)
{
    while (S->Top)
        printf("%d ", S->Data[--S->Top]);
    puts("");
}
  • 6.判空和销毁栈
bool StackEmpty(Stack S)
{
     return S->top==-1;
}
void DesStack(SqStack &S)
{
     free(s);
}

1.12链栈的结构、操作函数

    1. 链栈的结构体定义
typedef struct linknode
{
	ElemType data;
	struct linknode *next;
}LinkStNode;
  • 2.初始化栈
void InitStack(LinkStNode *&s)
{
	s = (LinkStNode*)malloc(sizeof(LinkStNode));
	s->next=NULL;
}
  • 3.销毁栈
void DestroyStack(LinkStNodew& s)
{
	LinkStNode* pre - s, * p = s->next;
	while(p!- NULL)//pre指向头结点指向首结点
	{
		free(pre);//循环到书为空
		pre = p://释放pre销版
		p = pre->next;// pre.p同步后移
	}
	free(pre);//此时pre指向尾结点,释放其空间
}
  • 4.进栈
void Push(LinkStNode n& s, ElemType e)
{
	LinkStNode* p;
	p = (LinkStNode*)malloc(sizeof(LinkStNode));
	p->data = e;
	p->next = s->next;
	s->next = p;
}
  • 5.出栈
bool Pop(LinkStNode*& s, ElemType& e)
{
	LinkStNode* p;
	if (s->next == NULL)
		return false;
	p = s->next;
	e = p - > data;
	s->next = p->next;
	free(p);
	return ture;
}
  • 6.取栈顶元素
bool GetTop(LinkStNode* s, ElemType& s)
{
	if (s->next == NULL)
		return false;
	e = s->next->data;
	return true;
}

1.2 栈的应用

表达式转换

转换原则

  1. 遇到操作数, 直接输出
  2. 操作符的优先级为 () 最大, * / 次之, +- 最小. 遇到操作符后, 假如操作符堆栈为空, 则直接压入操作符, 否则判断当前操作符与栈顶操作符的优先关系, 假如栈顶操作符的优先级大于 等于当前操作符的优先级, 那么弹出栈顶操作符, 持续弹出, 直到栈顶操作符优先级小于当前操作符优先级或栈为空. 最后将当前操作符入栈
  3. 如果遇到右括号, 那么将栈顶操作符弹出, 持续弹出直到遇到左括号, 左括号弹出但不输出
  4. 表达式读入完毕, 若栈不为空, 则持续弹出栈顶操作符, 直到栈为空

迷宫求解

1.3 队列

  • 队列(queue)简称队,它也是一种操作受限的线性表,其限制为仅允许在表的一端进行插人操作,而在表的
    另一端进行删除操作。把进行插人的一端称为队尾(rear),把进行删除的一端称为队头或队首(front),如图
    所示。向队列中插入新元素称为进队或入队(enqueue),新元素进队后就成为新的队尾元素;从队列中删除元
    素称为出队或离队(dequeue),元素出队后,其直接后继元素就成为队首元素。
  • 由于队列的插人和删除操作分别是在各自的一端进行的,每个元素必然按照进入的次序出队,所以又把队列
    称为先进先出表(FirstIn First Out. FIFO)。

1.31 顺序队列

  • 1.队列的结构体定义
typedef struct {
    Person data[MAXQSIZE]; 
    int front; //头指针
    int rear; //尾指针
} Queue;
  • 2.初始化队列
int InitQueue(SqQueue &Q) {//构造一个空队列Q
    Q = new Queue; //为队列分配一个最大容量为MAXSIZE的数组空间
    if (!Q->data)
        exit( OVERFLOW); //存储分配失败
    Q->front = Q->rear = 0; //头指针和尾指针置为零,队列为空
    return OK;
}
  • 3.进队
bool enQueue(SqQueue *&q,ElemType e)
{
    if(q->rear==MaxSize-1)
      return false;
      q->rear++; 
      q->data[q->rear]=e;
      return true;
}
  • 4.出队
bool deQueue(SqQueue *&q,ElemType &e)
{
       if(q->front==q->rear)
          return false;
          q->front++;
          e=q->data[q->front];
          return true;
}
  • 5.判空和销毁队列
bool QueueEmpty(SqQueue *q)
{
     return  q->front==q->rear;
}
bool DestoryQueue(SqQueue *&q)
{
     free(q);
}

1.32 链队列

  • 1.结构体定义
typedef struct qnode
{
    Elemtype data;
    struct qnode* next;
}DataNode;

typedef struct
{
    DataNode front;//队头指针;
    DataNode rear;//队尾指针;
}LinkQuNode;
  • 2.初始化队列
void InitQueue(LinkQueue& q)
{
    q = (LinkQuNode*)malloc(sizeof(LinkQuNode));
    q.front->next = NULL;
    q.rear->next = NULL;
}
  • 3.进队
void eeQueue(LinkQuNode*& q, Elmetype& e)
{
	DataNode* t;
	t = (DataNode*)malloc(sizeof(DataNode));
	t->data = e;
	t->next = NULL;
	if (q->rear == NULL)
		q->front = q->rear = t;
	else
	{
		q->rear->next = t;
		q->rear = t;
	}
}
  • 4.出队
bool deQueue(LinkQuNode*& q, Elmetype& e)
{
	DataNode* t;
	if (q->rear == NULL)
		return false;
	t = q->front;
	if (q->front == q->rear)
		q->front = q->rear = NULL;
	else
		q->front = q->front->next;
	e = t->data;
	free(t);
	return true;
}

1.33环形队列

  • 1.进队
bool enQueue(SqQueue *&q,ElemType e)
{
    if((q->rear+1)%MaxSize==q->front)
      return false;
      q->rear=(q->rear+1)%MaxSize;
      q->data[q->rear]=e;
      return true;
}
  • 2.出队
bool deQueue(SqQueue *&q,ElemType &e)
{
       if(q->front==q->rear)
          return false;
          q->front=(q->front+1)%MaxSize;
          e=q->data[q->front];
          return true;
}

1.4队列的应用

1.舞伴

2.报数

2.PTA实验作业

2.1 符号配对

2.1.1
  • 解题思路:利用各种条件来限制进栈和出栈的条件
    *伪代码
int len = strlen(s);
for i=0 to len
  if不是括号
    continue
  endif
  if是左括号
    进栈
   endif
  else if是右括号
    {
        if栈空
          break;
         if是右括号且栈顶是左括号
            出栈
    }
    endif
endfor
if栈空且i=len
  输出yes
else if栈空
  输出no
else
  输出栈顶和no
2.1.2 总结解题所用的知识点
  • 1.stl库的stack容器,可以调用已有的函数进行操作,极大的方便了代码的编程
  • 2.c++的cin和cout
  • 3.C语言的for和if ,else等

2.2 银行业务队列简单模拟

2.2.1 解题思路及伪代码
  • 解题思路
    先对奇偶数进行队列的输入,然后按照先出2个A在出1个B进行输出,等到一个空了之后再把没空的全部输出。
  • 伪代码
queue<int> a, b;
for i=1 to n
  if奇的
    进入b队列
  else
  进入a队列
endfor
while a or b 不空
  for 1 to 2
    输出a.front
    a.pop
  endfor
  输出b.front
  b.pop
endwhile
输出不空的队列的全部元素

2.2.2 总结解题所用的知识点

  • 1.stl库的queue容器,可以调用已有的函数进行操作,极大的方便了代码的编程
  • 2.c++的cin和cout
  • 3.C语言的for,while和if ,else等

3.阅读代码

3.1 题目及解题代码

class Solution {
public:
    int countStudents(vector<int>& students, vector<int>& sandwiches) {
        int stusum=0;
        for(int i=0;i<students.size();i++)
            stusum+=students[i];
        queue<int> q;
        for(int i=0;i<students.size();i++)
            q.push(students[i]);
        int i=0;
        while(i<sandwiches.size()){
            if(q.front()==sandwiches[i]){
                stusum-=sandwiches[i];
                q.pop();
                i++;
            }
            else{
                q.push(q.front());
                q.pop();
            }
            if(q.size()==0)
                break;
            if((sandwiches[i]!=q.front() && stusum==0 )||(sandwiches[i]!=q.front() &&stusum==q.size()))
                break;
        }
        return sandwiches.size()-i;
    }
};

作者:ZackQwQ
链接:https://leetcode-cn.com/problems/number-of-students-unable-to-eat-lunch/solution/c-dui-lie-queue-by-zackcai-wngn/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

3.2 该题的设计思路及伪代码
设计思路:先对喜好值进行求和,然后让学生数组进入队列,再利用循环来对队伍的第一个人的喜好进行挑选,符合条件的就把之前计数好的减去喜好值,最后用喜好值来进行条件限制循环的结束。

定义一个整型数studum来计数
for 0 to 学生数
  stusum加学生是1的数
endfor
定义一个queue容器q
for 0 to 学生数
  学生数组进队列
endfor
int i
while小于三明治数
  if队列第一个数等于sandwiches[i]
  {    
    stusum-sandwiches[i]
    endif
    q.pop
    i++;
  }
  else
  {
    队列第一个数进栈
    出栈
  }
  if队列没有元素就退出循环
  if((sandwiches[i]!=q.front() && stusum==0 )||(sandwiches[i]!=q.front() &&stusum==q.size()))
    break;
  endif
endwhile
return 三明治容器元素-1;

3.3 分析该题目解题优势及难点。
难点:对于条件的限制和对学生喜欢的三明治的比较如何设计。
优势:利用stl库的函数进行代码编程,不用自己来书写多余代码,大大提高了效率而且是的代码简洁美观。

编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示