《数据结构》第3章-栈与队列的学习总结

  我之前有接触过栈和队列,当时就觉得很好奇,那是以怎样的存储结构存储数据的呢?拨开重重迷雾,终于学到基础知识了。

  学习《栈和队列》有两个星期了,有了前面两个章节的思维基础,我觉得栈和队列学习起来还是很好理解的,通过一些实际应用例子,让我有了更进一步的理解。现在我梳理一下知识,下面总结这一章我所学习到的东西。

一、栈(后进先出:LIFO)

 1、顺序栈

这是顺序栈的存储结构:

typedef struct
{
  int *base;//栈底指针
  int *top; //栈顶指针
  int size; //栈容量
}SqStack;

  开始栈底、栈顶指针都为空,之后随着元素的插入,还有栈的特性(只能在栈顶插入删除),base始终指向栈底位置,而top则加1,指向栈顶元素的上一个。对于顺序栈的基本操作,我觉得跟前面顺序表差不多,只需要在栈顶操作,好像更简单些。

  我无意中发现自己现在更喜欢链式存储结构,可能是以前觉得链式比顺序复杂,而学习之后觉得链式更有趣,它的抽象逻辑结构如果捋清楚,就使我豁然开朗,也是这也是一种乐趣吧。

 2、链栈

这张图很好表示了链栈的存储结构,老师分析,链栈没必要设头结点,因为在这里对于链栈插入删除,只需要在栈顶操作最方便,初始化时直接将头指针置空就行。

//---------链栈存储结构--定义
typedef struct stacknode
{
  int data;  //数据域
  struct stacknode *next; // 指针域
}stacknode,*linkstack;

1、初始化
void initstack(linkstack &S)
{
  S=NULL;//构造空栈S.栈顶指针置空
}

2、入栈
void push(linkstack &S,int e)
{
  stacknode p;    //定义变量
  p=new stacknode;//申请变量空间,生成新结点
  p->data=e;    //将数据给新结点
  p->next=S;    //新结点插入栈顶
  S=p;       //修改栈顶指针为p
}

3、出栈
void pop(linkstack &S,int &e) //删除栈顶元素
{
  if(S==NULL) //判断是否栈空
  e=S->data; //栈顶元素数据赋给e
  p=S;    //用p保存栈顶空间,以备释放
  S=S->next;   // 修改栈顶指针
  delete p;      //释放原栈顶空间
}

4、取栈顶元素
int gettop(linkstack &S)
{
  if(S!=NULL)
   return S->data;
}

以上这些代码只是各自的算法,我在打的时候也在思考这一句代码的作用是什么,老师也强调注释的重要性,在这个过程中有时就是找出Bug的关键一步,我在自己做题目的时候或者跟同学讨论时确实感受到注释是检查程序的一个工具。

  我认为我们老师说的很有道理,一个程序的编写,首先要考虑它的逻辑结构,这也是数据结构这门课的关键,其次是算法,最后是存储结构。

比如,我在做PTA上面括号匹配题目时,开始就明确要用线性结构栈,算法我是参考一下课本案例里面,然后用链式存储结构。

二、队列(先进先出:FIFO)

 1、顺序队列(循环队列)

  这种循环队列是为了解决“假溢出”,这是由队列特性:队尾入队,队头出队限制造成的,实现操作一个巧妙方法就是(Q.rear+1)%MAXSIZE==Q.front.

 2、链队

  《银行业务队列简单模拟》那道题,让我对链队有了更深的理解。

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

输入格式:

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

输出格式:

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

输入样例:

8 2 1 3 9 4 11 13 15

输出样例:

1 3 2 9 11 4 13 15
#include<iostream>
using namespace std;

typedef struct qnode  //队列链式存储结构
{
    int data;
    struct qnode *next;
} qnode,*queue;

typedef struct
{
    queue front;//队头和队尾指针
    queue rear;
 } lqueue;

void initqueue(lqueue &q)
{
    q.front=q.rear=new qnode;//生成新结点作为头结点,队头和队尾指向头结点
    q.front->next=NULL;//头结点指针域为空
}

void enqueue(lqueue &q,int e)
{
    qnode *p;//定义结构体指针,并申请变量空间
    p=new qnode;
    p->data=e;//把e存入新结点数据域
    p->next=NULL;q.rear->next=p;//尾指针指针域指向新结点,即插入队尾
    q.rear=p;//将p修改队尾指针
}

void dequeue(lqueue &q)
{

      qnode *p;
        p=q.front->next;//指向队头
        cout<<p->data;//出队
        q.front->next=p->next;    //将头结点指针域指向下一个元素
        if(q.rear==p) q.rear=q.front;//最后一个元素出队,将队尾指针指向头结点

    delete p;//释放p的空间
}

int main()
{
    lqueue P,Q;
    int D;
    initqueue(P);initqueue(Q);//初始化两个链队
    int i,j,k,m=0,n=0;
    cin>>j;
    for(i=0;i<j;i++)
    {
        cin>>D;
        if(D%2)//奇数时入队P
        {
            enqueue(P,D);
            m++;//记录奇数个数
        }
        if(D%2==0)//偶数时入队Q
        {
            enqueue(Q,D);n++;//记录偶数个数
        }

    }

    k=(m/2)>=n?m/2:n;//确定循环输出次数

    for(i=0;i<k;i++)
    {
        if(m>1)//共有三种情况输出
        {
            if(n>0)//P出队2个,Q出队1个
            {
                    if(i!=0)cout<<" ";//第一次打印元素,前面不带空格
                    dequeue(P);cout<<" ";dequeue(P);cout<<" ";dequeue(Q);n--;m-=2;
            }
            if(n<=0)//P出队2个
                {
                    if(i!=0)cout<<" ";
                    dequeue(P);cout<<" ";dequeue(P);m-=2;
                }

        }
        else if(m==1)
        {
            if(n>0)//P出队1个,Q出队1个
            {    if(i!=0)cout<<" ";
                dequeue(P);m--;cout<<" ";dequeue(Q);n--;
            }
            if(n<=0)//P出队1个
                {
                    if(i!=0)cout<<" ";
                    dequeue(P);m--;n--;
                }

        }
        else if(m==0&&n>0)//Q出队
        {    if(i!=0)cout<<" ";
            dequeue(Q);n--;
        }
     } 

    return 0;

} 

这就是我通过许多次debug之后的程序,在处理队列问题时候,我考虑了所有可能出现的情况,程序结构看起来很清晰,我想还有不足之处,可以优化。

在解决这道题目时候,在无数次修正错误,我从中可以明白许多问题,所以多打代码,多尝试、实践,学得会更明白。

上一周也学习到很多,接下来还是要坚持做题目,实践与知识结合,我想这样更加牢固,自己容易犯错误的点也不少,希望在以后学习中能够严谨一些。

原文地址:https://www.cnblogs.com/chenzhenhong/p/10630756.html

时间: 2024-11-07 14:01:16

《数据结构》第3章-栈与队列的学习总结的相关文章

C语言数据结构——第三章 栈和队列

三.栈和队列 栈和队列是两种重要的线性结构.从数据结构的角度来看,栈和队列也是线性表,它的特殊性在于栈和队列的基本操作是线性表操作的子集,它们的操作相对于线性表来说是受到限制的,因此,可以称其为限定性的数据结构. 从数据类型的角度看,它们是和线性表大不相同的两种重要的抽象数据类型,在面向对象的程序设计中,它们是多型数据类型. 3.1-栈 3.1.1-抽象数据类型栈的定义 栈:是限定仅在表尾进行插入或删除操作的线性表,又可以称为后进先出的线性表. 栈顶:栈的表尾端 栈底:栈的表头端 空栈:不含元素

数据结构-王道2017-第3章 栈和队列-栈和队列的应用

1.前中后缀表达式的转换: 举例说明将自然表达式转换成二叉树: a×(b+c)-d ① 根据表达式的优先级顺序,首先计算(b+c),形成二叉树 ②然后是a×(b+c),在写时注意左右的位置关系 ③最后在右边加上 -d 然后最这个构造好的二叉树进行遍历,三种遍历的顺序分别是这样的: ① 前序遍历:根-左-右 ② 中序遍历:左-根-右 ③ 后序遍历:左-右-根 前缀表达式:-*a+bcd 中缀表达式:a*b+c-d 后缀表达式:abc+*d- 2.队列在层次遍历二叉树中起作用,且在计算机系统中应用非

第04章 栈和队列

栈 队列 优先级队列 本章涉及到的三种存储数据类型:栈 队列 优先级队列 本章涉及到的存储数据类型是算法构思的辅助工具,而不仅仅是存储数据的工具.数据结构的生命周期比较短,在程序结束时,对应的数据结构的生命周期随之结束. 栈 队列 优先级队列是比较抽象的数据结构,通过接口对三种数据结构进行定义和实现,而实现的过程对用户来说是屏蔽的. 栈 (后进先出) 栈只允许访问一个数据项,即最后插入的项,当最后一项被移除时,才能对倒数第二项进行操作,依次类推. 栈的操作有两种,入栈和出栈,push  pop.

Java数据结构和算法之栈与队列

二.栈与队列 1.栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底(Bottom). (2)当表中没有元素时称为空栈. (3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表. 栈的修改是按后进先出的原则进行. 每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除. 图1 [示例]元素是以a1,a2,-,a

数据结构实验三《栈和队列》

<数据结构>实验三 栈和队列 一.实验目的 巩固栈和队列数据结构,学会运用栈和队列. 1.回顾栈和队列的逻辑结构和受限操作特点,栈和队列的物理存储结构和常见操作. 2.学习运用栈和队列的知识来解决实际问题. 3.进一步巩固程序调试方法. 4.进一步巩固模板程序设计. 二.实验时间 准备时间为第5周到第6周,具体集中实验时间为6周第2次课.2个学时. 三.实验内容 1.自己选择顺序或链式存储结构,定义一个空栈类,并定义入栈.出栈.取栈元素基本操作.然后在主程序中对给定的N个数据进行验证,输出各个

Java数据结构与算法(第四章栈和队列)

本章涉及的三种数据存储类型:栈.队列和优先级队列. 不同类型的结构 程序员的工具 数组是已经介绍过的数据存储结构,和其他结构(链表.树等等)一样,都适用于数据应用中作数据记录. 然而,本章要讲解的是数据结构和算法更多的是作为程序员的工具来运用.它们组要作为构思算法的辅助工具,而不是完全的数据存储工具.这些数据结构的生命周期比那些数据库类型的结构要短的多.在程序操作执行期间它们才被创建,通常它们去执行某项特殊的任务,当完成之后,它们就被销毁. 受限访问 在数组中,只要知道下标就可以访问数据项.或顺

数据结构期末复习第三章栈和队列

第三章:栈和队列 栈的特性:后进先出(LIFO) 1.  输入序列为ABC,可以变为CBA时,经过的栈操作为( B )A. push, pop, push, pop, push, popB. push, push, push, pop, pop, popC. push, push, pop, pop, push, popD. push, pop, push, push, pop, pop 解析: ABC经过push,push,push操作后,从栈顶到栈底元素为CBA,经过pop,pop,pop出

【知识强化】第三章 栈和队列 3.1 栈

在第三章我们将继续学习三种非常重要的线性结构,分别是栈和队列的这样的受限线性表.我们将从它们的基本概念.存储结构以及相关应用这三方面进行详细的学习.最后我们将学习数组的相关知识,大家要注意一下这里的数组指的是一种线性结构,与我们之前在程序设计语言当中提到的数组类型是不同的概念.好,数组我们会学习它的定义以及它的存储结构,还有用数组来实现矩阵的压缩存储.最后还会提一个特殊的矩阵叫做稀疏矩阵.好,这就是本章所要学习的重要考点.本章所学习的知识点其实并不难,它常常出现在选择题当中,但是在之后我们解决一

用JS描述的数据结构及算法表示——栈和队列(基础版)

前言:找了上课时数据结构的教程来看,但是用的语言是c++,所以具体实现在网上搜大神的博客来看,我看到的大神们的博客都写得特别好,不止讲了最基本的思想和算法实现,更多的是侧重于实例运用,一边看一边在心里隐隐歌颂大神的厉害,然后别人的厉害不是我的,所以到底看得各种受打击+头昏脑涨,写这个系列是希望自己能够总结学到东一块.西一下的知识,因为水平有限+经验不足,所以在此只说最基础的思想,附上我自己的算法实现(肯定还有更优解),如果要想看进阶版的,可以在园里搜“数据结构”,各种语言实现和进阶提升的文章有很