对列,很好懂!

​哈喽!小伙伴们,大家好!

今天还是咱们的数据额结构,队列。队列也是受限定的线性表,不过它是限制只能在表的一端进行插入,在表的另一端进行删除的线性表。  之所叫它队列,就是因为它最大的特点就是“先进先出”,就像排队一样,来得早了就站在前面,先轮到你。

    队尾(rear)——允许插入的一端

    队头(front)——允许删除的一端

  

送道题帮你理解队列

请听题:

        一个队列的入列顺序是1,2,3,4,则队列的输出系列是   (② )

                  ① 4,3,2,1        ② 1,2,3,4     

                  ③1,4,3,2         ④ 3,2,4,1

解答:很好理解嘛,队列是先进先出的。入队顺序是1,2,3,4那么出队顺序也是1,2,3,4啦。

链队列

结点定义

typedef   struct QNode {          QElemType     data;      struct QNode  *next;}*QueuePtr;

队列的定义

struct LinkQueue{    QueuePtr  front;//队头指针      QueuePtr  rear;//队尾指针 } ;

空队列

初始化

void InitQueue ( LinkQueue *Q ) {       Q.rear= Q.front=(QueuePtr)malloc(sizeof(QNode));       if(!Q.front)exit(OVERFLOW);        Q.front->next=NULL;       return OK;   }

链队列的主要操作

判断队列是否为空 

int QueueEmpty ( LinkQueue *Q ){         return Q.front->next == NULL; }

取队头元素

int GetFront ( LinkQueue *Q, QueueData &x ) {    if ( QueueEmpty (Q) ) return 0;    x = Q.front->next->data;   return 1;    }

入队

 

int EnQueue ( LinkQueue *Q, QueueData x ) {          QueueNode *p = ( QueueNode * ) malloc( sizeof ( QueueNode ) );        if(!p) exit(OVERFLOW);         p->data = x;           p->next = NULL;         Q->rear->next=p;         Q->rear =p; }

出队

int DeQueue ( LinkQueue *Q, QueueData &e) { //删去队头结点,并返回队头元素的值      if ( QueueEmpty (Q) ) return 0;  //判队空       QueueNode *p = Q.front->next;     e = p->data;  //保存队头的值    Q.front->next= p->next;   //新队头    if(Q.rear==p) //队列被删除之后为空       Q.rear=Q.front;    free (p);   return 1;    }

循环队列 

顺序队列是用一组地址连续的存储单元依次存放从队列头到队列尾的元素,

指针front和rear分别指示队头元素和队尾元素下一个的位置。

插入新的队尾元素,尾指针增1,rear = rear + 1,

删除队头元素,头指针增1, front = front + 1,

因此,在非空队列中,头指针始终指向队列头元素,而尾指针始终指向队列尾元素的下一个位置。

 

存在一个问题?

队列的进队和出队

 

存在的问题

    设数组长度为M,则:

    当front=0,rear=M时,再有元素入队发生溢出——真溢出

    当front0,rear=M时,再有元素入队发生溢出——假溢出

 

解决方案

    队首固定,每次出队剩余元素向下移动——浪费时间

循环队列的基本思想:把队列设想成环形,让sq[0]接在sq[M-1]之后,若rear+1==M,则令rear=0;

 

新的问题

    队空用front == rear;判断

    队满时front==rear;

    出现矛盾。

解决方案

    1.另外设一个标志以区别队空、队满

    2.少用一个元素空间:

        队空:front==rear

        队满:(rear+1)%M==front

 

少用一个元素空间:

    队空:front==rear

    队满:(rear+1)%M==front

循环队列 特点:

         队头、队尾指针加1,可用取模(余数)运算实现。    

        队头指针进1(出队):  front = (front+1) %M; 

        队尾指针进1(入队):  rear = (rear+1) % M;

        队列初始化:front = rear = 0;

        队空条件:front == rear;

        队满条件:(rear+1) % M == front; 

循环队列的类型定义

#define MAXSIZE 100struct SqQueue{       QueueType *base;    int front;    int rear; };

初始化队列

void InitQueue ( SqQueue *Q ){//构造空队列   Q.base=(QElemType *)malloc(MAXSIZE *sizeof(QElemType));   if(! Q.base)exit(OVERFLOW);    Q->rear = Q->front = 0;   return OK; }

判队空

int QueueEmpty ( SeqQueue *Q ) {         return Q->rear == Q->front;  }

判队满

int QueueFull ( SeqQueue *Q ) {        return (Q->rear+1) % QueueSize == Q->front; }

 

入队

int EnQueue ( SeqQueue *Q, QueueData e ) {         if ( QueueFull (Q) ) return 0;        Q.base[Q->rear] = e;      Q->rear = ( Q->rear+1) % MAXSIZE;      return 1;  }

 

出队

int DeQueue ( SeqQueue *Q, QueueData &x ){          if ( QueueEmpty (Q) ) return 0;      x = Q.base[Q->front];      Q->front = ( Q->front+1) % MAXSIZE;       return 1;  }
取队头int GetFront ( SeqQueue *Q, QueueData &x ) {           if ( QueueEmpty (Q) ) return 0;       x = Q.base[Q->front];       return 1;  }
好啦,小伙伴们!今天的分享就到这里,你们学会了吗?如果有什么问题可以在微信公众号私信给我,明天见喽!
### 回答1: EXPLAIN命令是PostgreSQL中用于分析SQL语句执行计划的命令。它会显示系统如何执行你的SQL语句的步骤,并且可以帮助你了解系统如何执行SQL语句以及哪些步骤可能导致性能问题。 在查看EXPLAIN的输出时,你需要注意以下几点: - 输出的每一行代表一个操作,例如扫描表、连接表或使用索引。 - 输出中有几列是特别重要的: - "Node Type"列显示每个操作的类型,例如扫描表、连接表或使用索引。 - "Actual Rows"列显示每个操作处理的行数。如果这一数字很大,可能意味着系统处理了很多无用数据,这可能导致性能问题。 - "Actual Time"列显示每个操作执行的时间,这可以帮助你了解哪些操作花费了更多时间。 通常,你希望看到"Actual Rows"和"Actual Time"较小,这意味着系统处理的数据量较少,并且执行较快。如果看到这些数字很大,则可能需要调整SQL语句或者建立索引来优化性能。 总的来说,查看EXPLAIN的输出需要一定的SQL知识,但是如果你了解了上面提 ### 回答2: 当我们在 PostgreSQL 中使用 EXPLAIN 命令来分析一条 SQL 查询语句时,其结果会提供有关查询执行计划的详细信息。理解 EXPLAIN 结果对于优化查询性能至关重要。 首先,我们需要注意的是 EXPLAIN 结果是按照树形结构显示的。对于一个查询,每个节点代表一个执行计划中的操作。从根节点到叶节点,每个节点都有自己的属性和信息。 首先,我们应该关注的是根节点的计划属性,如计划类型(例如Seq Scan,Index Scan等),它决定了查询的执行方式。下一个得关注的是执行时间,当然我们更希望执行时间越短越好。还可以查看开始行和结束行属性,用于确定查询结果集的范围。 接下来,我们可以关注子节点的详细属性。这些属性可能因操作类型而异,例如 Seq Scan 操作会显示表名和顺序扫描的行数。对于 Join操作,我们可以看到连接的方式(如 Nested Loop Join、Hash Join、Merge Join等)。 对于每个节点,我们可以查看其成本估计和实际成本。估计成本是基于统计信息和规划选项进行估算,实际成本是实际执行时的结果。比较这两个成本能够帮助我们判断查询执行的效率。 关注计划属性的顺序也是很重要的。如果一个操作是在处理海量数据之前执行的,它可能会造成查询效率的低下。因此,在分析查询计划时要特别关注操作的顺序。 最后,我们还可以使用 EXPLAIN ANALYZE 命令来获得更详细的执行信息,包括实际执行的时间和资源使用情况。这可以帮助我们更精确地判断查询的性能瓶颈所在。 总而言之,理解 PostgreSQL 的 EXPLAIN 结果对于优化查询非常重要。通过仔细观察节点、属性和成本估计等信息,我们可以确定查询执行的方式和效率,并做出相应的调整以提高性能。 ### 回答3: 要理解PostgreSQL的explain结果,您可以按照以下步骤进行: 1. 首先,需要了解explain结果的基本结构。explain以一棵树的形式显示查询的执行计划。每个节点代表一个操作,如扫描表、连接操作等。节点之间以树状结构连接,故意味着节点之间存在关系。 2. 查询计划通常按照树的先序遍历方式展示。您可以通过查看节点的顺序和包含关系来了解查询的执行顺序。 3. 对于每个节点,可以查看其输出的行数、过滤条件、排序方式和访问方式等信息。这些信息将帮助您判断查询性能和优化策略。 4. 节点之间的箭头表示数据的流向。您可以根据箭头的指向,了解查询的连接方式和关系。 5. 关注执行计划中的成本估算。通常,计划节点上列出了该操作的成本估算,包括内部成本和总成本。较高的成本可能表示该操作比较耗时。 6. 查看执行计划中的索引信息,了解哪些索引被使用。如果涉及到大量数据的扫描而没有使用任何索引,可能需要优化查询或添加合适的索引。 7. 注意执行计划中的磁盘访问,如是否有磁盘排序或磁盘临时文件。过多的磁盘访问可能导致较长的执行时间,需要优化查询或调整数据库配置。 总而言之,了解PostgreSQL的explain结果需要一定的经验和背景知识。通过分析每个节点的信息、关系和成本估算,您可以更好地理解查询的执行过程和性能瓶颈,从而进行性能优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值