c语言 队列定义.顺序队列,循环队列,链队列结构(详细的)

1.顺序队列的常用基本操作及条件判断

队空:    Q.front=Q.rear
 队满:    Q.rear=Maxlen
 求队长:  Q.rear-Q.front

入队: 1)新元素按 rear 指示位置加入
2)rear = rear + 1队尾指针加一
出队: 1)将front指示的元素取出。
2)front = front + 1队头指针加一
2.顺序队列的类型定义

#define MAXLEN 100
   typedef struct
    	{datatype  Q[MAXLEN];
    	  int front=0;
    	  int rear=0;
        } SeqQueue,*P;

问:什么叫“假溢出” ?如何解决?
答:在顺序队中,当尾指针已经到了数组的上界,不能再有入队操作,但其实数组中还有空位置,这就叫“假溢出”。
解决假溢出的途径———采用循环列队

循环队列

想象为一个首尾相接的圆环,并称这种向量为循环向量,存储在其中的队列称为循环队列。在这里插入图片描述

新问题:在循环队列中,空队特征是Q.front=Q.rear;队满时也会有Q.front=Q.rear;判决条件将出现二义性!
解决方案有三:
①使用一个计数器记录队列中元素个数(即队列长度);
②加设标志位,删除时置1,插入时置0,则可识别当前Q.front=Q.rear属于何种情况
③ 人为浪费一个单元,则队满特征可改为Q.front=(Q.rear+1)%MAXLEN;

实际中常选用方案3(人为浪费一个单元):
即front和rear二者之一指向实元素,另一个指向空闲元素。

队空条件 :  Q.front =Q. rear       (初始化时:Q.front = Q.rear )
队满条件: Q.front = (Q.rear+1) % N         (N=maxsize)
队列长度(即数据元素个数):L=(N+Q.rear-Q.front)% N
 

在这里插入图片描述
例1:数组Q[n]用来表示一个循环队列,f 为当前队列头元素的前一位置,r 为队尾元素的位置。假定队列中元素的个数小于n,计算队列中元素的公式为:
A) r-f (B)(n+f-r)% n
(C)n+r-f (D) (n+r-f)% n
要分析4种公式哪种最合理?
当 r ≥f 时(A)合理;
当 r < f 时(C)合理; 综合2种情况,以(D)的表达最为合理
例2:在一个循环队列中,若约定队首指针指向队首元素的前一个位置。那么,从循环队列中删除一个元素时,其操作是 先 移动队首指针,后取出元素
在这里插入图片描述
在这里插入图片描述

怎样构成循环队列?
在循环队列中进行出队、入队操作时,头尾指针仍要加1,朝前移动。
只不过当头尾指针指向向量上界(MAXLEN-1)时,其加1操作的结果是指向向量的下界0。
加1操作的结是指向向量的下界0的办法

*(front+1)%M       (rear+1)%M*

在这里插入图片描述

队空:Q.front =Q. rear
队满:Q.front =(Q.rear + 1) % MAXLEN
入队: Q.rear = (Q.rear + 1) % MAXLEN
出队: Q.front = (front + 1) % MAXLEN;
求队长:(Q.rear-Q.front+ MAXLEN)% MAXLEN

- 3)循环队列的类型定义

#define MAXLEN 100
typedef struct
	{datatype *data[MAXLEN];
	  int front;
	  int rear;
     int n;/*判队空,队满的另一方法*/
   } CseqQueue

- 4)循环队列操作的实现

①初始化队列

CseqQueue * IniQueue (CseqQueue *Q) 
{                                                    //构造空队列
  Q= (CseqQueue *) malloc(sizeof(CseqQueue ));
  Q->rear = Q->front = 0;
  return Q;
}

在这里插入图片描述
②判队空

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

③判队满

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

④判队满

int QueueFull (CseqQueue *Q ) 
{
    return( (Q->n) == MAXLEN);
}

⑤入队

int InQueue (CseqQueue *Q, datatype x ) 
{
    if (QueueFull (Q) ) 
          return 0;
   else 
      {Q->data[Q->rear] = x; 
        Q->rear = ( Q->rear+1) % MAXLEN; 
        Q->n++;
        return 1;
      }
 }

⑥出队

int DeQueue (CseqQueue *Q, datatype *x ) 
{
    if ( QueueEmpty (Q) ) 
        return 0;
   else
       {*x = Q->data[Q->front]; 
         Q->front = ( Q->front+1) % MAXLEN; 
         Q->n--;
         return 1;
      }
}

⑦取队头

int GetFront (CseqQueue *Q, datatype *x ) 
{
     if ( QueueEmpty (Q) )
          return 0;
     *x = Q->data[Q->front];
     return 1;
}

⑧求队列长度

int QueueLength (CseqQueue  *Q)
{
  return( (Q->rear – Q->front + MAXSIZE) % MAXSIZE);
}

链队列结构

(1)链队列结构**
链队列示意图在这里插入图片描述
(2)链队列的描述
和顺序队列类似,我们也是将这两个指针封装在一起,将链队列的类型LinkQueue定义为一个结构类型:

typedef struct queuenode
      { datatype  data;
         struct queuenode *next;
       }queuenode;
   typedef struct
      {  queuenode  *front;
          queuenode  *rear;
       }Linkqueue;

3)链队列上实现的基本运算
1)构造一个空队列(带头结点空队列)

  void initqueue(Linkqueue  *q)
     { q.front=(queuenode *)malloc(sizeof(queuenode));
       q.rear=q.front
       q.front->next=q.rear->next= NULL;
     }

在这里插入图片描述
2)入队操作
在这里插入图片描述
入队操作算法

void inqueue(Linkqueue  *q,datatype  x)
     {queuenode *p
      p=(queuenode * )malloc(sizeof(queuenode));
      p–>data=x;
      p–>next=NULL;
      q.rear–>next=p;
      q.rear=p;
     }

3)队列的判空

int queueempty(Linkqueue  *q)
    {
      return (q.front->next= =NULL &&
                  q.rear->next= =NULL);
     }
  1. 出队操作在这里插入图片描述
    4)出队操作算法

Datatype dequeue(Linkqueue *q)
{ datatype x;
queuenode *p
if(queueempty(q))
{ printf(“队列为空”); return;}
p=q.front–>next;
x=p–>data;
q.front–>next=p–>next;
if(q.rear = =p) /删除的是尾结点/
q.rear=q.front;
free§;
return x;
}

有什么问题请留言 会及时修改的

发布了10 篇原创文章 · 获赞 12 · 访问量 1856

猜你喜欢

转载自blog.csdn.net/qq_44236958/article/details/89167223