大话数据结构9栈和队列

1、队列的定义:只允许在一端进行插入操作,而另一端进行删除操作的线性表。例如操作系统和客服系统。

  队列是一种先进先出(First In First Out)的线性表,简称FIFO,允许插入的一端称为队尾,允许删除的一端称为队头。front指针指向队列元素,rear指针指向队尾元素的下一个位置。所以当front等于rear时,代表着一个空队列。

2、队列的抽象数据类型:不同于一般的线性表,插入数据只能在队尾进行,删除数据只能在队头进行。

		ADT 队列(Queue)
		Data
			同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。
		Operation
			InitQueue(*Q):初始化操作,建立一个空队列Q。
			DestroyQueue(*Q):若队列Q存在,则销毁它。
			ClearQueue(*Q):将队列Q清空。
			QueueEmpty(Q):若队列Q为空,返回true,否则返回false。
			GetHead(Q,*e):若队列存在且非空,用e返回队列Q的队头元素。
			EnQueue(*Q,e):若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
			DeQueue(*Q,*e):删除队列Q中队头元素,并用e返回其值。
			QueueLength(Q):返回队列Q的元素个数。
		endADT
3、循环队列

队列顺序存储的不足:

入队列操作是将元素加在队尾,不需要移动任何元素,时间复杂度为O(1)。出队列操作需要队列中的所有元素都向前移动,一保证队列的队头不为空,时间复杂度为O(n)。

循环队列的定义:队列的头尾相接的顺序存储结构

在循环队列中,如何判断队列是空还是满?

  1、设置符号标志量flag,当front == rear且flag = 0时队列为空,当front == rear且flag = 1时,队列为满。

  2、当队列空时,条件就是front = rear,当队列满时,条件改为保留一个元素空间,即(rear + 1) % QueueSize == front,通用的计算队列长度公式:(rear - front + QueueSize) % QueueSize

  循环队列的顺序存储结构代码:

		typedef int QElemType;/*QElemType类型根据实际情况而定,这里假设为int*/
		/*循环队列的顺序存储结构*/
		typedef struct
		{
			QelemType data[MAXSIZE];
			int front;    /*头指针*/
			int rear;     /*尾指针,若队列不空,指向列尾元素的下一个位置*/
		}SqQueue;
  循环队列的初始化代码:

/*初始化一个空队列*/

		Status InitQueue(SqQueue *Q)
		{
			Q->front = 0;
			Q->rear = 0;
			return OK;
		}

  循环队列求长度的代码:

/*返回Q的元素个数,即队列的当前长度*/

		int QueueLength(SqQueue Q)
		{
			return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
		}
  循环队列的入队列操作代码:

/*若队列未满,则插入元素e为Q新的队尾元素*/

		Status EnQueue(SqQueue *Q,QelemType e)
		{
			if((Q->rear + 1) % MAXSIZE == Q->front)  /*队列满的判断*/
				return ERROR;
			Q->data[Q->rear] = e;    /*将元素e赋值给队尾*/
			Q->rear = (Q->rear + 1) % MAXSIZE;   /*rear指针向后一位置*/
							    /*若到最后则转到数组头部*/
			return OK;
		}

  循环队列的出队列操作代码:

		/*若队列不空,则删除Q中队头元素,用e返回其值*/
		Status DeQueue(SqQueue *Q,QElemType *e)
		{
			if(Q->front == Q->rear)      /*队列空的判断*/
				return ERROR;
			*e = Q->data[Q->front];      /*将队头元素赋值给e*/
			Q->front = (Q->front + 1) % MAXSIZE; /*front指向向后移一位置*/
							   /*若到最后则转到数组头部*/
			return OK;
		}

  循环队列面临着数组溢出的问题,所以就有不用担心队列长度的链式存储结构。

4、队列的链式存储结构及实现

  队列的链式存储结构定义:就是线性表的单链表,只不过只能尾进头出。

  链队列的结构:

		typedef int QElemType;  /*QElemType类型根据实际情况而定,这里假设为int*/
		typedef struct QNode /*结点结构*/
		{
			QElemType data;
			struct QNode *next;
		}Qnode,*QueuePtr;
		
		typedef struct            /*队列的链表结构*/
		{
			QueuePtr front,rear;  /*队头、队尾指针*/
		}LinkQueue;
  队列的链式存储结构的入队操作:

		/*插入元素e为Q的新的队尾元素*/
		Status EnQueue(LinkQueue *Q,QElemType e)
		{
			QueuePtr s = (QueuePtr)malloc(sizeof(QNode));
			if(!s)       /*存储分配失败*/
				exit(OVERFLOW);
			s->data = e;
			s->next = NULL;
			Q->rear->next = s;    /*把拥有元素e新结点s赋值给原队尾结点的后缀*/
			Q->rear = s;        /*把当前的s设置为队尾结点,rear指向s*/
			return OK;
		}

  队列的链式存储结构的出队操作:将头结点的后缀结点出队,再将头结点的后缀改为其后面的结点,若链表除头结点外只剩下一个元素时,则需要将rear指向头结点。

		/*若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR*/
		Status DeQueue(LinkQueue *Q,QELemType *e)
		{
			QueuePtr p;
			if(Q->front == Q->rear)
				return ERROR;
			p = Q->front->next;  /*将欲删除的队头结点暂存给p*/
			*e = p->data;      /*将欲删除的队头结点的值赋值给e*/
			Q->front->next = p->next;  /*将原队头结点后继p->next赋值给头结点后继*/
			if(Q->rear == p)   /*若队头是队尾,则删除后将rear指向头结点*/
				Q->rear = Q->front;
			free(p);
			return OK;
		}




 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值