第三章:栈与队列,学习小结

(1)先说说这两个星期的收获

学了栈和队列的相关内容,但是对栈比较熟,队列还需要多熟悉一下,学了发现和前面的顺序表的结构还是很像的。

(2)上次的目标:

  全部没有达到,对时间的安排不合理,作业堆在一个星期完成,大大降低效率,希望下个星期不要再这样了,要留多点时间研究透题目和自己代码的错因。

 

(3)这周的作业编程题:

题目:括号匹配

给定一串字符,不超过100个字符,可能包括括号、数字、字母、标点符号、空格,编程检查这一串字符中的( ) ,[ ],{ }是否匹配。

输入格式:

输入在一行中给出一行字符串,不超过100个字符,可能包括括号、数字、字母、标点符号、空格。

输出格式:

如果括号配对,输出yes,否则输出no。

代码:

#include

#include

#include

using namespace std;

 

#define OK 1

#define ERROR 0

#define OVERFLOW -2

#define MAXSIZE  100

typedef int Status;

typedef char SElemType;

typedef struct{

           SElemType *base;

           SElemType *top;

           int stacksize;

}SqStack;//顺序栈定义

 

//顺序栈的初始化

Status InitStack(SqStack &S)

{// 构造一个空栈 S

           S.base = new SElemType[MAXSIZE];     //为顺序栈分配一个最大容量为MAXSIZE的数组空间

           if(!S.base)

                     exit (OVERFLOW);          //存储分配失败

           S.top = S.base;

           S.stacksize = MAXSIZE;

           return OK;

}

//顺序栈的入栈

Status Push(SqStack &S,SElemType &e)

{ // 插入元素e为新的栈顶元素

           if(S.top-S.base==S.stacksize)

                     return ERROR;         //栈满

           *(S.top++) = e;       //元素e压入栈顶,栈顶指针加1

           return OK;

}

// 顺序栈的出栈

Status Pop(SqStack &S,SElemType &e)

{// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR

           if(S.base == S.top)

                     return ERROR;//栈空

           e = *(--S.top); //栈顶指针减1,将栈顶元素赋给e

           return OK;

}

//取顺序栈的栈顶元素

Status GetTop(SqStack S,SElemType &e)

{// 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR

           if(S.top == S.base)

                     return ERROR;

           e = *(S.top-1);//栈顶指针减1,将栈顶元素赋给e

           return OK;

}

 

int main()

{

           string s;

           getline(cin,s);           //getline()获取一行输入,包括空格

           int len=s.size();        //获取输入字符的长度

           SqStack S;

           SElemType temp;

           InitStack(S);

          

           int flag = 1;             //判断匹配是否成功

           for(int i = 0; i < len; i++) {

                     SElemType e;

                     switch (s[i]){

                             case '[':

                             case '(':

                             case '{':

                                          Push(S, s[i]);   //左括号入栈

                                          break;

                             case ')' :

                                          if (GetTop(S, e) && e == '(')         //栈非空且取出的栈顶元素为(

                                                     Pop(S, e);      //匹配成功,(出栈

                                          else

                                                     flag=0;                    //匹配失败

                                          break;

                             case ']' :

                                          if (GetTop(S, e) && e == '[')         //栈非空且取出的栈顶元素为[

                                                     Pop(S, e);      //匹配成功,[出栈

                                          else

                                                     flag=0;                    //匹配失败

                                          break;

                                case '}' :

                                          if (GetTop(S, e) && e == '{')         //栈非空且取出的栈顶元素为{

                                                     Pop(S, e);      //匹配成功,{出栈

                                          else

                                                     flag=0;                    //匹配失败

                                          break;

                     }

           }

                                  

           if(flag && GetTop(S, temp) == ERROR)           //栈为空 说明所有的括号匹配成功

                     cout << "yes";

           else

                     cout << "no";

           return 0;

 }

 

分析如代码中的注释所示

遇到的困难:

(1)     改错的能力差,要像老师说的那样,遇到代码出错时要通过多写注释,运用cout一些标记的方法来分析,我写了很多个版本,有些版本还没找出错误就放弃了,这是不行的,应该通过改到对为止来发现自己的错误

(2)     头文件部分不熟,经常乱用或少用

(3)     Getline()和cin的用法区别还没有分清;

(4)     有一些低价错误要避免,true因为写成ture而导致出错。

(5)     if,elseif,switch用法还不熟

(6)     if,else语句后有两条以上语句 要加{}!!经常出错

 

 

实践题:

题目:设某银行有A、B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 —— 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客。给定到达银行的顾客序列,请按业务完成的顺序输出顾客序列。假定不考虑顾客先后到达的时间间隔,并且当不同窗口同时处理完2个顾客时,A窗口顾客优先输出。

输入格式:

输入为一行正整数,其中第1个数字N(1000)为顾客总数,后面跟着N位顾客的编号。编号为奇数的顾客需要到A窗口办理业务,为偶数的顾客则去B窗口。数字间以空格分隔。

输出格式:

按业务处理完成的顺序输出顾客的编号。数字间以空格分隔,但最后一个编号后不能有多余的空格

 

代码:

#include

using namespace std;

 

#define OK 1

#define ERROR 0

#define OVERFLOW -2

 

typedef int QElemType;

typedef int Status;

 

typedef struct QNode{

           QElemType data;

           QNode *next;

}QNode,*QueuePtr;

typedef struct{

           QueuePtr front;

           QueuePtr rear;

}LinkQueue;

 

// 链队的初始化

Status InitQueue(LinkQueue &Q)

{// 构造一个空队列Q

           Q.front = new QNode;

           if(Q.front == NULL)

           {

                     return OVERFLOW;   // 存储分配失败

           }

           Q.front->next = NULL;

           Q.rear = Q.front;

           return OK;

}

 

// 链队的入队

Status EnQueue(LinkQueue &Q,QElemType e)

{ // 插入元素e为Q的新的队尾元素

           QNode *p = new QNode;

           if(p == NULL)

           {

                     return OVERFLOW;// 存储分配失败

           }

           p->data = e;

           p->next = NULL;

           Q.rear->next = p;

           Q.rear = p;    // 修改队尾指针

           return OK;

}

 

// 链队的出队

Status DeQueue(LinkQueue &Q,QElemType &e)

{//删除Q的队头元素,用e返回其值,并返回OK

           if(Q.front == Q.rear)

           {

                     return ERROR;         //若队列空,则返回 ERROR

           }

           QNode *p = Q.front->next;//p指向队头元素

           e = p->data;//e保存队头元素的值

           Q.front->next = p->next;//修改头指针

           if(Q.rear == p)

           {

                     Q.rear = Q.front;//最后一个元素被删,队尾指针指向头结点

           }

           delete p;

           return OK;

}

 

int main()

{

           LinkQueue A, B;                 // 新建两个队列

           InitQueue(A);                     // 初始化队列

           InitQueue(B);

          

           int n;

           cin >> n;                 // 顾客数量

           int a[n];        

           for(int i = 0; i < n; i++)

           {

                     cin >> a[i];

                     if (a[i] % 2 == 1)                 // 奇数顾客入队

                                EnQueue(A, a[i]);

                     else                                              // 偶数顾客入队

                                EnQueue(B, a[i]);

           }

 

           int flag = 0;                                  // 判断是否第一个顾客

           for(int i = 0; i < 1000; ++i)

           {

                     /*

                     A队出两个,B队出一个的第一个关键之处

                     temp必须放进for循环,每一次循环都会初始化,失去之前的赋值

                     相当于每次循环都重新声明temp这个变量

                     */

                     QElemType temp;                       

        if(DeQueue(A, temp) == OK)             // A队列非空

        {

            if(flag == 0)                                // 第一个顾客

                     cout << temp;                             // 输出没有空格

            else

                     cout << " " << temp;        // 之后的顾客都先输出空格再输出顾客编号

                   flag = 1;

        }

        /*

        A队出两个,B队出一个的第二个关键之处

        整个for循环里面有两个if判断,第一个if判断只要A队列非空就可以输出

                     第二个if判断必须B队列非空且隔一次输出

                     简单来说就是

                     i = 0:A

                     i = 1:A B

                     i = 2:A

                     i = 3:A B

                     以此类推,输出就是A A B A A B .... 直到输出完所有编号

                     */

        if(i % 2 == 1 && DeQueue(B, temp) == OK)

        {

              if(flag == 0)

                   cout << temp;

            else

                     cout << " " << temp;

                   flag = 1;

        }

    }

           return 0;

}

遇到的问题:

(1)     依旧是改错能力差

(2)     分类讨论考虑不全,容易想复杂

 

 

下周目标:

作业提前写,不要都堆在最后一天

坚持一个方法就不要变,要通过不断改正发现自己的问题

一道题有多种解法,每一种都去试一下。

你可能感兴趣的:(第三章:栈与队列,学习小结)