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

0.PTA得分截图

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

1.1 总结栈和队列内容

1.堆栈的描述
堆找(Stack):具有一定操作约束的线性表,只在一端(栈顶,Top)做插入、删除
-插入数据:入栈(Push)
-删除数据:出栈(Pop)
2.栈的顺序存储实现
栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成。

#define MaxSize <储存数据元素的最大个数>
typedef struct SNode *Stack;
struct SNode{
ElementType Data[MaxSize];
int Top;
};

入栈操作

void Push( Stack PtrS, ElementType item )
{
      if ( PtrS->Top == MaxSize-1 ) {
         printf( “堆栈满”); return;
        }else {
           PtrS->Data[++(PtrS->Top)] = item;
           return;
         }
}

出栈操作

ElementType Pop( Stack PtrS )
{
     if( PtrS->Top ==-1){
             printf(“堆栈空");
             return ERROR;/* ERROR是ElementType的特殊值,标志错误*/
      } else
          return ( PtrS->Data[(PtrS->Top)-] );
}

3.堆栈的链式存储实现
栈的链式存储结构实际上就是一个单链表,叫做链栈。插入和删除操作只能在链栈的栈顶进行。

typedef struct SNode *Stack;
struct SNode{
       ElementType Data;
       struct SNode *Next;
};

初始化以及判断堆栈是否为空

Stack CreateStack ()
{ /*构建一个堆栈的头结点,返回指针*/
       Stack S;
       S =(Stack)mal1oc(sizeof(struct SNode) ) ;
       S->Next = NULL; 
       return S;
}
int IsEmpty (Stack S)
{    /*判断堆栈s是否为空,若为空函数返回整数1,否则返回0 */
      return ( S->Next == NULL ) ;

入栈

void Push ( ElementType item, Stack S)
{     /*将元素item压入堆栈S */
     struct SNode *Tmp ;
      Tmp=(struct SNode*) mal1oc (sizeof(struct SNode)) ;
      Tmp->Element = item;
      Tmp->Next = S->Next;
      S->Next = Tmp;
}

出栈

E1ementType Pop (Stack S)
{ /*删除并返回堆栈s的栈顶元素*/
       struct SNode *First ;
       E1ementType TopElem;
       if(IsEmpty(S)) {
           printf (“堆栈空") ; return NULL;
       } else {
          First = S->Next;
          S->Next = First->Next;
          TopElem = First ->E1ement;
          free (First) ;
          return TopElem;
        }
}

3.堆栈应用:表达式求值
步骤:
从左到右读入后缀表达式的各项(运算符或运算数)
①.运算数:入栈;
②.运算符:从堆栈中弹出适当数量的运算数,计算并结果入栈;
③.最后,堆栈顶上的元素就是表达式的结果值。
4.队列
队列(Queue)的插入和删除操作:只能在一端插入,而在另一端删除。
数据插入:入队列(AddQ)
数据删除:出队列(DeleteQ)
队列的顺序存储
队列的顺序存储结构通常由一个一维数组和一个记录队列头元素位置的变量front以及一个记录队列尾元素位置的变量rear组成。

#define MaxSize <储存数据元素的最大个数>
struct QNode {
       ElementType Data[MaxSize];
       int rear;
       int front;
};
typedef struct QNode *Queue;

入队列

void AddQ( Queue Q, ElementType item)
{
     if ((Q->rear+1)%MaxSize==Q->front)
         {
             printf(“队列满");
             return; 
         }
          Q->rear = (Q->rear+1)% MaxSize;
          Q->Data[Q->rear] = item;
}

出队列

ElementType DeleteQ (Queue Q)
{
      if (Q->front == Q->rear) {
           printf("“队列空");
           return ERROR;
          } else {
             Q->front = (Q->front+1)% MaxSize;
             return Q->Data[Q->front];
         }
}

1.2.谈谈你对栈和队列的认识及学习体会。

这两周学习了栈和队列这两种数据结构,两者的原理略有差别,能在不同情况下解决问题,都是很实用的结构。目前对一些复杂的操作还不是很了解,接下来要多花点时间

2.PTA实验作业

2.1.题目1:7-3 jmu-ds-符号配对

2.1.1代码截图





2.1.2本题PTA提交列表说明。


部分正确:没能解决括号不匹配时栈空和栈不空的两个测试点,解决方法是设置一个函数取得栈顶的元素再输出

2.2.题目2:7-2 jmu-字符串是否对称

2.2.1代码截图


2.2.2本题PTA提交列表说明。


编译错误:刚开始写的时候问题很多,一些关键点,比如如何进行对比还不知道怎么用代码实现,后来也去网上借鉴了一下别人的代码,了解了大致的思路,但问题也很多,并不能正确编译,于是改了很多

3.阅读代码

3.1 题目及解题代码

class MinStack {
public:
    /** initialize your data structure here. */
    stack<int> _stack;
    int _min = INT_MAX;
    MinStack() {
        
    }
    
    void push(int x) {
        if(_min >= x){
            if(!_stack.empty()){
                _stack.push(_min);
            }
            _min = x;
        }
        _stack.push(x);
    }
    
    void pop() {
        if(_stack.empty())
            return;
        if(_stack.size() == 1)
            _min = INT_MAX;
        else if(_min == _stack.top()){//下一个元素是下一个最小值
            _stack.pop();
            _min = _stack.top();
        }
        _stack.pop();
    }
    
    int top() {
        return _stack.top();
    }
    
    int getMin() {
        return _min;
    }
};

作者:Benjamin-Crice
来源:力扣(LeetCode)

3.1.1 该题的设计思路

利用一个_min变量标记当前的最小栈内元素。
入栈时,如果最小元素发生变更,就把当前最小元素也进行压栈,标记这一次的最小元素变更情况。
出栈时,如果遇到当前最小值与栈顶元素相同的情况,就连着这个元素一起弹出,并将当前最小值更新为这个元素的下一个元素。
时间复杂度O(1),空间复杂度O(1);

3.1.2 该题的伪代码

文字+代码简要介绍本题思路

void push(int x){
	if 最小元素大于等于x
		if 栈非空
			最小元素入栈
		最小元素等于x
	x入栈
}
void pop() {
	if 栈空
		返回
	if 栈长度等于1
		_min = INT_MAX;
	else if 下一个元素是下一个最小值
		出栈;
	    最小元素等于栈顶元素
	出栈
}

3.1.3 运行结果

3.1.4分析该题目解题优势及难点。

这段代码只用了一个栈就实现了题目要求,比其他解法中用到了两个站的代码要节省空间。入栈时,如果最小元素发生变更,就把当前最小元素也进行压栈,标记这一次的最小元素变更情况,这个方法确实精妙,值得学习。代码里这句 _min >= x 中的等于号也很关键。

3.2 题目及解题代码

class Solution {
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
        int n = A.size();
        move(n, A, B, C);
    }

    void move(int n, vector<int>& A, vector<int>& B, vector<int>& C){
        if (n == 1){
            C.push_back(A.back());
            A.pop_back();
            return;
        }

        move(n-1, A, C, B);  
        C.push_back(A.back());  
        A.pop_back();         
        move(n-1, B, A, C);  
    }
};

3.2.1 该题的设计思路

用递归的方法解决
n = 1 时,直接把盘子从 A 移到 C;
n > 1 时,
先把上面 n - 1 个盘子从 A 移到 B(子问题,递归);
再将最大的盘子从 A 移到 C;
再将 B 上 n - 1 个盘子从 B 移到 C(子问题,递归)。

时间复杂度:O(2^n−1).一共需要移动的次数。
空间复杂度:O(1).




3.2.2 该题的伪代码

	void move(int n, vector<int>& A, vector<int>& B, vector<int>& C) {
		if n等于1 
			把盘子从 A 移到 C
			return
		将A上面n-1个通过C移到B
		将A最后一个移到C
		将B上面n-1个通过空的A移到C
	}

3.2.3 运行结果

3.2.4分析该题目解题优势及难点。

本题运用了递归的思想,将复杂的问题一步步拆解,把n个盘子也看成两个部分,一部分有1个盘子,另一部分有n-1个盘子,变成两个盘子的问题。依次类推,直至转化成 1 个盘子的问题时,问题也就解决了。

原文地址:https://www.cnblogs.com/9418wdnm/p/12546937.html