c语言指针解决首尾相接,C语言之队列

本文详细解析了队列的定义、FIFO原则,包括顺序队列的结构、操作及溢出现象,以及链队列的定义、类定义和基本运算。探讨了如何用链表表示链队列,并介绍了循环队列的概念和其实现策略,适用于IT技术人员学习数据结构基础。
摘要由CSDN通过智能技术生成

队列的定义及其运算

1、定义

队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表。

      1ec2e70aab3543e981b3c633193c8121.jpg

(1)允许删除的一端称为队头(Front)。

(2)允许插入的一端称为队尾(Rear)。

(3)当队列中没有元素时称为空队列。

(4)队列亦称作先进先出(First In First Out)的线性表,简称为FIFO表。

具体算法演示请点击查看【算法演示】

队列的结构特点是先进队的元素先出队。假设有队列Q=(a1,a2,...,an),则队列Q中的元素是按a1,a2,...,an的次序进队,而第一个出队的应该是a1,第二个出队的应该是a2,只有在ai-1出队后, ai才可以出队(1≤i≤n),如图3.9所示。

队列的修改是依先进先出的原则进行的。新来的成员总是加入队尾(即不允许"加塞"),每次离开的成员总是队列头上的(不允许中途离队),即当前"最老的"成员离队。

2、队列的基本逻辑运算与栈类似,队列的运算可以归纳为以下几种:

1. AddQ(ElemType x)

——在队列的尾部插入一个新的元素x。队尾的位置由rear指出。

2. DelQ(Q)

——删除队列的队头的元素。队头的位置由front指出。

3. EmptyQ(Q)

——测试队列Q是否为空队。当队列为空时返回一个真值,否则返回一个假值。

4. FrontQ(Q)

——取得队列Q的队头元素。该运算与DelQ(Q)不同,后者要修改队头元素指针。

5. SetNULL(Q)

——创建一个空队Q,这个运算与线性表置空表类似。

顺序队列

(1)顺序队列的定义   队列的顺序存储结构称为顺序队列,队列的顺序存储结构和栈类似,在计算机中,常借助于一维数组来存储队列中的元素,顺序队列实际上是运算受限的顺序表。 (2) 顺序队列的表示

①和顺序表一样,顺序队列用一个向量空间来存放当前队列中的元素。

②由于队列的队头和队尾的位置是变化的,设置两个指针front和rear分别指示队头元素和队尾元素在向量空间中的位置,它们的初值在队列初始化时均应置为0,见图3.12。

队列的顺序存储结构可描述为:

typedef int ElemType;

struct SeQueuestr { ElemType elem[MAXSIZE];

int front,rear;

} ;

(3) 顺序队列的基本操作

①入队时:将新元素插入rear所指的位置,然后将rear加1。

②出队时:删去front所指的元素,然后将front加1并返回被删元素。

注意:

①当头尾指针相等时,队列为空。

②在非空队列里,队头指针始终指向队头元素,尾指针始终指向队尾元素的下一位置。

顺序队列在入队和出队操作时的具体算法演示请点击查看【算法演示】

(4)顺序队列中的溢出现象

① "下溢"现象

当队列为空时,做出队运算产生的溢出现象。“下溢”是正常现象,常用作程序控制转移的条件。

② "真上溢"现象

当队列满时,做进栈运算产生空间溢出的现象。“真上溢”是一种出错状态,应设法避免。

③ "假上溢"现象

由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为"假上溢"现象。

解决“假溢出”的方法有两种:

(1) 采用平移元素的方法,即一旦发生“假溢出”就把整个队列的元素平移到存储区的首部。平移元素的方法效率是很低的。

(2)将整个队列作为循环队列来处理,。这样,虽然物理上队尾在队首之前,但逻辑上队首仍然在前,作插入和删除运算时仍按"先进先出"的原则。

循环队列

为充分利用向量空间,克服"假上溢"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。

       bcafd0e489ce4e249d930a896832041f.jpg

在循环队列中只凭等式rear==front无法判别队空还是队满。因此,可再设置一个布尔变量来区分队空和队满,或者不设布尔变量,而把尾指针加1后等于头指针作为队满的标志。这意味着损失一个空间,或者反过来说,拥有MAXSIZE个数组元素的数组仅能表示一个长度为MAXSIZE-1的循环队列。

循环队列的类定义

循环队列实质上仍然还是顺序存储结构,只是形式上有所改变而已。现在用面向对象的方法来设计循环队列的类。

1.循环队列的类定义:

class SeQueue

{ private:

ElemType elem[MAXSIZE];

int front,rear;

public:

SeQueue();

~SeQueue();

void Display();

void AddQ(ElemType x);

ElemType DelQ();

};

2.下面给出循环队列的运算算法:

(1)将循环队列置为空

//将队列初始化

SeQueue::SeQueue()

{  front=0;

rear=0;

cout<

}

(2)判断循环队列是否为空

int SeQueue::Empty()

{  if(rear==front) return(1);

else return(0);

}

(3)在循环队列中插入新的元素x

void SeQueue::AddQ(ElemType x)

{ if((rear+1) % MAXSIZE==front) cout<

else{ rear=(rear+1) % MAXSIZE;

elem[rear]=x;

cout<

}

}

(4)删除队列中队首元素

ElemType SeQueue::DelQ()

{ if(front==rear)

{ cout<

else{ front=(front+1) % MAXSIZE;

return(elem[front]);

}

}

(5)取队列中的队首元素

ElemType SeQueue::Front()

{  ElemType x;

if(front== rear)

cout<

else x= elem[(front+1)%MAXSIZE];

return (x);

}

链队列

1、 链队列的定义    用链表表示的队列简称为链队列.如图3.16所示。一个链队列显然需要两个指针才能唯一确定,它们分别指示队头和队尾(分别称为头指针和尾指针)。与线性表的单链表一样,为了操作方便起见,我们也给链队列添加了一个头结点,并令头指针指向头结点.由此,空的链队列的判别条件为头指针和尾指针均指向头结点,如图3.17(a)所示。

2、 链队列的类定义

队列采用链表存储结构时,需要两个指针才能唯一确定,它们分别指示队头和队尾(分别称为头指针和尾指针)。同时,我们把头、尾指针作为类的私有成员来处理。链队列的各种操作设计为类的函数成员。

class LsQueue

{  private:

quenode *front, *rear;

public:

LsQueue();

~LsQueue();

void Display();

void AddQ(ElemType x);

ElemType DelQ();

};

3、 链队列的基本运算

(1)判队列是否为空

int LsQueue::Empty()

{

if(front==rear) return(1);

else return(0);

}

(2)在队尾结点之后插入一个元素

void LsQueue::AddQ(ElemType x)       //值为x 的结点入队

{ quenode *s;

s=new quenode;

s->data=x;

s->next=NULL;

rear->next=s;

rear=s;

}

(3)删除队头元素

ElemType LsQueue::DelQ() //出队一个元素

{ ElemType x; quenode *p;

if ( front==rear) {cout<

else { p=front->next;

front->next=p->next;

if(p->next==NULL) rear=front; // 防止尾指针丢失

x=p->data; free(p);

}

return x;

}

(4)取队列首元素

ElemType LsQueue::Front()

{ ElemType x;

NodeType *p;

if(Empty())

cout<

else{

p=front->next;

x=p->data;

return (x);

}

}

链式队列的优点是便于实现存储空间的共享.在同时存在多个队列的情况下,采用链式存崐储结构是比较理想的。

注意:

①和链栈类似,无须考虑判队满的运算及上溢。

②在出队算法中,一般只需修改队头指针。但当原队中只有一个结点时,该结点既是队头也是队尾,故删去此结点时亦需修改尾指针,且删去此结点后队列变空。

③以上讨论的是无头结点链队列的基本运算。和单链表类似,为了简化边界条件的处理,在队头结点前也可附加一个头结点,增加头结点的链队列的基本运算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值