第三章「栈与队列」 学习总结

       通过第三章【栈与队列】的学习,我掌握了对两种特殊线性表—栈与队列的

一系列操作方法。栈的特点是后进后出,队列的特点是后进先出。这两种操作受

限的线性表在帮助我们解决特定的问题时能带来相当大的便利。

       本章的作业一是pta上的括号匹配编程题,题目要求我们对一串输入的字符

串进行扫描判断该串字符中的括号是否匹配。再学完栈之后,我第一个想到的便

是利用栈后出后进的特点对字符串中的括号进行操作。

这是我最先写出的算法版本:

int main()
{
    SqStack S;
    InitStack(S);
    char ch;
    char x;
    cin.get(ch);
    while(ch!='\n')
    {
        switch (ch)
        {
        case'{': Push(S, ch); break;  //将左括号压入栈
        case'[': Push(S, ch); break;
        case'(': Push(S, ch); break;
        case'}':
            if (!StackEmpty(S) && GetTop(S) == '{')
                Pop(S, x);  //正确匹配栈顶元素
            break;
        case']':
            if (!StackEmpty(S) && GetTop(S) == '[')
                Pop(S, x);  //正确匹配栈顶元素
            break;
        case')':
            if (!StackEmpty(S) && GetTop(S) == '(')
                Pop(S, x);  //正确匹配栈顶元素
            break;
        }
    }
    if (StackEmpty(S) )   //判断栈是否为空且是否出现错误匹配
        cout << "yes";
    else cout << "no";
    return 0;
}

       在vs中初步运行后,输入几个样例进行验证,结果正确。

      但是提交到pta上,出现了运行超时的问题(五个样例全部超时)。介于上一章

所学的教训,我再次将目光放回主函数,试图对算法进行简化提高效率。经过一系

列演算并参考书本例题后,我对算法进行了修改,加入了初始标识值flag=1,当swtich

循环中出现括号不匹配的情况,直接将flag赋值为0并直接结束while循环。

更改后的算法:

int main()
{
    int flag=1;//设置匹配结果初始值为1
    SqStack S;
    InitStack(S);
    char ch;
    char x;
    cin.get(ch);
    while(ch!='\n'&&flag)
    {
        switch (ch)
        {
        case'{': Push(S, ch); break;  //将左括号压入栈
        case'[': Push(S, ch); break;
        case'(': Push(S, ch); break;
        case'}':
            if (!StackEmpty(S) && GetTop(S) == '{')
                Pop(S, x);  //正确匹配栈顶元素
        else flag = 0; //错误匹配
            break;
        case']':
            if (!StackEmpty(S) && GetTop(S) == '[')
                Pop(S, x);  //正确匹配栈顶元素
        else flag = 0; //错误匹配
            break;
        case')':
            if (!StackEmpty(S) && GetTop(S) == '(')
                Pop(S, x);  //正确匹配栈顶元素
        else flag = 0; //错误匹配
            break;
        }
    }
    if (StackEmpty(S)&&flag )   //判断栈是否为空且是否出现错误匹配
        cout << "yes";
    else cout << "no";
    return 0;
}

       对算法进行优化后,提交到pta上后,发现五个样例中只有两个正确,另外两个是运行超时和

答案错误。在一句一句检查了n次以后仍没有发现错误在哪,最后有点烦躁将这个题目晾了几天。

       之后在与舍友的交流中,舍友告诉我他了解到运用cin.get读取单个元素会造成超时的问题,于

是将cin.get换成了cin.getline,用一个数组接受输入的字符串,对循环语句等稍作改动后,终于过

了验证。

修改成cin.getline之后的算法:

int main()
{
    int flag = 1;//设置匹配结果初始值为1
    SqStack S;
    InitStack(S);
    char ch[MAXSIZE];
    char x;
    cin.getline(ch, MAXSIZE);
    for (int i=0;i<MAXSIZE&&flag;i++)
    {
        switch (ch[i])
        {
        case'{': Push(S, ch[i]); break;  //将左括号压入栈
        case'[': Push(S, ch[i]); break;
        case'(': Push(S, ch[i]); break;
        case'}':
            if (!StackEmpty(S) && GetTop(S) == '{')
                Pop(S, x);  //正确匹配栈顶元素
            else flag = 0; //错误匹配
            break;
        case']':
            if (!StackEmpty(S) && GetTop(S) == '[')
                Pop(S, x);  //正确匹配栈顶元素
            else flag = 0; //错误匹配
            break;
        case')':
            if (!StackEmpty(S) && GetTop(S) == '(')
                Pop(S, x);  //正确匹配栈顶元素
            else flag = 0; //错误匹配
            break;
        }
    }
    if (StackEmpty(S) && flag)   //判断栈是否为空且是否出现错误匹配
        cout << "yes";
    else cout << "no";
    return 0;
}

        总的来说这次我的算法没出现多少错误,而是在cin.get函数上吃了亏。下次进行编程时

要时刻注意,减少cin.get的使用。

       至于pta上的第二题则较为简单,对题目条件进行分析以后就是对一串整数数组进行操作,

让其按照输入的先后顺序,输出两个奇数再输出一个偶数,直至用完所有读取的元素。针对该

题,我建立了两个队列分别用于接受奇数与偶数,最后再按顺序输出即可。

算法如下:

int main()
{
    LinkQueue Q1,Q2;//建立两个队列Q1(奇数队) Q2(偶数队)
    InitQueue(Q1);//初始化队列
    InitQueue(Q2);
    int n, x;
    cin >> n;//输入元素个数
    for (int i = 0; i < n; i++)
    {
        cin >> x;
        if (x % 2 == 0) //将奇数插入到Q1队尾
            Enqueue(Q2, x);
        else Enqueue(Q1, x);//将偶数插入到Q2队尾
    }
    while (!QueueEmpty(Q1) || !QueueEmpty(Q2))//判断队列Q1、Q2是否为空
    {
        for (int j = 0; j < 2 && !QueueEmpty(Q1); j++)//先判断Q1是否为空,再移出Q1的两个元素
        {
            DeQueue(Q1, x);
            cout << x;
            if (!QueueEmpty(Q1) || !QueueEmpty(Q2))//根据Q1、Q2是否为空判断是否为最后一项
                cout << " ";
        }
        if (!QueueEmpty(Q2)) { //执行Q1的出队后再执行Q2的队头元素出队
            DeQueue(Q2, x);
            cout << x;
            if (!QueueEmpty(Q1) || !QueueEmpty(Q2))//根据Q1、Q2是否为空判断是否为最后一项
                cout << " ";
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kirigirikyoko/p/10633901.html